diff --git a/.hgignore b/.hgignore index d5b25104e..c19d9d91a 100644 --- a/.hgignore +++ b/.hgignore @@ -1,9 +1,10 @@ -.*.orig$ -.*\.o$ -.*~$ -build-dir -build -.*\.sconsign -doc/html.* -doc/latex.* -.lock-wscript +\.rej$ +\.orig$ +\.o$ +~$ +^build-dir +^build +^doc/html +^doc/latex +^\.lock-wscript +^\.waf diff --git a/changeset.txt b/changeset.txt deleted file mode 100644 index 837107a48..000000000 --- a/changeset.txt +++ /dev/null @@ -1,12278 +0,0 @@ -searching for changes -changeset: 1278:a8f3d01d4a2c -user: Craig Dowell -date: Sun Aug 12 13:59:49 2007 -0700 -summary: untested multicast support - -diff -r c26bf0511078 -r a8f3d01d4a2c examples/csma-multicast.cc ---- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/examples/csma-multicast.cc Sun Aug 12 13:59:49 2007 -0700 -@@ -0,0 +1,173 @@ -+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ -+/* -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation; -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+// Network topology -+// -+// n0 n1 n2 n3 -+// | | | | -+// ===================== -+// -+// - CBR/UDP flows from n0 to n1, and from n3 to n0 -+// - UDP packet size of 210 bytes, with per-packet interval 0.00375 sec. -+// (i.e., DataRate of 448,000 bps) -+// - DropTail queues -+// - Tracing of queues and packet receptions to file "csma-one-subnet.tr" -+ -+#include -+#include -+#include -+#include -+ -+#include "ns3/command-line.h" -+#include "ns3/default-value.h" -+#include "ns3/ptr.h" -+#include "ns3/random-variable.h" -+#include "ns3/debug.h" -+ -+#include "ns3/simulator.h" -+#include "ns3/nstime.h" -+#include "ns3/data-rate.h" -+ -+#include "ns3/ascii-trace.h" -+#include "ns3/pcap-trace.h" -+#include "ns3/internet-node.h" -+#include "ns3/csma-channel.h" -+#include "ns3/csma-net-device.h" -+#include "ns3/csma-topology.h" -+#include "ns3/csma-ipv4-topology.h" -+#include "ns3/eui48-address.h" -+#include "ns3/ipv4-address.h" -+#include "ns3/inet-socket-address.h" -+#include "ns3/ipv4.h" -+#include "ns3/socket.h" -+#include "ns3/ipv4-route.h" -+#include "ns3/onoff-application.h" -+ -+using namespace ns3; -+ -+int -+main (int argc, char *argv[]) -+{ -+ // Users may find it convenient to turn on explicit debugging -+ // for selected modules; the below lines suggest how to do this -+#if 0 -+ DebugComponentEnable("CsmaNetDevice"); -+ DebugComponentEnable("Ipv4L3Protocol"); -+ DebugComponentEnable("NetDevice"); -+ DebugComponentEnable("Channel"); -+ DebugComponentEnable("CsmaChannel"); -+ DebugComponentEnable("PacketSocket"); -+#endif -+ -+ // Set up some default values for the simulation. Use the Bind() -+ // technique to tell the system what subclass of Queue to use, -+ // and what the queue limit is -+ -+ // The below Bind command tells the queue factory which class to -+ // instantiate, when the queue factory is invoked in the topology code -+ DefaultValue::Bind ("Queue", "DropTailQueue"); -+ -+ // Allow the user to override any of the defaults and the above -+ // Bind()s at run-time, via command-line arguments -+ CommandLine::Parse (argc, argv); -+ -+ // Here, we will explicitly create four nodes. In more sophisticated -+ // topologies, we could configure a node factory. -+ Ptr n0 = Create (); -+ Ptr n1 = Create (); -+ Ptr n2 = Create (); -+ Ptr n3 = Create (); -+ -+ // We create the channels first without any IP addressing information -+ Ptr channel0 = -+ CsmaTopology::CreateCsmaChannel( -+ DataRate(5000000), MilliSeconds(2)); -+ -+ uint32_t n0ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n0, channel0, -+ Eui48Address("10:54:23:54:23:50")); -+ uint32_t n1ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n1, channel0, -+ Eui48Address("10:54:23:54:23:51")); -+ uint32_t n2ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n2, channel0, -+ Eui48Address("10:54:23:54:23:52")); -+ uint32_t n3ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n3, channel0, -+ Eui48Address("10:54:23:54:23:53")); -+ -+ // Later, we add IP addresses. -+ CsmaIpv4Topology::AddIpv4Address ( -+ n0, n0ifIndex, Ipv4Address("10.1.1.1"), Ipv4Mask("255.255.255.0")); -+ -+ CsmaIpv4Topology::AddIpv4Address ( -+ n1, n1ifIndex, Ipv4Address("10.1.1.2"), Ipv4Mask("255.255.255.0")); -+ -+ CsmaIpv4Topology::AddIpv4Address ( -+ n2, n2ifIndex, Ipv4Address("10.1.1.3"), Ipv4Mask("255.255.255.0")); -+ -+ CsmaIpv4Topology::AddIpv4Address ( -+ n3, n3ifIndex, Ipv4Address("10.1.1.4"), Ipv4Mask("255.255.255.0")); -+ -+ // Configure multicasting -+ Ipv4Address multicastSource ("10.1.1.1"); -+ Ipv4Address multicastGroup ("225.0.0.0"); -+ -+ Ptr ipv4; -+ ipv4 = n0->QueryInterface (Ipv4::iid); -+ -+ std::vector outputInterfaces (1); -+ outputInterfaces[0] = n0ifIndex; -+ -+ ipv4->AddMulticastRoute (multicastSource, multicastGroup, 0, -+ outputInterfaces); -+ -+ ipv4 = n1->QueryInterface (Ipv4::iid); -+ ipv4->JoinMulticastGroup (multicastSource, multicastGroup); -+ -+ ipv4 = n2->QueryInterface (Ipv4::iid); -+ ipv4->JoinMulticastGroup (multicastSource, multicastGroup); -+ -+ ipv4 = n3->QueryInterface (Ipv4::iid); -+ ipv4->JoinMulticastGroup (multicastSource, multicastGroup); -+ -+ // Create the OnOff application to send UDP datagrams of size -+ // 210 bytes at a rate of 448 Kb/s -+ // from n0 to n1 -+ Ptr ooff = Create ( -+ n0, -+ InetSocketAddress (multicastGroup, 80), -+ "Udp", -+ ConstantVariable(1), -+ ConstantVariable(0)); -+ // Start the application -+ ooff->Start(Seconds(1.0)); -+ ooff->Stop (Seconds(10.0)); -+ -+ // Configure tracing of all enqueue, dequeue, and NetDevice receive events -+ // Trace output will be sent to the csma-one-subnet.tr file -+ AsciiTrace asciitrace ("csma-one-subnet.tr"); -+ asciitrace.TraceAllNetDeviceRx (); -+ asciitrace.TraceAllQueues (); -+ -+ // Also configure some tcpdump traces; each interface will be traced -+ // The output files will be named -+ // simple-point-to-point.pcap-- -+ // and can be read by the "tcpdump -r" command (use "-tt" option to -+ // display timestamps correctly) -+ PcapTrace pcaptrace ("csma-one-subnet.pcap"); -+ pcaptrace.TraceAllIp (); -+ -+ Simulator::Run (); -+ -+ Simulator::Destroy (); -+} -diff -r c26bf0511078 -r a8f3d01d4a2c examples/wscript ---- a/examples/wscript Fri Aug 10 13:49:41 2007 -0700 -+++ b/examples/wscript Sun Aug 12 13:59:49 2007 -0700 -@@ -17,3 +17,8 @@ def build(bld): - obj = bld.create_ns3_program('csma-packet-socket', - ['csma', 'internet-node']) - obj.source = 'csma-packet-socket.cc' -+ -+ obj = bld.create_ns3_program('csma-multicast', -+ ['csma', 'internet-node']) -+ obj.source = 'csma-multicast.cc' -+ -diff -r c26bf0511078 -r a8f3d01d4a2c src/internet-node/ipv4-impl.cc ---- a/src/internet-node/ipv4-impl.cc Fri Aug 10 13:49:41 2007 -0700 -+++ b/src/internet-node/ipv4-impl.cc Sun Aug 12 13:59:49 2007 -0700 -@@ -95,6 +95,42 @@ Ipv4Impl::RemoveRoute (uint32_t i) - { - return m_ipv4->RemoveRoute (i); - } -+ -+void -+Ipv4Impl::AddMulticastRoute (Ipv4Address origin, -+ Ipv4Address group, -+ uint32_t inputInterface, -+ std::vector outputInterfaces) -+{ -+ m_ipv4->AddMulticastRoute (origin, group, inputInterface, outputInterfaces); -+} -+ -+uint32_t -+Ipv4Impl::GetNMulticastRoutes (void) const -+{ -+ return m_ipv4->GetNMulticastRoutes (); -+} -+ -+Ipv4MulticastRoute -+Ipv4Impl::GetMulticastRoute (uint32_t i) const -+{ -+ return *m_ipv4->GetMulticastRoute (i); -+} -+ -+void -+Ipv4Impl::RemoveMulticastRoute (Ipv4Address origin, -+ Ipv4Address group, -+ uint32_t inputInterface) -+{ -+ m_ipv4->RemoveMulticastRoute (origin, group, inputInterface); -+} -+ -+void -+Ipv4Impl::RemoveMulticastRoute (uint32_t i) -+{ -+ return m_ipv4->RemoveMulticastRoute (i); -+} -+ - uint32_t - Ipv4Impl::AddInterface (Ptr device) - { -@@ -112,6 +148,18 @@ Ipv4Impl::GetNetDevice (uint32_t i) - } - - void -+Ipv4Impl::JoinMulticastGroup (Ipv4Address origin, Ipv4Address group) -+{ -+ m_ipv4->JoinMulticastGroup(origin, group); -+} -+ -+void -+Ipv4Impl::LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group) -+{ -+ m_ipv4->LeaveMulticastGroup(origin, group); -+} -+ -+void - Ipv4Impl::SetAddress (uint32_t i, Ipv4Address address) - { - m_ipv4->SetAddress (i, address); -diff -r c26bf0511078 -r a8f3d01d4a2c src/internet-node/ipv4-impl.h ---- a/src/internet-node/ipv4-impl.h Fri Aug 10 13:49:41 2007 -0700 -+++ b/src/internet-node/ipv4-impl.h Sun Aug 12 13:59:49 2007 -0700 -@@ -55,9 +55,27 @@ public: - virtual uint32_t GetNRoutes (void); - virtual Ipv4Route GetRoute (uint32_t i); - virtual void RemoveRoute (uint32_t i); -+ -+ -+ virtual void AddMulticastRoute (Ipv4Address origin, -+ Ipv4Address group, -+ uint32_t inputInterface, -+ std::vector outputInterfaces); -+ -+ virtual uint32_t GetNMulticastRoutes (void) const; -+ virtual Ipv4MulticastRoute GetMulticastRoute (uint32_t i) const; -+ -+ virtual void RemoveMulticastRoute (Ipv4Address origin, -+ Ipv4Address group, -+ uint32_t inputInterface); -+ virtual void RemoveMulticastRoute (uint32_t i); -+ - virtual uint32_t AddInterface (Ptr device); - virtual uint32_t GetNInterfaces (void); - virtual Ptr GetNetDevice(uint32_t i); -+ -+ virtual void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group); -+ virtual void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group); - - virtual void SetAddress (uint32_t i, Ipv4Address address); - virtual void SetNetworkMask (uint32_t i, Ipv4Mask mask); -diff -r c26bf0511078 -r a8f3d01d4a2c src/internet-node/ipv4-l3-protocol.cc ---- a/src/internet-node/ipv4-l3-protocol.cc Fri Aug 10 13:49:41 2007 -0700 -+++ b/src/internet-node/ipv4-l3-protocol.cc Sun Aug 12 13:59:49 2007 -0700 -@@ -17,6 +17,7 @@ - // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - // - // Author: George F. Riley -+// Craig Dowell - // - - #include "ns3/packet.h" -@@ -131,7 +132,8 @@ void - void - Ipv4L3Protocol::DoDispose (void) - { -- for (Ipv4InterfaceList::iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++) -+ for (Ipv4InterfaceList::iterator i = m_interfaces.begin (); -+ i != m_interfaces.end (); i++) - { - delete (*i); - } -@@ -224,12 +226,15 @@ Ipv4L3Protocol::Lookup (Ipv4Header const - Packet packet, - Ipv4RoutingProtocol::RouteReplyCallback routeReply) - { -- for (Ipv4RoutingProtocolList::const_iterator rprotoIter = m_routingProtocols.begin (); -- rprotoIter != m_routingProtocols.end (); rprotoIter++) -+ for (Ipv4RoutingProtocolList::const_iterator rprotoIter = -+ m_routingProtocols.begin (); -+ rprotoIter != m_routingProtocols.end (); -+ rprotoIter++) - { - if ((*rprotoIter).second->RequestRoute (ipHeader, packet, routeReply)) - return; - } -+ - // No route found - routeReply (false, Ipv4Route (), packet, ipHeader); - } -@@ -261,6 +266,41 @@ Ipv4L3Protocol::RemoveRoute (uint32_t in - m_staticRouting->RemoveRoute (index); - } - -+void -+Ipv4L3Protocol::AddMulticastRoute (Ipv4Address origin, -+ Ipv4Address group, -+ uint32_t inputInterface, -+ std::vector outputInterfaces) -+{ -+ m_staticRouting->AddMulticastRoute (origin, group, inputInterface, -+ outputInterfaces); -+} -+ -+uint32_t -+Ipv4L3Protocol::GetNMulticastRoutes (void) const -+{ -+ return m_staticRouting->GetNMulticastRoutes (); -+} -+ -+Ipv4MulticastRoute * -+Ipv4L3Protocol::GetMulticastRoute (uint32_t index) const -+{ -+ return m_staticRouting->GetMulticastRoute (index); -+} -+ -+void -+Ipv4L3Protocol::RemoveMulticastRoute (Ipv4Address origin, -+ Ipv4Address group, -+ uint32_t inputInterface) -+{ -+ m_staticRouting->RemoveMulticastRoute (origin, group, inputInterface); -+} -+ -+void -+Ipv4L3Protocol::RemoveMulticastRoute (uint32_t index) -+{ -+ m_staticRouting->RemoveMulticastRoute (index); -+} - - uint32_t - Ipv4L3Protocol::AddInterface (Ptr device) -@@ -463,12 +503,28 @@ Ipv4L3Protocol::Forwarding (Packet const - } - ipHeader.SetTtl (ipHeader.GetTtl () - 1); - -- NS_DEBUG ("not for me -- forwarding."); -+ NS_DEBUG ("forwarding."); - Lookup (ipHeader, packet, - MakeCallback (&Ipv4L3Protocol::SendRealOut, this)); -+// -+// If this is a to a multicast address and this node is a member of the -+// indicated group we need to return false so the multicast is forwarded up. -+// Note that we may have just forwarded this packet too. -+// -+ for (Ipv4MulticastGroupList::const_iterator i = m_multicastGroups.begin (); -+ i != m_multicastGroups.end (); i++) -+ { -+ if ((*i).first.IsEqual (ipHeader.GetSource ()) && -+ (*i).second.IsEqual (ipHeader.GetDestination ())) -+ { -+ NS_DEBUG ("for me 5"); -+ return false; -+ } -+ } -+ -+ NS_DEBUG ("not for me."); - return true; - } -- - - void - Ipv4L3Protocol::ForwardUp (Packet p, Ipv4Header const&ip) -@@ -476,6 +532,28 @@ Ipv4L3Protocol::ForwardUp (Packet p, Ipv - Ptr demux = m_node->QueryInterface (Ipv4L4Demux::iid); - Ptr protocol = demux->GetProtocol (ip.GetProtocol ()); - protocol->Receive (p, ip.GetSource (), ip.GetDestination ()); -+} -+ -+void -+Ipv4L3Protocol::JoinMulticastGroup (Ipv4Address origin, Ipv4Address group) -+{ -+ m_multicastGroups.push_back( -+ std::pair (origin, group)); -+} -+ -+void -+Ipv4L3Protocol::LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group) -+{ -+ for (Ipv4MulticastGroupList::iterator i = m_multicastGroups.begin (); -+ i != m_multicastGroups.end (); -+ i++) -+ { -+ if ((*i).first.IsEqual(origin) && (*i).second.IsEqual(group)) -+ { -+ m_multicastGroups.erase (i); -+ return; -+ } -+ } - } - - void -diff -r c26bf0511078 -r a8f3d01d4a2c src/internet-node/ipv4-l3-protocol.h ---- a/src/internet-node/ipv4-l3-protocol.h Fri Aug 10 13:49:41 2007 -0700 -+++ b/src/internet-node/ipv4-l3-protocol.h Sun Aug 12 13:59:49 2007 -0700 -@@ -158,11 +158,26 @@ public: - Ipv4Route *GetRoute (uint32_t i); - void RemoveRoute (uint32_t i); - -+ void AddMulticastRoute (Ipv4Address origin, -+ Ipv4Address group, -+ uint32_t inputInterface, -+ std::vector outputInterfaces); -+ -+ uint32_t GetNMulticastRoutes (void) const; -+ Ipv4MulticastRoute *GetMulticastRoute (uint32_t i) const; -+ -+ void RemoveMulticastRoute (Ipv4Address origin, -+ Ipv4Address group, -+ uint32_t inputInterface); -+ void RemoveMulticastRoute (uint32_t i); -+ - uint32_t AddInterface (Ptr device); - Ipv4Interface * GetInterface (uint32_t i) const; - uint32_t GetNInterfaces (void) const; -- - -+ virtual void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group); -+ virtual void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group); -+ - void SetAddress (uint32_t i, Ipv4Address address); - void SetNetworkMask (uint32_t i, Ipv4Mask mask); - Ipv4Mask GetNetworkMask (uint32_t t) const; -@@ -192,7 +207,10 @@ private: - TraceResolver *InterfacesCreateTraceResolver (TraceContext const &context) const; - - typedef std::list Ipv4InterfaceList; -- typedef std::list< std::pair< int, Ptr > > Ipv4RoutingProtocolList; -+ typedef std::list > -+ Ipv4MulticastGroupList; -+ typedef std::list > > -+ Ipv4RoutingProtocolList; - - Ipv4InterfaceList m_interfaces; - uint32_t m_nInterfaces; -@@ -206,6 +224,7 @@ private: - Ipv4RoutingProtocolList m_routingProtocols; - - Ptr m_staticRouting; -+ Ipv4MulticastGroupList m_multicastGroups; - }; - - } // Namespace ns3 -diff -r c26bf0511078 -r a8f3d01d4a2c src/internet-node/ipv4-static-routing.cc ---- a/src/internet-node/ipv4-static-routing.cc Fri Aug 10 13:49:41 2007 -0700 -+++ b/src/internet-node/ipv4-static-routing.cc Sun Aug 12 13:59:49 2007 -0700 -@@ -18,10 +18,10 @@ - // - // Author: George F. Riley - // Gustavo Carneiro -+// Craig Dowell - - #include "ipv4-static-routing.h" - #include "ns3/packet.h" -- - - namespace ns3 { - -@@ -77,6 +77,83 @@ Ipv4StaticRouting::SetDefaultRoute (Ipv4 - m_defaultRoute = route; - } - -+void -+Ipv4StaticRouting::AddMulticastRoute(Ipv4Address origin, -+ Ipv4Address group, -+ uint32_t inputInterface, -+ std::vector outputInterfaces) -+{ -+ Ipv4MulticastRoute *route = new Ipv4MulticastRoute (); -+ *route = Ipv4MulticastRoute::CreateMulticastRoute (origin, group, -+ inputInterface, outputInterfaces); -+ m_multicastRoutes.push_back (route); -+} -+ -+uint32_t -+Ipv4StaticRouting::GetNMulticastRoutes (void) const -+{ -+ return m_multicastRoutes.size (); -+} -+ -+Ipv4MulticastRoute * -+Ipv4StaticRouting::GetMulticastRoute (uint32_t index) const -+{ -+ NS_ASSERT_MSG(index < m_multicastRoutes.size (), -+ "Ipv4StaticRouting::GetMulticastRoute (): Index out of range"); -+ -+ uint32_t tmp = 0; -+ for (MulticastRoutesCI i = m_multicastRoutes.begin (); -+ i != m_multicastRoutes.end (); -+ i++) -+ { -+ if (tmp == index) -+ { -+ return *i; -+ } -+ tmp++; -+ } -+ return 0; -+} -+ -+void -+Ipv4StaticRouting::RemoveMulticastRoute(Ipv4Address origin, -+ Ipv4Address group, -+ uint32_t inputInterface) -+{ -+ for (MulticastRoutesI i = m_multicastRoutes.begin (); -+ i != m_multicastRoutes.end (); -+ i++) -+ { -+ Ipv4MulticastRoute *route = *i; -+ if (origin == route->GetOrigin () && -+ group == route->GetGroup () && -+ inputInterface == route->GetInputInterface ()) -+ { -+ delete *i; -+ m_multicastRoutes.erase (i); -+ return; -+ } -+ } -+} -+ -+void -+Ipv4StaticRouting::RemoveMulticastRoute(uint32_t index) -+{ -+ uint32_t tmp = 0; -+ for (MulticastRoutesI i = m_multicastRoutes.begin (); -+ i != m_multicastRoutes.end (); -+ i++) -+ { -+ if (tmp == index) -+ { -+ delete *i; -+ m_multicastRoutes.erase (i); -+ return; -+ } -+ tmp++; -+ } -+} -+ - Ipv4Route * - Ipv4StaticRouting::LookupStatic (Ipv4Address dest) - { -@@ -106,6 +183,25 @@ Ipv4StaticRouting::LookupStatic (Ipv4Add - { - NS_ASSERT (m_defaultRoute->IsDefault ()); - return m_defaultRoute; -+ } -+ return 0; -+} -+ -+Ipv4MulticastRoute * -+Ipv4StaticRouting::LookupStatic ( -+ Ipv4Address origin, -+ Ipv4Address group) -+{ -+ for (MulticastRoutesI i = m_multicastRoutes.begin (); -+ i != m_multicastRoutes.end (); -+ i++) -+ { -+ Ipv4MulticastRoute *route = *i; -+ if (origin == route->GetOrigin () && -+ group == route->GetGroup ()) -+ { -+ return *i; -+ } - } - return 0; - } -@@ -213,6 +309,27 @@ Ipv4StaticRouting::RequestRoute (Ipv4Hea - Packet packet, - RouteReplyCallback routeReply) - { -+// -+// First, see if this is a multicast packet we have a route for. If we -+// have a route, then send the packet down each of the specified interfaces. -+// -+ Ipv4MulticastRoute *mRoute = LookupStatic(ipHeader.GetSource (), -+ ipHeader.GetDestination ()); -+ if (mRoute) -+ { -+ for (uint32_t i = 0; i < mRoute->GetNOutputInterfaces (); ++i) -+ { -+ Packet p = packet; -+ Ipv4Route route = -+ Ipv4Route::CreateHostRouteTo(ipHeader.GetDestination (), -+ mRoute->GetOutputInterface(i)); -+ routeReply (true, route, p, ipHeader); -+ return true; -+ } -+ } -+// -+// See if this is a unicast packet we have a route for. -+// - Ipv4Route *route = LookupStatic (ipHeader.GetDestination ()); - if (route != 0) - { -@@ -246,8 +363,13 @@ Ipv4StaticRouting::DoDispose (void) - delete m_defaultRoute; - m_defaultRoute = 0; - } -+ for (MulticastRoutesI i = m_multicastRoutes.begin (); -+ i != m_multicastRoutes.end (); -+ i = m_multicastRoutes.erase (i)) -+ { -+ delete (*i); -+ } - Ipv4RoutingProtocol::DoDispose (); - } - -- - }//namespace ns3 -diff -r c26bf0511078 -r a8f3d01d4a2c src/internet-node/ipv4-static-routing.h ---- a/src/internet-node/ipv4-static-routing.h Fri Aug 10 13:49:41 2007 -0700 -+++ b/src/internet-node/ipv4-static-routing.h Sun Aug 12 13:59:49 2007 -0700 -@@ -75,6 +75,20 @@ public: - Ipv4Route *GetRoute (uint32_t i); - void RemoveRoute (uint32_t i); - -+ void AddMulticastRoute (Ipv4Address origin, -+ Ipv4Address group, -+ uint32_t inputInterface, -+ std::vector outputInterfaces); -+ -+ uint32_t GetNMulticastRoutes (void) const; -+ Ipv4MulticastRoute *GetMulticastRoute (uint32_t i) const; -+ -+ void RemoveMulticastRoute (Ipv4Address origin, -+ Ipv4Address group, -+ uint32_t inputInterface); -+ -+ void RemoveMulticastRoute (uint32_t index); -+ - protected: - void DoDispose (void); - -@@ -86,14 +100,18 @@ private: - typedef std::list::const_iterator NetworkRoutesCI; - typedef std::list::iterator NetworkRoutesI; - -+ typedef std::list MulticastRoutes; -+ typedef std::list::const_iterator MulticastRoutesCI; -+ typedef std::list::iterator MulticastRoutesI; -+ - Ipv4Route *LookupStatic (Ipv4Address dest); -+ Ipv4MulticastRoute *LookupStatic (Ipv4Address origin, Ipv4Address group); - - HostRoutes m_hostRoutes; - NetworkRoutes m_networkRoutes; - Ipv4Route *m_defaultRoute; -+ MulticastRoutes m_multicastRoutes; - }; -- -- - - } // Namespace ns3 - -diff -r c26bf0511078 -r a8f3d01d4a2c src/node/ipv4-route.cc ---- a/src/node/ipv4-route.cc Fri Aug 10 13:49:41 2007 -0700 -+++ b/src/node/ipv4-route.cc Sun Aug 12 13:59:49 2007 -0700 -@@ -137,7 +137,6 @@ Ipv4Route::GetInterface (void) const - return m_interface; - } - -- - Ipv4Route - Ipv4Route::CreateHostRouteTo (Ipv4Address dest, - Ipv4Address nextHop, -@@ -220,4 +219,99 @@ std::ostream& operator<< (std::ostream& - return os; - } - -+/***************************************************** -+ * Ipv4MulticastRoute -+ *****************************************************/ -+ -+Ipv4MulticastRoute::Ipv4MulticastRoute () -+{ -+} -+ -+Ipv4MulticastRoute::Ipv4MulticastRoute (Ipv4MulticastRoute const &route) -+: -+ m_origin (route.m_origin), -+ m_group (route.m_group), -+ m_inputInterface (route.m_inputInterface), -+ m_outputInterfaces (route.m_outputInterfaces) -+{ -+} -+ -+Ipv4MulticastRoute::Ipv4MulticastRoute ( -+ Ipv4Address origin, -+ Ipv4Address group, -+ uint32_t inputInterface, -+ std::vector outputInterfaces) -+{ -+ m_origin = origin; -+ m_group = group; -+ m_inputInterface = inputInterface; -+ m_outputInterfaces = outputInterfaces; -+} -+ -+Ipv4Address -+Ipv4MulticastRoute::GetOrigin (void) const -+{ -+ return m_origin; -+} -+ -+Ipv4Address -+Ipv4MulticastRoute::GetGroup (void) const -+{ -+ return m_group; -+} -+ -+uint32_t -+Ipv4MulticastRoute::GetInputInterface (void) const -+{ -+ return m_inputInterface; -+} -+ -+uint32_t -+Ipv4MulticastRoute::GetNOutputInterfaces (void) const -+{ -+ return m_outputInterfaces.size (); -+} -+ -+uint32_t -+Ipv4MulticastRoute::GetOutputInterface (uint32_t n) const -+{ -+ NS_ASSERT_MSG(n < m_outputInterfaces.size (), -+ "Ipv4MulticastRoute::GetOutputInterface (): index out of bounds"); -+ -+ return m_outputInterfaces[n]; -+} -+ -+std::vector -+Ipv4MulticastRoute::GetOutputInterfaces (void) const -+{ -+ return m_outputInterfaces; -+} -+ -+Ipv4MulticastRoute -+Ipv4MulticastRoute::CreateMulticastRoute ( -+ Ipv4Address origin, -+ Ipv4Address group, -+ uint32_t inputInterface, -+ std::vector outputInterfaces) -+{ -+ return Ipv4MulticastRoute (origin, group, inputInterface, outputInterfaces); -+} -+ -+std::ostream& -+operator<< (std::ostream& os, Ipv4MulticastRoute const& route) -+{ -+ os << "origin=" << route.GetOrigin () << -+ ", group=" << route.GetGroup () << -+ ", input interface=" << route.GetInputInterface () << -+ ", output interfaces="; -+ -+ for (uint32_t i = 0; i < route.GetNOutputInterfaces (); ++i) -+ { -+ os << route.GetOutputInterface (i) << " "; -+ -+ } -+ -+ return os; -+} -+ - }//namespace ns3 -diff -r c26bf0511078 -r a8f3d01d4a2c src/node/ipv4-route.h ---- a/src/node/ipv4-route.h Fri Aug 10 13:49:41 2007 -0700 -+++ b/src/node/ipv4-route.h Sun Aug 12 13:59:49 2007 -0700 -@@ -22,6 +22,7 @@ - #define IPV4_ROUTE_H - - #include -+#include - #include - - #include "ipv4-address.h" -@@ -98,6 +99,67 @@ private: - - std::ostream& operator<< (std::ostream& os, Ipv4Route const& route); - -+/** -+ * \brief A record of an IPv4 multicast route -+ */ -+class Ipv4MulticastRoute { -+public: -+ /** -+ * \brief This constructor does nothing -+ */ -+ Ipv4MulticastRoute (); -+ /** -+ * \brief Copy Constructor -+ * \param route The route to copy -+ */ -+ Ipv4MulticastRoute (Ipv4MulticastRoute const &route); -+ -+ /** -+ * \return The IPv4 address of the source of this route -+ */ -+ Ipv4Address GetOrigin (void) const; -+ -+ /** -+ * \return The IPv4 address of the multicast group of this route -+ */ -+ Ipv4Address GetGroup (void) const; -+ -+ /** -+ * \return The IPv4 address of the input interface of this route -+ */ -+ uint32_t GetInputInterface (void) const; -+ -+ /** -+ * \return The number of output interfaces of this route -+ */ -+ uint32_t GetNOutputInterfaces (void) const; -+ -+ /** -+ * \return A specified output interface. -+ */ -+ uint32_t GetOutputInterface (uint32_t n) const; -+ -+ /** -+ * \return A vector of all of the output interfaces of this route. -+ */ -+ std::vector GetOutputInterfaces (void) const; -+ -+ static Ipv4MulticastRoute CreateMulticastRoute (Ipv4Address origin, -+ Ipv4Address group, uint32_t inputInterface, -+ std::vector outputInterfaces); -+ -+private: -+ Ipv4MulticastRoute (Ipv4Address origin, Ipv4Address group, -+ uint32_t inputInterface, std::vector outputInterfaces); -+ -+ Ipv4Address m_origin; -+ Ipv4Address m_group; -+ uint32_t m_inputInterface; -+ std::vector m_outputInterfaces; -+}; -+ -+std::ostream& operator<< (std::ostream& os, Ipv4MulticastRoute const& route); -+ - }//namespace ns3 - - #endif /* IPV4_ROUTE_H */ -diff -r c26bf0511078 -r a8f3d01d4a2c src/node/ipv4.h ---- a/src/node/ipv4.h Fri Aug 10 13:49:41 2007 -0700 -+++ b/src/node/ipv4.h Sun Aug 12 13:59:49 2007 -0700 -@@ -202,7 +202,49 @@ public: - * \param i index of route to remove from routing table. - */ - virtual void RemoveRoute (uint32_t i) = 0; -+ -+ /** -+ * \brief Add a static multicast route for a given multicast source and -+ * group. -+ * -+ * \param origin The Ipv4 address of the multicast source. -+ * \param group The multicast group address. -+ * \param inputInterface The interface index over which the packet arrived. -+ * \param outputInterfaces The list of output interface indices over which -+ * the packet should be sent (excluding the inputInterface). -+ */ -+ virtual void AddMulticastRoute (Ipv4Address origin, -+ Ipv4Address group, -+ uint32_t inputInterface, -+ std::vector outputInterfaces) = 0; -+ /** -+ * \brief Remove a static multicast route for a given multicast source and -+ * group. -+ * -+ * \param origin The Ipv4 address of the multicast source. -+ * \param group The multicast group address. -+ * \param inputInterface The interface index over which the packet arrived. -+ */ -+ virtual void RemoveMulticastRoute (Ipv4Address origin, -+ Ipv4Address group, -+ uint32_t inputInterface) = 0; - -+ /** -+ * \returns the number of entries in the multicast routing table. -+ */ -+ virtual uint32_t GetNMulticastRoutes (void) const = 0; -+ -+ /** -+ * \param i index of route to return -+ * \returns the route whose index is i -+ */ -+ virtual Ipv4MulticastRoute GetMulticastRoute (uint32_t i) const = 0; -+ -+ /** -+ * \param i index of route to remove from routing table. -+ */ -+ virtual void RemoveMulticastRoute (uint32_t i) = 0; -+ - /** - * \param device device to add to the list of ipv4 interfaces - * which can be used as output interfaces during packet forwarding. -@@ -225,6 +267,24 @@ public: - virtual Ptr GetNetDevice (uint32_t i) = 0; - - /** -+ * \brief Join a multicast group for a given multicast source and -+ * group. -+ * -+ * \param origin The Ipv4 address of the multicast source. -+ * \param group The multicast group address. -+ */ -+ virtual void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group) = 0; -+ -+ /** -+ * \brief Leave a multicast group for a given multicast source and -+ * group. -+ * -+ * \param origin The Ipv4 address of the multicast source. -+ * \param group The multicast group address. -+ */ -+ virtual void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group) = 0; -+ -+ /** - * \param i index of ipv4 interface - * \param address address to associate to the underlying ipv4 interface - */ - -changeset: 1279:31cb0668defd -user: Craig Dowell -date: Sun Aug 12 15:51:12 2007 -0700 -summary: debug prints to make validation easier - -diff -r a8f3d01d4a2c -r 31cb0668defd examples/csma-multicast.cc ---- a/examples/csma-multicast.cc Sun Aug 12 13:59:49 2007 -0700 -+++ b/examples/csma-multicast.cc Sun Aug 12 15:51:12 2007 -0700 -@@ -58,19 +58,36 @@ - - using namespace ns3; - -+NS_DEBUG_COMPONENT_DEFINE ("Me"); -+ - int - main (int argc, char *argv[]) - { - // Users may find it convenient to turn on explicit debugging - // for selected modules; the below lines suggest how to do this - #if 0 -+ DebugComponentEnable("Me"); - DebugComponentEnable("CsmaNetDevice"); - DebugComponentEnable("Ipv4L3Protocol"); - DebugComponentEnable("NetDevice"); - DebugComponentEnable("Channel"); - DebugComponentEnable("CsmaChannel"); - DebugComponentEnable("PacketSocket"); -+ DebugComponentEnable("OnOffApplication"); -+ DebugComponentEnable("UdpSocket"); -+ DebugComponentEnable("UdpL4Protocol"); -+ DebugComponentEnable("Ipv4L3Protocol"); -+ DebugComponentEnable("Ipv4StaticRouting"); - #endif -+ -+ DebugComponentEnable("Me"); -+ DebugComponentEnable("OnOffApplication"); -+ DebugComponentEnable("UdpSocket"); -+ DebugComponentEnable("UdpL4Protocol"); -+ DebugComponentEnable("Ipv4L3Protocol"); -+ DebugComponentEnable("Ipv4StaticRouting"); -+ DebugComponentEnable("CsmaNetDevice"); -+ DebugComponentEnable("CsmaChannel"); - - // Set up some default values for the simulation. Use the Bind() - // technique to tell the system what subclass of Queue to use, -@@ -86,16 +103,19 @@ main (int argc, char *argv[]) - - // Here, we will explicitly create four nodes. In more sophisticated - // topologies, we could configure a node factory. -+ NS_DEBUG("Create nodes."); - Ptr n0 = Create (); - Ptr n1 = Create (); - Ptr n2 = Create (); - Ptr n3 = Create (); - -+ NS_DEBUG("Create channels."); - // We create the channels first without any IP addressing information - Ptr channel0 = - CsmaTopology::CreateCsmaChannel( - DataRate(5000000), MilliSeconds(2)); - -+ NS_DEBUG("Build Topology."); - uint32_t n0ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n0, channel0, - Eui48Address("10:54:23:54:23:50")); - uint32_t n1ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n1, channel0, -@@ -106,6 +126,8 @@ main (int argc, char *argv[]) - Eui48Address("10:54:23:54:23:53")); - - // Later, we add IP addresses. -+ NS_DEBUG("Assign IP Addresses."); -+ - CsmaIpv4Topology::AddIpv4Address ( - n0, n0ifIndex, Ipv4Address("10.1.1.1"), Ipv4Mask("255.255.255.0")); - -@@ -119,6 +141,7 @@ main (int argc, char *argv[]) - n3, n3ifIndex, Ipv4Address("10.1.1.4"), Ipv4Mask("255.255.255.0")); - - // Configure multicasting -+ NS_DEBUG("Configure multicasting."); - Ipv4Address multicastSource ("10.1.1.1"); - Ipv4Address multicastGroup ("225.0.0.0"); - -@@ -142,7 +165,8 @@ main (int argc, char *argv[]) - - // Create the OnOff application to send UDP datagrams of size - // 210 bytes at a rate of 448 Kb/s -- // from n0 to n1 -+ // from n0 to the multicast group -+ NS_DEBUG("Create Applications."); - Ptr ooff = Create ( - n0, - InetSocketAddress (multicastGroup, 80), -@@ -155,7 +179,8 @@ main (int argc, char *argv[]) - - // Configure tracing of all enqueue, dequeue, and NetDevice receive events - // Trace output will be sent to the csma-one-subnet.tr file -- AsciiTrace asciitrace ("csma-one-subnet.tr"); -+ NS_DEBUG("Configure Tracing."); -+ AsciiTrace asciitrace ("csma-multicast.tr"); - asciitrace.TraceAllNetDeviceRx (); - asciitrace.TraceAllQueues (); - -@@ -164,10 +189,11 @@ main (int argc, char *argv[]) - // simple-point-to-point.pcap-- - // and can be read by the "tcpdump -r" command (use "-tt" option to - // display timestamps correctly) -- PcapTrace pcaptrace ("csma-one-subnet.pcap"); -+ PcapTrace pcaptrace ("csma-multicast.pcap"); - pcaptrace.TraceAllIp (); - -+ NS_DEBUG("Run Simulation."); - Simulator::Run (); -- - Simulator::Destroy (); -+ NS_DEBUG("Done."); - } -diff -r a8f3d01d4a2c -r 31cb0668defd src/applications/onoff-application.cc ---- a/src/applications/onoff-application.cc Sun Aug 12 13:59:49 2007 -0700 -+++ b/src/applications/onoff-application.cc Sun Aug 12 15:51:12 2007 -0700 -@@ -22,6 +22,7 @@ - // George F. Riley, Georgia Tech, Spring 2007 - // Adapted from ApplicationOnOff in GTNetS. - -+#include "ns3/debug.h" - #include "ns3/address.h" - #include "ns3/node.h" - #include "ns3/nstime.h" -@@ -34,6 +35,8 @@ - #include "ns3/packet.h" - #include "onoff-application.h" - -+NS_DEBUG_COMPONENT_DEFINE ("OnOffApplication"); -+ - using namespace std; - - namespace ns3 { -@@ -95,30 +98,37 @@ OnOffApplication::Construct (Ptr n - m_iid = iid; - } - -- - OnOffApplication::~OnOffApplication() --{} -+{ -+ NS_DEBUG("OnOffApplication::~OnOffApplication()"); -+} - - void - OnOffApplication::SetMaxBytes(uint32_t maxBytes) - { -+ NS_DEBUG("OnOffApplication::SetMaxBytes(" << maxBytes << ")"); - m_maxBytes = maxBytes; - } - - void - OnOffApplication::SetDefaultRate (const DataRate &rate) - { -+ NS_DEBUG("OnOffApplication::SetDefaultRate(" << &rate << ")"); - g_defaultRate.SetValue (rate); - } -+ - void - OnOffApplication::SetDefaultSize (uint32_t size) - { -+ NS_DEBUG("OnOffApplication::SetDefaultSize(" << size << ")"); - g_defaultSize.SetValue (size); - } - - void - OnOffApplication::DoDispose (void) - { -+ NS_DEBUG("OnOffApplication::DoDispose()"); -+ - m_socket = 0; - delete m_onTime; - delete m_offTime; -@@ -130,10 +140,11 @@ OnOffApplication::DoDispose (void) - Application::DoDispose (); - } - -- - // Application Methods --void OnOffApplication::StartApplication() // Called at time specified by Start --{ -+void OnOffApplication::StartApplication() // Called at time specified by Start -+{ -+ NS_DEBUG("OnOffApplication::StartApplication()"); -+ - // Create the socket if not already - if (!m_socket) - { -@@ -151,8 +162,10 @@ void OnOffApplication::StartApplication( - ScheduleStartEvent(); - } - --void OnOffApplication::StopApplication() // Called at time specified by Stop --{ -+void OnOffApplication::StopApplication() // Called at time specified by Stop -+{ -+ NS_DEBUG("OnOffApplication::StopApplication()"); -+ - if (m_sendEvent.IsRunning ()) - { // Cancel the pending send packet event - // Calculate residual bits since last packet sent -@@ -166,17 +179,23 @@ void OnOffApplication::StopApplication() - // Event handlers - void OnOffApplication::StartSending() - { -+ NS_DEBUG("OnOffApplication::StartSending ()"); -+ - ScheduleNextTx(); // Schedule the send packet event - } - - void OnOffApplication::StopSending() - { -+ NS_DEBUG("OnOffApplication::StopSending ()"); -+ - Simulator::Cancel(m_sendEvent); - } - - // Private helpers - void OnOffApplication::ScheduleNextTx() - { -+ NS_DEBUG("OnOffApplication::ScheduleNextTx ()"); -+ - if (m_totBytes < m_maxBytes) - { - uint32_t bits = m_pktSize * 8 - m_residualBits; -@@ -192,12 +211,16 @@ void OnOffApplication::ScheduleNextTx() - - void OnOffApplication::ScheduleStartEvent() - { // Schedules the event to start sending data (switch to the "On" state) -+ NS_DEBUG("OnOffApplication::ScheduleStartEvent ()"); -+ - Time offInterval = Seconds(m_offTime->GetValue()); - m_startStopEvent = Simulator::Schedule(offInterval, &OnOffApplication::StartSending, this); - } - - void OnOffApplication::ScheduleStopEvent() - { // Schedules the event to stop sending data (switch to "Off" state) -+ NS_DEBUG("OnOffApplication::ScheduleStopEvent ()"); -+ - Time onInterval = Seconds(m_onTime->GetValue()); - Simulator::Schedule(onInterval, &OnOffApplication::StopSending, this); - } -@@ -205,6 +228,8 @@ void OnOffApplication::ScheduleStopEvent - - void OnOffApplication::SendPacket() - { -+ NS_DEBUG("OnOffApplication::SendPacket ()"); -+ - NS_ASSERT (m_sendEvent.IsExpired ()); - m_socket->Send(Packet (m_pktSize)); - m_totBytes += m_pktSize; -@@ -215,6 +240,8 @@ void OnOffApplication::SendPacket() - - void OnOffApplication::ConnectionSucceeded(Ptr) - { -+ NS_DEBUG("OnOffApplication::ConnectionSucceeded ()"); -+ - m_connected = true; - ScheduleStartEvent(); - } -diff -r a8f3d01d4a2c -r 31cb0668defd src/internet-node/ipv4-l3-protocol.cc ---- a/src/internet-node/ipv4-l3-protocol.cc Sun Aug 12 13:59:49 2007 -0700 -+++ b/src/internet-node/ipv4-l3-protocol.cc Sun Aug 12 15:51:12 2007 -0700 -@@ -17,7 +17,6 @@ - // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - // - // Author: George F. Riley --// Craig Dowell - // - - #include "ns3/packet.h" -@@ -121,17 +120,24 @@ Ipv4L3Protocol::Ipv4L3Protocol(Ptr - m_identification (0), - m_node (node) - { -+ NS_DEBUG("Ipv4L3Protocol::Ipv4L3Protocol ()"); -+ - SetInterfaceId (Ipv4L3Protocol::iid); - m_staticRouting = Create (); - AddRoutingProtocol (m_staticRouting, 0); - SetupLoopback (); - } -+ - Ipv4L3Protocol::~Ipv4L3Protocol () --{} -+{ -+ NS_DEBUG("Ipv4L3Protocol::~Ipv4L3Protocol ()"); -+} - - void - Ipv4L3Protocol::DoDispose (void) - { -+ NS_DEBUG("Ipv4L3Protocol::DoDispose ()"); -+ - for (Ipv4InterfaceList::iterator i = m_interfaces.begin (); - i != m_interfaces.end (); i++) - { -@@ -147,6 +153,8 @@ void - void - Ipv4L3Protocol::SetupLoopback (void) - { -+ NS_DEBUG("Ipv4L3Protocol::SetupLoopback ()"); -+ - Ipv4LoopbackInterface * interface = new Ipv4LoopbackInterface (m_node); - interface->SetAddress (Ipv4Address::GetLoopback ()); - interface->SetNetworkMask (Ipv4Mask::GetLoopback ()); -@@ -158,6 +166,8 @@ TraceResolver * - TraceResolver * - Ipv4L3Protocol::CreateTraceResolver (TraceContext const &context) - { -+ NS_DEBUG("Ipv4L3Protocol::CreateTraceResolver ()"); -+ - CompositeTraceResolver *resolver = new CompositeTraceResolver (context); - resolver->Add ("tx", m_txTrace, Ipv4L3ProtocolTraceContextElement(Ipv4L3ProtocolTraceContextElement::TX)); - resolver->Add ("rx", m_rxTrace, Ipv4L3ProtocolTraceContextElement(Ipv4L3ProtocolTraceContextElement::RX)); -@@ -170,6 +180,8 @@ TraceResolver * - TraceResolver * - Ipv4L3Protocol::InterfacesCreateTraceResolver (TraceContext const &context) const - { -+ NS_DEBUG("Ipv4L3Protocol::InterfacesCreateTraceResolver ()"); -+ - ArrayTraceResolver *resolver = - new ArrayTraceResolver - (context, -@@ -181,6 +193,7 @@ void - void - Ipv4L3Protocol::SetDefaultTtl (uint8_t ttl) - { -+ NS_DEBUG("Ipv4L3Protocol::SetDefaultTtl ()"); - m_defaultTtl = ttl; - } - -@@ -190,20 +203,28 @@ Ipv4L3Protocol::AddHostRouteTo (Ipv4Addr - Ipv4Address nextHop, - uint32_t interface) - { -+ NS_DEBUG("Ipv4L3Protocol::AddHostRouteTo (" << dest << ", " << nextHop << -+ ", " << interface << ")"); - m_staticRouting->AddHostRouteTo (dest, nextHop, interface); - } -+ - void - Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest, - uint32_t interface) - { -+ NS_DEBUG("Ipv4L3Protocol::AddHostRouteTo (" << dest << ", " << -+ interface << ")"); - m_staticRouting->AddHostRouteTo (dest, interface); - } -+ - void - Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network, - Ipv4Mask networkMask, - Ipv4Address nextHop, - uint32_t interface) - { -+ NS_DEBUG("Ipv4L3Protocol::AddNetworkRouteTo (" << network << ", " << -+ networkMask << ", " << nextHop << ", " << interface << ")"); - m_staticRouting->AddNetworkRouteTo (network, networkMask, nextHop, interface); - } - void -@@ -211,26 +232,33 @@ Ipv4L3Protocol::AddNetworkRouteTo (Ipv4A - Ipv4Mask networkMask, - uint32_t interface) - { -+ NS_DEBUG("Ipv4L3Protocol::AddNetworkRouteTo (" << network << ", " << -+ networkMask << ", " << interface << ")"); - m_staticRouting->AddNetworkRouteTo (network, networkMask, interface); - } - void - Ipv4L3Protocol::SetDefaultRoute (Ipv4Address nextHop, - uint32_t interface) - { -+ NS_DEBUG("Ipv4L3Protocol::SetDefaultRoute (" << nextHop << ", " << -+ interface << ")"); - m_staticRouting->SetDefaultRoute (nextHop, interface); - } -- - - void - Ipv4L3Protocol::Lookup (Ipv4Header const &ipHeader, - Packet packet, - Ipv4RoutingProtocol::RouteReplyCallback routeReply) - { -+ NS_DEBUG("Ipv4L3Protocol::Lookup (" << &ipHeader << ", " << &packet << -+ &routeReply << ")"); -+ - for (Ipv4RoutingProtocolList::const_iterator rprotoIter = - m_routingProtocols.begin (); - rprotoIter != m_routingProtocols.end (); - rprotoIter++) - { -+ NS_DEBUG("Ipv4L3Protocol::Lookup (): Requesting route"); - if ((*rprotoIter).second->RequestRoute (ipHeader, packet, routeReply)) - return; - } -@@ -243,6 +271,8 @@ Ipv4L3Protocol::AddRoutingProtocol (Ptr< - Ipv4L3Protocol::AddRoutingProtocol (Ptr routingProtocol, - int priority) - { -+ NS_DEBUG("Ipv4L3Protocol::AddRoutingProtocol (" << &routingProtocol << -+ ", " << priority << ")"); - m_routingProtocols.push_back - (std::pair > (-priority, routingProtocol)); - m_routingProtocols.sort (); -@@ -251,18 +281,21 @@ uint32_t - uint32_t - Ipv4L3Protocol::GetNRoutes (void) - { -+ NS_DEBUG("Ipv4L3Protocol::GetNRoutes ()"); - return m_staticRouting->GetNRoutes (); - } - - Ipv4Route * - Ipv4L3Protocol::GetRoute (uint32_t index) - { -+ NS_DEBUG("Ipv4L3Protocol::GetRoute ()"); - return m_staticRouting->GetRoute (index); - } - - void - Ipv4L3Protocol::RemoveRoute (uint32_t index) - { -+ NS_DEBUG("Ipv4L3Protocol::RemoveRoute (" << index << ")"); - m_staticRouting->RemoveRoute (index); - } - -@@ -272,6 +305,9 @@ Ipv4L3Protocol::AddMulticastRoute (Ipv4A - uint32_t inputInterface, - std::vector outputInterfaces) - { -+ NS_DEBUG("Ipv4L3Protocol::AddMulticastRoute (" << origin << ", " << -+ group << ", " << inputInterface << ", " << &outputInterfaces << ")"); -+ - m_staticRouting->AddMulticastRoute (origin, group, inputInterface, - outputInterfaces); - } -@@ -279,12 +315,14 @@ uint32_t - uint32_t - Ipv4L3Protocol::GetNMulticastRoutes (void) const - { -+ NS_DEBUG("Ipv4L3Protocol::GetNMulticastRoutes ()"); - return m_staticRouting->GetNMulticastRoutes (); - } - - Ipv4MulticastRoute * - Ipv4L3Protocol::GetMulticastRoute (uint32_t index) const - { -+ NS_DEBUG("Ipv4L3Protocol::GetMulticastRoute (" << index << ")"); - return m_staticRouting->GetMulticastRoute (index); - } - -@@ -293,32 +331,40 @@ Ipv4L3Protocol::RemoveMulticastRoute (Ip - Ipv4Address group, - uint32_t inputInterface) - { -+ NS_DEBUG("Ipv4L3Protocol::RemoveMulticastRoute (" << origin << ", " << -+ group << ", " << inputInterface << ")"); - m_staticRouting->RemoveMulticastRoute (origin, group, inputInterface); - } - - void - Ipv4L3Protocol::RemoveMulticastRoute (uint32_t index) - { -+ NS_DEBUG("Ipv4L3Protocol::RemoveMulticastRoute (" << index << ")"); - m_staticRouting->RemoveMulticastRoute (index); - } - - uint32_t - Ipv4L3Protocol::AddInterface (Ptr device) - { -+ NS_DEBUG("Ipv4L3Protocol::AddInterface (" << &device << ")"); - Ipv4Interface *interface = new ArpIpv4Interface (m_node, device); - return AddIpv4Interface (interface); - } -+ - uint32_t - Ipv4L3Protocol::AddIpv4Interface (Ipv4Interface *interface) - { -+ NS_DEBUG("Ipv4L3Protocol::AddIpv4Interface (" << interface << ")"); - uint32_t index = m_nInterfaces; - m_interfaces.push_back (interface); - m_nInterfaces++; - return index; - } -+ - Ipv4Interface * - Ipv4L3Protocol::GetInterface (uint32_t index) const - { -+ NS_DEBUG("Ipv4L3Protocol::GetInterface (" << index << ")"); - uint32_t tmp = 0; - for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++) - { -@@ -330,15 +376,18 @@ Ipv4L3Protocol::GetInterface (uint32_t i - } - return 0; - } -+ - uint32_t - Ipv4L3Protocol::GetNInterfaces (void) const - { -+ NS_DEBUG("Ipv4L3Protocol::GetNInterface ()"); - return m_nInterfaces; - } - - Ipv4Interface * - Ipv4L3Protocol::FindInterfaceForDevice (Ptr device) - { -+ NS_DEBUG("Ipv4L3Protocol::FindInterfaceForDevice (" << &device << ")"); - for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++) - { - if ((*i)->GetDevice () == device) -@@ -352,6 +401,9 @@ void - void - Ipv4L3Protocol::Receive( Ptr device, const Packet& p, uint16_t protocol, const Address &from) - { -+ NS_DEBUG("Ipv4L3Protocol::Receive (" << &device << ", " << &p << ", " << -+ protocol << ", " << from << ")"); -+ - uint32_t index = 0; - for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++) - { -@@ -386,6 +438,9 @@ Ipv4L3Protocol::Send (Packet const &pack - Ipv4Address destination, - uint8_t protocol) - { -+ NS_DEBUG("Ipv4L3Protocol::Send (" << &packet << ", " << source << ", " << -+ ", " << destination << ", " << protocol << ")"); -+ - Ipv4Header ipHeader; - - ipHeader.SetSource (source); -@@ -434,6 +489,9 @@ Ipv4L3Protocol::SendRealOut (bool found, - Packet packet, - Ipv4Header const &ipHeader) - { -+ NS_DEBUG("Ipv4L3Protocol::SendRealOut (" << found << ", " << &route << -+ ", " << &packet << &ipHeader << ")"); -+ - if (!found) - { - NS_DEBUG ("no route to host. drop."); -@@ -458,6 +516,9 @@ bool - bool - Ipv4L3Protocol::Forwarding (Packet const &packet, Ipv4Header &ipHeader, Ptr device) - { -+ NS_DEBUG("Ipv4L3Protocol::Forwarding (" << &packet << ", " << &ipHeader << -+ ", " << device << ")"); -+ - for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); - i != m_interfaces.end (); i++) - { -@@ -529,6 +590,7 @@ void - void - Ipv4L3Protocol::ForwardUp (Packet p, Ipv4Header const&ip) - { -+ NS_DEBUG("Ipv4L3Protocol::ForwardUp (" << &p << ", " << &ip << ")"); - Ptr demux = m_node->QueryInterface (Ipv4L4Demux::iid); - Ptr protocol = demux->GetProtocol (ip.GetProtocol ()); - protocol->Receive (p, ip.GetSource (), ip.GetDestination ()); -@@ -537,6 +599,8 @@ void - void - Ipv4L3Protocol::JoinMulticastGroup (Ipv4Address origin, Ipv4Address group) - { -+ NS_DEBUG("Ipv4L3Protocol::JoinMulticastGroup (" << origin << ", " << -+ group << ")"); - m_multicastGroups.push_back( - std::pair (origin, group)); - } -@@ -544,6 +608,9 @@ void - void - Ipv4L3Protocol::LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group) - { -+ NS_DEBUG("Ipv4L3Protocol::LeaveMulticastGroup (" << origin << ", " << -+ group << ")"); -+ - for (Ipv4MulticastGroupList::iterator i = m_multicastGroups.begin (); - i != m_multicastGroups.end (); - i++) -@@ -559,42 +626,55 @@ void - void - Ipv4L3Protocol::SetAddress (uint32_t i, Ipv4Address address) - { -+ NS_DEBUG("Ipv4L3Protocol::SetAddress (" << i << ", " << address << ")"); - Ipv4Interface *interface = GetInterface (i); - interface->SetAddress (address); - } -+ - void - Ipv4L3Protocol::SetNetworkMask (uint32_t i, Ipv4Mask mask) - { -+ NS_DEBUG("Ipv4L3Protocol::SetNetworkMask (" << i << ", " << mask << ")"); - Ipv4Interface *interface = GetInterface (i); - interface->SetNetworkMask (mask); - } -+ - Ipv4Mask - Ipv4L3Protocol::GetNetworkMask (uint32_t i) const - { -+ NS_DEBUG("Ipv4L3Protocol::GetNetworkMask (" << i << ")"); - Ipv4Interface *interface = GetInterface (i); - return interface->GetNetworkMask (); - } -+ - Ipv4Address - Ipv4L3Protocol::GetAddress (uint32_t i) const - { -+ NS_DEBUG("Ipv4L3Protocol::GetAddress (" << i << ")"); - Ipv4Interface *interface = GetInterface (i); - return interface->GetAddress (); - } -+ - uint16_t - Ipv4L3Protocol::GetMtu (uint32_t i) const - { -+ NS_DEBUG("Ipv4L3Protocol::GetMtu (" << i << ")"); - Ipv4Interface *interface = GetInterface (i); - return interface->GetMtu (); - } -+ - bool - Ipv4L3Protocol::IsUp (uint32_t i) const - { -+ NS_DEBUG("Ipv4L3Protocol::IsUp (" << i << ")"); - Ipv4Interface *interface = GetInterface (i); - return interface->IsUp (); - } -+ - void - Ipv4L3Protocol::SetUp (uint32_t i) - { -+ NS_DEBUG("Ipv4L3Protocol::SetUp (" << i << ")"); - Ipv4Interface *interface = GetInterface (i); - interface->SetUp (); - -@@ -608,9 +688,11 @@ Ipv4L3Protocol::SetUp (uint32_t i) - interface->GetNetworkMask (), i); - } - } -+ - void - Ipv4L3Protocol::SetDown (uint32_t ifaceIndex) - { -+ NS_DEBUG("Ipv4L3Protocol::SetDown (" << ifaceIndex << ")"); - Ipv4Interface *interface = GetInterface (ifaceIndex); - interface->SetDown (); - -diff -r a8f3d01d4a2c -r 31cb0668defd src/internet-node/ipv4-static-routing.cc ---- a/src/internet-node/ipv4-static-routing.cc Sun Aug 12 13:59:49 2007 -0700 -+++ b/src/internet-node/ipv4-static-routing.cc Sun Aug 12 15:51:12 2007 -0700 -@@ -18,10 +18,12 @@ - // - // Author: George F. Riley - // Gustavo Carneiro --// Craig Dowell -- -+ -+#include "ns3/debug.h" - #include "ipv4-static-routing.h" - #include "ns3/packet.h" -+ -+NS_DEBUG_COMPONENT_DEFINE ("Ipv4StaticRouting"); - - namespace ns3 { - -@@ -31,10 +33,12 @@ Ipv4StaticRouting::AddHostRouteTo (Ipv4A - Ipv4Address nextHop, - uint32_t interface) - { -+ - Ipv4Route *route = new Ipv4Route (); - *route = Ipv4Route::CreateHostRouteTo (dest, nextHop, interface); - m_hostRoutes.push_back (route); - } -+ - void - Ipv4StaticRouting::AddHostRouteTo (Ipv4Address dest, - uint32_t interface) -@@ -43,6 +47,7 @@ Ipv4StaticRouting::AddHostRouteTo (Ipv4A - *route = Ipv4Route::CreateHostRouteTo (dest, interface); - m_hostRoutes.push_back (route); - } -+ - void - Ipv4StaticRouting::AddNetworkRouteTo (Ipv4Address network, - Ipv4Mask networkMask, -@@ -56,6 +61,7 @@ Ipv4StaticRouting::AddNetworkRouteTo (Ip - interface); - m_networkRoutes.push_back (route); - } -+ - void - Ipv4StaticRouting::AddNetworkRouteTo (Ipv4Address network, - Ipv4Mask networkMask, -@@ -67,6 +73,7 @@ Ipv4StaticRouting::AddNetworkRouteTo (Ip - interface); - m_networkRoutes.push_back (route); - } -+ - void - Ipv4StaticRouting::SetDefaultRoute (Ipv4Address nextHop, - uint32_t interface) -@@ -197,7 +204,8 @@ Ipv4StaticRouting::LookupStatic ( - i++) - { - Ipv4MulticastRoute *route = *i; -- if (origin == route->GetOrigin () && -+ if ( (origin == route->GetOrigin () || -+ origin == Ipv4Address::GetAny ()) && - group == route->GetGroup ()) - { - return *i; -@@ -309,6 +317,15 @@ Ipv4StaticRouting::RequestRoute (Ipv4Hea - Packet packet, - RouteReplyCallback routeReply) - { -+ NS_DEBUG ("Ipv4StaticRouting::RequestRoute (" << &ipHeader << ", " << -+ &packet << ", " << &routeReply << ")"); -+ -+ NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): source = " << -+ ipHeader.GetSource ()); -+ -+ NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): destination = " << -+ ipHeader.GetDestination ()); -+ - // - // First, see if this is a multicast packet we have a route for. If we - // have a route, then send the packet down each of the specified interfaces. -diff -r a8f3d01d4a2c -r 31cb0668defd src/internet-node/udp-l4-protocol.cc ---- a/src/internet-node/udp-l4-protocol.cc Sun Aug 12 13:59:49 2007 -0700 -+++ b/src/internet-node/udp-l4-protocol.cc Sun Aug 12 15:51:12 2007 -0700 -@@ -19,6 +19,7 @@ - * Author: Mathieu Lacage - */ - -+#include "ns3/debug.h" - #include "ns3/assert.h" - #include "ns3/packet.h" - #include "ns3/empty-trace-resolver.h" -@@ -31,6 +32,8 @@ - #include "ipv4-l3-protocol.h" - #include "udp-socket.h" - -+NS_DEBUG_COMPONENT_DEFINE ("UdpL4Protocol"); -+ - namespace ns3 { - - /* see http://www.iana.org/assignments/protocol-numbers */ -@@ -40,20 +43,26 @@ UdpL4Protocol::UdpL4Protocol (Ptr - : Ipv4L4Protocol (PROT_NUMBER, 2), - m_node (node), - m_endPoints (new Ipv4EndPointDemux ()) --{} -+{ -+ NS_DEBUG("UdpL4Protocol::UdpL4Protocol ()"); -+} - - UdpL4Protocol::~UdpL4Protocol () --{} -+{ -+ NS_DEBUG("UdpL4Protocol::~UdpL4Protocol ()"); -+} - - TraceResolver * - UdpL4Protocol::CreateTraceResolver (TraceContext const &context) - { -+ NS_DEBUG("UdpL4Protocol::CreateTraceResolver ()"); - return new EmptyTraceResolver (context); - } - - void - UdpL4Protocol::DoDispose (void) - { -+ NS_DEBUG("UdpL4Protocol::DoDispose ()"); - if (m_endPoints != 0) - { - delete m_endPoints; -@@ -66,6 +75,7 @@ Ptr - Ptr - UdpL4Protocol::CreateSocket (void) - { -+ NS_DEBUG("UdpL4Protocol::CreateSocket ()"); - Ptr socket = Create (m_node, this); - return socket; - } -@@ -73,27 +83,36 @@ Ipv4EndPoint * - Ipv4EndPoint * - UdpL4Protocol::Allocate (void) - { -+ NS_DEBUG("UdpL4Protocol::Allocate ()"); - return m_endPoints->Allocate (); - } -+ - Ipv4EndPoint * - UdpL4Protocol::Allocate (Ipv4Address address) - { -+ NS_DEBUG("UdpL4Protocol::Allocate (" << address << ")"); - return m_endPoints->Allocate (address); - } -+ - Ipv4EndPoint * - UdpL4Protocol::Allocate (uint16_t port) - { -+ NS_DEBUG("UdpL4Protocol::Allocate (" << port << ")"); - return m_endPoints->Allocate (port); - } -+ - Ipv4EndPoint * - UdpL4Protocol::Allocate (Ipv4Address address, uint16_t port) - { -+ NS_DEBUG("UdpL4Protocol::Allocate (" << address << ", " << port << ")"); - return m_endPoints->Allocate (address, port); - } - Ipv4EndPoint * - UdpL4Protocol::Allocate (Ipv4Address localAddress, uint16_t localPort, - Ipv4Address peerAddress, uint16_t peerPort) - { -+ NS_DEBUG("UdpL4Protocol::Allocate (" << localAddress << ", " << localPort << -+ ", " << peerAddress << ", " << peerPort << ")"); - return m_endPoints->Allocate (localAddress, localPort, - peerAddress, peerPort); - } -@@ -101,6 +120,7 @@ void - void - UdpL4Protocol::DeAllocate (Ipv4EndPoint *endPoint) - { -+ NS_DEBUG("UdpL4Protocol::Deallocate (" << endPoint << ")"); - m_endPoints->DeAllocate (endPoint); - } - -@@ -109,6 +129,9 @@ UdpL4Protocol::Receive(Packet& packet, - Ipv4Address const &source, - Ipv4Address const &destination) - { -+ NS_DEBUG("UdpL4Protocol::Receive (" << &packet << ", " << source << -+ ", " << destination << ")"); -+ - UdpHeader udpHeader; - packet.RemoveHeader (udpHeader); - Ipv4EndPointDemux::EndPoints endPoints = -@@ -126,6 +149,9 @@ UdpL4Protocol::Send (Packet packet, - Ipv4Address saddr, Ipv4Address daddr, - uint16_t sport, uint16_t dport) - { -+ NS_DEBUG("UdpL4Protocol::Send (" << &packet << ", " << saddr << -+ ", " << daddr << ", " << sport << ", " << dport << ")"); -+ - UdpHeader udpHeader; - udpHeader.SetDestination (dport); - udpHeader.SetSource (sport); -@@ -139,6 +165,7 @@ UdpL4Protocol::Send (Packet packet, - Ptr ipv4 = m_node->QueryInterface (Ipv4L3Protocol::iid); - if (ipv4 != 0) - { -+ NS_DEBUG("UdpL4Protocol::Send (): Sending to IP"); - ipv4->Send (packet, saddr, daddr, PROT_NUMBER); - } - } -diff -r a8f3d01d4a2c -r 31cb0668defd src/internet-node/udp-socket.cc ---- a/src/internet-node/udp-socket.cc Sun Aug 12 13:59:49 2007 -0700 -+++ b/src/internet-node/udp-socket.cc Sun Aug 12 15:51:12 2007 -0700 -@@ -18,12 +18,16 @@ - * - * Author: Mathieu Lacage - */ -+ -+#include "ns3/debug.h" - #include "ns3/node.h" - #include "ns3/inet-socket-address.h" - #include "udp-socket.h" - #include "udp-l4-protocol.h" - #include "ipv4-end-point.h" - #include "ipv4-l4-demux.h" -+ -+NS_DEBUG_COMPONENT_DEFINE ("UdpSocket"); - - namespace ns3 { - -@@ -35,9 +39,14 @@ UdpSocket::UdpSocket (Ptr node, Pt - m_shutdownSend (false), - m_shutdownRecv (false), - m_connected (false) --{} -+{ -+ NS_DEBUG("UdpSocket::UdpSocket ()"); -+} -+ - UdpSocket::~UdpSocket () - { -+ NS_DEBUG("UdpSocket::~UdpSocket ()"); -+ - m_node = 0; - if (m_endPoint != 0) - { -@@ -60,25 +69,32 @@ enum Socket::SocketErrno - enum Socket::SocketErrno - UdpSocket::GetErrno (void) const - { -+ NS_DEBUG("UdpSocket::GetErrno ()"); -+ - return m_errno; - } - - Ptr - UdpSocket::GetNode (void) const - { -+ NS_DEBUG("UdpSocket::GetNode ()"); - return m_node; - } - - void - UdpSocket::Destroy (void) - { -+ NS_DEBUG("UdpSocket::Destroy ()"); - m_node = 0; - m_endPoint = 0; - m_udp = 0; - } -+ - int - UdpSocket::FinishBind (void) - { -+ NS_DEBUG("UdpSocket::FinishBind ()"); -+ - if (m_endPoint == 0) - { - return -1; -@@ -91,14 +107,20 @@ int - int - UdpSocket::Bind (void) - { -+ NS_DEBUG("UdpSocket::Bind ()"); -+ - m_endPoint = m_udp->Allocate (); - return FinishBind (); - } -+ - int - UdpSocket::Bind (const Address &address) - { -+ NS_DEBUG("UdpSocket::Bind (" << address << ")"); -+ - if (!InetSocketAddress::IsMatchingType (address)) - { -+ NS_DEBUG("UdpSocket::Bind (): Not IsMatchingType"); - return ERROR_INVAL; - } - InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); -@@ -127,12 +149,15 @@ int - int - UdpSocket::ShutdownSend (void) - { -+ NS_DEBUG("UdpSocket::ShutDownSend ()"); - m_shutdownSend = true; - return 0; - } -+ - int - UdpSocket::ShutdownRecv (void) - { -+ NS_DEBUG("UdpSocket::ShutDownRecv ()"); - m_shutdownRecv = false; - return 0; - } -@@ -140,6 +165,7 @@ int - int - UdpSocket::Close(void) - { -+ NS_DEBUG("UdpSocket::Close ()"); - NotifyCloseCompleted (); - return 0; - } -@@ -147,6 +173,8 @@ int - int - UdpSocket::Connect(const Address & address) - { -+ NS_DEBUG("UdpSocket::Connect (" << address << ")"); -+ - InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); - m_defaultAddress = transport.GetIpv4 (); - m_defaultPort = transport.GetPort (); -@@ -154,9 +182,12 @@ UdpSocket::Connect(const Address & addre - m_connected = true; - return 0; - } -+ - int - UdpSocket::Send (const Packet &p) - { -+ NS_DEBUG("UdpSocket::Send (" << &p << ")"); -+ - if (!m_connected) - { - m_errno = ERROR_NOTCONN; -@@ -164,17 +195,23 @@ UdpSocket::Send (const Packet &p) - } - return DoSendTo (p, m_defaultAddress, m_defaultPort); - } -+ - int - UdpSocket::DoSendTo (const Packet &p, const Address &address) - { -+ NS_DEBUG("UdpSocket::DoSendTo (" << &p << ", " << address << ")"); - InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); - Ipv4Address ipv4 = transport.GetIpv4 (); - uint16_t port = transport.GetPort (); - return DoSendTo (p, ipv4, port); - } -+ - int - UdpSocket::DoSendTo (const Packet &p, Ipv4Address ipv4, uint16_t port) - { -+ NS_DEBUG("UdpSocket::DoSendTo (" << &p << ", " << ipv4 << ", " << -+ port << ")"); -+ - if (m_endPoint == 0) - { - if (Bind () == -1) -@@ -189,14 +226,18 @@ UdpSocket::DoSendTo (const Packet &p, Ip - m_errno = ERROR_SHUTDOWN; - return -1; - } -+ -+ NS_DEBUG("UdpSocket::DoSendTo (): Send to UDP"); - m_udp->Send (p, m_endPoint->GetLocalAddress (), ipv4, - m_endPoint->GetLocalPort (), port); - NotifyDataSent (p.GetSize ()); - return 0; - } -+ - int - UdpSocket::SendTo(const Address &address, const Packet &p) - { -+ NS_DEBUG("UdpSocket::SendTo (" << address << ", " << &p << ")"); - if (m_connected) - { - m_errno = ERROR_ISCONN; -@@ -211,6 +252,9 @@ void - void - UdpSocket::ForwardUp (const Packet &packet, Ipv4Address ipv4, uint16_t port) - { -+ NS_DEBUG("UdpSocket::ForwardUp (" << &packet << ", " << ipv4 << ", " << -+ port << ")"); -+ - if (m_shutdownRecv) - { - return; - -changeset: 1280:25fa26a6533e -user: Craig Dowell -date: Sun Aug 12 22:41:24 2007 -0700 -summary: many debug prints - -diff -r 31cb0668defd -r 25fa26a6533e examples/csma-multicast.cc ---- a/examples/csma-multicast.cc Sun Aug 12 15:51:12 2007 -0700 -+++ b/examples/csma-multicast.cc Sun Aug 12 22:41:24 2007 -0700 -@@ -67,17 +67,23 @@ main (int argc, char *argv[]) - // for selected modules; the below lines suggest how to do this - #if 0 - DebugComponentEnable("Me"); -- DebugComponentEnable("CsmaNetDevice"); -- DebugComponentEnable("Ipv4L3Protocol"); -- DebugComponentEnable("NetDevice"); -+ DebugComponentEnable("Object"); -+ DebugComponentEnable("Queue"); -+ DebugComponentEnable("DropTailQueue"); - DebugComponentEnable("Channel"); - DebugComponentEnable("CsmaChannel"); -+ DebugComponentEnable("CsmaNetDevice"); -+ DebugComponentEnable("Ipv4L3Protocol"); -+ DebugComponentEnable("NetDevice"); - DebugComponentEnable("PacketSocket"); - DebugComponentEnable("OnOffApplication"); - DebugComponentEnable("UdpSocket"); - DebugComponentEnable("UdpL4Protocol"); - DebugComponentEnable("Ipv4L3Protocol"); - DebugComponentEnable("Ipv4StaticRouting"); -+ DebugComponentEnable("Ipv4Interface"); -+ DebugComponentEnable("ArpIpv4Interface"); -+ DebugComponentEnable("Ipv4LoopbackInterface"); - #endif - - DebugComponentEnable("Me"); -@@ -88,6 +94,9 @@ main (int argc, char *argv[]) - DebugComponentEnable("Ipv4StaticRouting"); - DebugComponentEnable("CsmaNetDevice"); - DebugComponentEnable("CsmaChannel"); -+ DebugComponentEnable("Ipv4Interface"); -+ DebugComponentEnable("ArpIpv4Interface"); -+ DebugComponentEnable("Ipv4LoopbackInterface"); - - // Set up some default values for the simulation. Use the Bind() - // technique to tell the system what subclass of Queue to use, -diff -r 31cb0668defd -r 25fa26a6533e examples/csma-one-subnet.cc ---- a/examples/csma-one-subnet.cc Sun Aug 12 15:51:12 2007 -0700 -+++ b/examples/csma-one-subnet.cc Sun Aug 12 22:41:24 2007 -0700 -@@ -58,23 +58,47 @@ - #include "ns3/ipv4-route.h" - #include "ns3/onoff-application.h" - -- - using namespace ns3; - -+NS_DEBUG_COMPONENT_DEFINE ("Me"); - --int main (int argc, char *argv[]) -+int -+main (int argc, char *argv[]) - { -- - // Users may find it convenient to turn on explicit debugging - // for selected modules; the below lines suggest how to do this - #if 0 -+ DebugComponentEnable("Me"); -+ DebugComponentEnable("Object"); -+ DebugComponentEnable("Queue"); -+ DebugComponentEnable("DropTailQueue"); -+ DebugComponentEnable("Channel"); -+ DebugComponentEnable("CsmaChannel"); - DebugComponentEnable("CsmaNetDevice"); - DebugComponentEnable("Ipv4L3Protocol"); - DebugComponentEnable("NetDevice"); -- DebugComponentEnable("Channel"); -+ DebugComponentEnable("PacketSocket"); -+ DebugComponentEnable("OnOffApplication"); -+ DebugComponentEnable("UdpSocket"); -+ DebugComponentEnable("UdpL4Protocol"); -+ DebugComponentEnable("Ipv4L3Protocol"); -+ DebugComponentEnable("Ipv4StaticRouting"); -+ DebugComponentEnable("Ipv4Interface"); -+ DebugComponentEnable("ArpIpv4Interface"); -+ DebugComponentEnable("Ipv4LoopbackInterface"); -+#endif -+ -+ DebugComponentEnable("Me"); -+ DebugComponentEnable("OnOffApplication"); -+ DebugComponentEnable("UdpSocket"); -+ DebugComponentEnable("UdpL4Protocol"); -+ DebugComponentEnable("Ipv4L3Protocol"); -+ DebugComponentEnable("Ipv4StaticRouting"); -+ DebugComponentEnable("CsmaNetDevice"); - DebugComponentEnable("CsmaChannel"); -- DebugComponentEnable("PacketSocket"); --#endif -+ DebugComponentEnable("Ipv4Interface"); -+ DebugComponentEnable("ArpIpv4Interface"); -+ DebugComponentEnable("Ipv4LoopbackInterface"); - - // Set up some default values for the simulation. Use the Bind() - // technique to tell the system what subclass of Queue to use, -@@ -90,16 +114,19 @@ int main (int argc, char *argv[]) - - // Here, we will explicitly create four nodes. In more sophisticated - // topologies, we could configure a node factory. -+ NS_DEBUG("Create nodes."); - Ptr n0 = Create (); - Ptr n1 = Create (); - Ptr n2 = Create (); - Ptr n3 = Create (); - - // We create the channels first without any IP addressing information -+ NS_DEBUG("Create channels."); - Ptr channel0 = - CsmaTopology::CreateCsmaChannel( - DataRate(5000000), MilliSeconds(2)); - -+ NS_DEBUG("Build Topology."); - uint32_t n0ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n0, channel0, - Eui48Address("10:54:23:54:23:50")); - uint32_t n1ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n1, channel0, -@@ -110,6 +137,7 @@ int main (int argc, char *argv[]) - Eui48Address("10:54:23:54:23:53")); - - // Later, we add IP addresses. -+ NS_DEBUG("Assign IP Addresses."); - CsmaIpv4Topology::AddIpv4Address ( - n0, n0ifIndex, Ipv4Address("10.1.1.1"), Ipv4Mask("255.255.255.0")); - -@@ -125,6 +153,7 @@ int main (int argc, char *argv[]) - // Create the OnOff application to send UDP datagrams of size - // 210 bytes at a rate of 448 Kb/s - // from n0 to n1 -+ NS_DEBUG("Create Applications."); - Ptr ooff = Create ( - n0, - InetSocketAddress ("10.1.1.2", 80), -@@ -148,6 +177,7 @@ int main (int argc, char *argv[]) - - // Configure tracing of all enqueue, dequeue, and NetDevice receive events - // Trace output will be sent to the csma-one-subnet.tr file -+ NS_DEBUG("Configure Tracing."); - AsciiTrace asciitrace ("csma-one-subnet.tr"); - asciitrace.TraceAllNetDeviceRx (); - asciitrace.TraceAllQueues (); -@@ -160,7 +190,8 @@ int main (int argc, char *argv[]) - PcapTrace pcaptrace ("csma-one-subnet.pcap"); - pcaptrace.TraceAllIp (); - -+ NS_DEBUG("Run Simulation."); - Simulator::Run (); -- - Simulator::Destroy (); -+ NS_DEBUG("Done."); - } -diff -r 31cb0668defd -r 25fa26a6533e examples/simple-point-to-point.cc ---- a/examples/simple-point-to-point.cc Sun Aug 12 15:51:12 2007 -0700 -+++ b/examples/simple-point-to-point.cc Sun Aug 12 22:41:24 2007 -0700 -@@ -38,11 +38,7 @@ - // - Tracing of queues and packet receptions to file - // "simple-point-to-point.tr" - --#include --#include --#include --#include -- -+#include "ns3/debug.h" - #include "ns3/command-line.h" - #include "ns3/default-value.h" - #include "ns3/ptr.h" -@@ -67,19 +63,46 @@ - - using namespace ns3; - --int main (int argc, char *argv[]) -+NS_DEBUG_COMPONENT_DEFINE ("Me"); -+ -+int -+main (int argc, char *argv[]) - { - - // Users may find it convenient to turn on explicit debugging - // for selected modules; the below lines suggest how to do this - #if 0 -+ DebugComponentEnable("Me"); - DebugComponentEnable("Object"); - DebugComponentEnable("Queue"); - DebugComponentEnable("DropTailQueue"); - DebugComponentEnable("Channel"); - DebugComponentEnable("PointToPointChannel"); - DebugComponentEnable("PointToPointNetDevice"); -+ DebugComponentEnable("Ipv4L3Protocol"); -+ DebugComponentEnable("NetDevice"); -+ DebugComponentEnable("PacketSocket"); -+ DebugComponentEnable("OnOffApplication"); -+ DebugComponentEnable("UdpSocket"); -+ DebugComponentEnable("UdpL4Protocol"); -+ DebugComponentEnable("Ipv4L3Protocol"); -+ DebugComponentEnable("Ipv4StaticRouting"); -+ DebugComponentEnable("Ipv4Interface"); -+ DebugComponentEnable("ArpIpv4Interface"); -+ DebugComponentEnable("Ipv4LoopbackInterface"); - #endif -+ -+ DebugComponentEnable("Me"); -+ DebugComponentEnable("OnOffApplication"); -+ DebugComponentEnable("UdpSocket"); -+ DebugComponentEnable("UdpL4Protocol"); -+ DebugComponentEnable("Ipv4L3Protocol"); -+ DebugComponentEnable("Ipv4StaticRouting"); -+ DebugComponentEnable("PointToPointChannel"); -+ DebugComponentEnable("PointToPointNetDevice"); -+ DebugComponentEnable("Ipv4Interface"); -+ DebugComponentEnable("ArpIpv4Interface"); -+ DebugComponentEnable("Ipv4LoopbackInterface"); - - // Set up some default values for the simulation. Use the Bind() - // technique to tell the system what subclass of Queue to use, -@@ -100,12 +123,14 @@ int main (int argc, char *argv[]) - - // Here, we will explicitly create four nodes. In more sophisticated - // topologies, we could configure a node factory. -+ NS_DEBUG("Create nodes."); - Ptr n0 = Create (); - Ptr n1 = Create (); - Ptr n2 = Create (); - Ptr n3 = Create (); - - // We create the channels first without any IP addressing information -+ NS_DEBUG("Create channels."); - Ptr channel0 = - PointToPointTopology::AddPointToPointLink ( - n0, n2, DataRate(5000000), MilliSeconds(2)); -@@ -119,6 +144,7 @@ int main (int argc, char *argv[]) - n2, n3, DataRate(1500000), MilliSeconds(10)); - - // Later, we add IP addresses. -+ NS_DEBUG("Assign IP Addresses."); - PointToPointTopology::AddIpv4Addresses ( - channel0, n0, Ipv4Address("10.1.1.1"), - n2, Ipv4Address("10.1.1.2")); -@@ -135,13 +161,14 @@ int main (int argc, char *argv[]) - // NetDevice creation, IP Address assignment, and routing) are - // separated because there may be a need to postpone IP Address - // assignment (emulation) or modify to use dynamic routing -+ NS_DEBUG("Add Static Routes."); - PointToPointTopology::AddIpv4Routes(n0, n2, channel0); - PointToPointTopology::AddIpv4Routes(n1, n2, channel1); - PointToPointTopology::AddIpv4Routes(n2, n3, channel2); - -- - // Create the OnOff application to send UDP datagrams of size - // 210 bytes at a rate of 448 Kb/s -+ NS_DEBUG("Create Applications."); - Ptr ooff = Create ( - n0, - InetSocketAddress ("10.1.3.2", 80), -@@ -165,6 +192,7 @@ int main (int argc, char *argv[]) - - // Here, finish off packet routing configuration - // This will likely set by some global StaticRouting object in the future -+ NS_DEBUG("Set Default Routes."); - Ptr ipv4; - ipv4 = n0->QueryInterface (Ipv4::iid); - ipv4->SetDefaultRoute (Ipv4Address ("10.1.1.2"), 1); -@@ -173,6 +201,7 @@ int main (int argc, char *argv[]) - - // Configure tracing of all enqueue, dequeue, and NetDevice receive events - // Trace output will be sent to the simple-point-to-point.tr file -+ NS_DEBUG("Configure Tracing."); - AsciiTrace asciitrace ("simple-point-to-point.tr"); - asciitrace.TraceAllQueues (); - asciitrace.TraceAllNetDeviceRx (); -@@ -185,7 +214,8 @@ int main (int argc, char *argv[]) - PcapTrace pcaptrace ("simple-point-to-point.pcap"); - pcaptrace.TraceAllIp (); - -- Simulator::Run (); -- -+ NS_DEBUG("Run Simulation."); -+ Simulator::Run (); - Simulator::Destroy (); -+ NS_DEBUG("Done."); - } -diff -r 31cb0668defd -r 25fa26a6533e src/devices/csma/csma-ipv4-topology.cc ---- a/src/devices/csma/csma-ipv4-topology.cc Sun Aug 12 15:51:12 2007 -0700 -+++ b/src/devices/csma/csma-ipv4-topology.cc Sun Aug 12 22:41:24 2007 -0700 -@@ -36,15 +36,15 @@ namespace ns3 { - - uint32_t - CsmaIpv4Topology::AddIpv4CsmaNode(Ptr n1, -- Ptr ch, -- Eui48Address addr) -+ Ptr ch, -+ Eui48Address addr) - { - Ptr q = Queue::CreateDefault (); - - // assume full-duplex - Ptr nd0 = Create (n1, addr, -- ns3::CsmaNetDevice::IP_ARP, -- true, true); -+ ns3::CsmaNetDevice::IP_ARP, -+ true, true); - nd0->AddQueue(q); - nd0->Attach (ch); - return nd0->GetIfIndex (); -@@ -53,51 +53,50 @@ CsmaIpv4Topology::AddIpv4CsmaNode(Ptr n1, -- Ptr ch, -- Eui48Address addr) -+ Ptr ch, -+ Eui48Address addr) - { - Ptr q = Queue::CreateDefault (); - - Ptr nd0 = Create (n1, addr, -- ns3::CsmaNetDevice::LLC, -- true, false); -+ ns3::CsmaNetDevice::LLC, -+ true, false); - nd0->AddQueue(q); - nd0->Attach (ch); - - Ptr nd1 = Create (n1, addr, -- ns3::CsmaNetDevice::LLC, -- false, true); -+ ns3::CsmaNetDevice::LLC, -+ false, true); - nd1->AddQueue(q); - nd1->Attach (ch); - } - - void - CsmaIpv4Topology::AddIpv4RawCsmaNode(Ptr n1, -- Ptr ch, -- Eui48Address addr) -+ Ptr ch, -+ Eui48Address addr) - { - Ptr q = Queue::CreateDefault (); - - Ptr nd0 = Create (n1, addr, -- ns3::CsmaNetDevice::RAW, -- true, false); -+ ns3::CsmaNetDevice::RAW, -+ true, false); - nd0->AddQueue(q); - nd0->Attach (ch); - - Ptr nd1 = Create (n1, addr, -- ns3::CsmaNetDevice::RAW, -- false, true); -+ ns3::CsmaNetDevice::RAW, -+ false, true); - nd1->AddQueue(q); - nd1->Attach (ch); - } - - void - CsmaIpv4Topology::AddIpv4Address(Ptr n1, -- int ndNum, -- const Ipv4Address& addr1, -- const Ipv4Mask& netmask1) -+ int ndNum, -+ const Ipv4Address& addr1, -+ const Ipv4Mask& netmask1) - { -- - // Duplex link is assumed to be subnetted as a /30 - // May run this unnumbered in the future? - Ipv4Mask netmask(netmask1); -@@ -110,7 +109,6 @@ CsmaIpv4Topology::AddIpv4Address(PtrSetAddress (index1, addr1); - ip1->SetNetworkMask (index1, netmask); - ip1->SetUp (index1); -- - } - - void -@@ -133,7 +131,7 @@ CsmaIpv4Topology::AddIpv4Routes ( - found = true; - } - } -- NS_ASSERT(found); -+ NS_ASSERT (found); - - uint32_t index2 = 0; - found = false; -@@ -145,7 +143,7 @@ CsmaIpv4Topology::AddIpv4Routes ( - found = true; - } - } -- NS_ASSERT(found); -+ NS_ASSERT (found); - - ip1->AddHostRouteTo (ip2-> GetAddress (index2), index1); - ip2->AddHostRouteTo (ip1-> GetAddress (index1), index2); -diff -r 31cb0668defd -r 25fa26a6533e src/internet-node/arp-ipv4-interface.cc ---- a/src/internet-node/arp-ipv4-interface.cc Sun Aug 12 15:51:12 2007 -0700 -+++ b/src/internet-node/arp-ipv4-interface.cc Sun Aug 12 22:41:24 2007 -0700 -@@ -31,18 +31,26 @@ - #include "ipv4-l3-protocol.h" - #include "arp-l3-protocol.h" - -+NS_DEBUG_COMPONENT_DEFINE ("ArpIpv4Interface"); -+ - namespace ns3 { - - ArpIpv4Interface::ArpIpv4Interface (Ptr node, Ptr device) - : Ipv4Interface (device), - m_node (node) --{} -+{ -+ NS_DEBUG ("ArpIpv4Interface::ArpIpv4Interface ()"); -+} -+ - ArpIpv4Interface::~ArpIpv4Interface () --{} -+{ -+ NS_DEBUG ("ArpIpv4Interface::~ArpIpv4Interface ()"); -+} - - TraceResolver * - ArpIpv4Interface::DoCreateTraceResolver (TraceContext const &context) - { -+ NS_DEBUG ("ArpIpv4Interface::DoCreateTraceResolver ()"); - CompositeTraceResolver *resolver = new CompositeTraceResolver (context); - if (GetDevice () != 0) - { -@@ -56,31 +64,41 @@ void - void - ArpIpv4Interface::SendTo (Packet p, Ipv4Address dest) - { -+ NS_DEBUG ("ArpIpv4Interface::SendTo (" << &p << ", " << dest << ")"); -+ - NS_ASSERT (GetDevice () != 0); - if (GetDevice ()->NeedsArp ()) - { -- Ptr arp = m_node->QueryInterface (ArpL3Protocol::iid); -+ NS_DEBUG ("ArpIpv4Interface::SendTo (): Needs ARP"); -+ Ptr arp = -+ m_node->QueryInterface (ArpL3Protocol::iid); - Address hardwareDestination; - bool found; - - if (dest.IsBroadcast ()) - { -+ NS_DEBUG ("ArpIpv4Interface::SendTo (): IsBroadcast"); - hardwareDestination = GetDevice ()->GetBroadcast (); - found = true; - } - else - { -+ NS_DEBUG ("ArpIpv4Interface::SendTo (): ARP Lookup"); - found = arp->Lookup (p, dest, GetDevice (), &hardwareDestination); - } - - if (found) - { -- GetDevice ()->Send (p, hardwareDestination, Ipv4L3Protocol::PROT_NUMBER); -+ NS_DEBUG ("ArpIpv4Interface::SendTo (): Address Resolved. Send."); -+ GetDevice ()->Send (p, hardwareDestination, -+ Ipv4L3Protocol::PROT_NUMBER); - } - } - else - { -- GetDevice ()->Send (p, GetDevice ()->GetBroadcast (), Ipv4L3Protocol::PROT_NUMBER); -+ NS_DEBUG ("ArpIpv4Interface::SendTo (): Doesn't need ARP"); -+ GetDevice ()->Send (p, GetDevice ()->GetBroadcast (), -+ Ipv4L3Protocol::PROT_NUMBER); - } - } - -diff -r 31cb0668defd -r 25fa26a6533e src/internet-node/ipv4-interface.cc ---- a/src/internet-node/ipv4-interface.cc Sun Aug 12 15:51:12 2007 -0700 -+++ b/src/internet-node/ipv4-interface.cc Sun Aug 12 22:41:24 2007 -0700 -@@ -22,6 +22,9 @@ - #include "ipv4-interface.h" - #include "ns3/ipv4-address.h" - #include "ns3/net-device.h" -+#include "ns3/debug.h" -+ -+NS_DEBUG_COMPONENT_DEFINE ("Ipv4Interface"); - - namespace ns3 { - -@@ -34,56 +37,72 @@ Ipv4Interface::Ipv4Interface (Ptr nd) - : m_netdevice (nd), - m_ifup(false) --{} -+{ -+ NS_DEBUG ("Ipv4Interface::Ipv4Interface (" << &nd << ")"); -+} - - Ipv4Interface::~Ipv4Interface () --{} -+{ -+ NS_DEBUG ("Ipv4Interface::~Ipv4Interface ()"); -+} - - Ptr - Ipv4Interface::GetDevice (void) const - { -+ NS_DEBUG ("Ipv4Interface::GetDevice ()"); - return m_netdevice; - } - - TraceResolver * - Ipv4Interface::CreateTraceResolver (TraceContext const &context) - { -+ NS_DEBUG ("Ipv4Interface::CreateTraceResolver (" << &context << ")"); - return DoCreateTraceResolver (context); - } - - void - Ipv4Interface::SetAddress (Ipv4Address a) - { -+ NS_DEBUG ("Ipv4Interface::SetAddress (" << a << ")"); - m_address = a; - } -+ - void - Ipv4Interface::SetNetworkMask (Ipv4Mask mask) - { -+ NS_DEBUG ("Ipv4Interface::SetMask (" << mask << ")"); - m_netmask = mask; - } - - Ipv4Address - Ipv4Interface::GetBroadcast (void) const - { -+ NS_DEBUG ("Ipv4Interface::GetBroadcast ()"); -+ - uint32_t mask = m_netmask.GetHostOrder (); - uint32_t address = m_address.GetHostOrder (); - Ipv4Address broadcast = Ipv4Address (address | (~mask)); - return broadcast; - } -+ - Ipv4Mask - Ipv4Interface::GetNetworkMask (void) const - { -+ NS_DEBUG ("Ipv4Interface::GetNetworkMask ()"); - return m_netmask; - } -+ - Ipv4Address - Ipv4Interface::GetAddress (void) const - { -+ NS_DEBUG ("Ipv4Interface::Address ()"); - return m_address; - } - - uint16_t - Ipv4Interface::GetMtu (void) const - { -+ NS_DEBUG ("Ipv4Interface::GetMtu ()"); - if (m_netdevice == 0) - { - uint32_t mtu = (1<<16) - 1; -@@ -92,32 +111,36 @@ Ipv4Interface::GetMtu (void) const - return m_netdevice->GetMtu (); - } - -- /** -- * These are IP interface states and may be distinct from -- * NetDevice states, such as found in real implementations -- * (where the device may be down but IP interface state is still up). -- */ -+/** -+ * These are IP interface states and may be distinct from -+ * NetDevice states, such as found in real implementations -+ * (where the device may be down but IP interface state is still up). -+ */ - bool - Ipv4Interface::IsUp (void) const - { -+ NS_DEBUG ("Ipv4Interface::IsUp ()"); - return m_ifup; - } - - bool - Ipv4Interface::IsDown (void) const - { -+ NS_DEBUG ("Ipv4Interface::IsDown ()"); - return !m_ifup; - } - - void - Ipv4Interface::SetUp (void) - { -+ NS_DEBUG ("Ipv4Interface::SetUp ()"); - m_ifup = true; - } - - void - Ipv4Interface::SetDown (void) - { -+ NS_DEBUG ("Ipv4Interface::SetDown ()"); - m_ifup = false; - } - -@@ -125,7 +148,10 @@ void - void - Ipv4Interface::Send(Packet p, Ipv4Address dest) - { -+ NS_DEBUG ("Ipv4Interface::Send ()"); -+ - if (IsUp()) { -+ NS_DEBUG ("Ipv4Interface::Send (): SendTo ()"); - SendTo(p, dest); - } - } -diff -r 31cb0668defd -r 25fa26a6533e src/internet-node/ipv4-l3-protocol.cc ---- a/src/internet-node/ipv4-l3-protocol.cc Sun Aug 12 15:51:12 2007 -0700 -+++ b/src/internet-node/ipv4-l3-protocol.cc Sun Aug 12 22:41:24 2007 -0700 -@@ -494,24 +494,31 @@ Ipv4L3Protocol::SendRealOut (bool found, - - if (!found) - { -- NS_DEBUG ("no route to host. drop."); -+ NS_DEBUG ("Ipv4L3Protocol::SendRealOut (): No route to host. Drop."); - m_dropTrace (packet); - return; - } -+ -+ NS_DEBUG ("Ipv4L3Protocol::SendRealOut (): Send via interface " << -+ route.GetInterface ()); -+ - packet.AddHeader (ipHeader); - Ipv4Interface *outInterface = GetInterface (route.GetInterface ()); - NS_ASSERT (packet.GetSize () <= outInterface->GetMtu ()); - m_txTrace (packet, route.GetInterface ()); - if (route.IsGateway ()) - { -+ NS_DEBUG ("Ipv4L3Protocol::SendRealOut (): Send to gateway " << -+ route.GetGateway ()); - outInterface->Send (packet, route.GetGateway ()); - } - else - { -+ NS_DEBUG ("Ipv4L3Protocol::SendRealOut (): Send to destination " << -+ ipHeader.GetDestination ()); - outInterface->Send (packet, ipHeader.GetDestination ()); - } - } -- - - bool - Ipv4L3Protocol::Forwarding (Packet const &packet, Ipv4Header &ipHeader, Ptr device) -@@ -524,7 +531,8 @@ Ipv4L3Protocol::Forwarding (Packet const - { - if ((*i)->GetAddress ().IsEqual (ipHeader.GetDestination ())) - { -- NS_DEBUG ("for me 1"); -+ NS_DEBUG("Ipv4L3Protocol::Forwarding (): " -+ "For me (destination match)"); - return false; - } - } -@@ -537,7 +545,8 @@ Ipv4L3Protocol::Forwarding (Packet const - { - if (ipHeader.GetDestination ().IsEqual (interface->GetBroadcast ())) - { -- NS_DEBUG ("for me 2"); -+ NS_DEBUG("Ipv4L3Protocol::Forwarding (): " -+ "For me (interface broadcast address)"); - return false; - } - break; -@@ -546,25 +555,30 @@ Ipv4L3Protocol::Forwarding (Packet const - - if (ipHeader.GetDestination ().IsBroadcast ()) - { -- NS_DEBUG ("for me 3"); -+ NS_DEBUG("Ipv4L3Protocol::Forwarding (): " -+ "For me (Ipv4Addr broadcast address)"); - return false; - } -+ - if (ipHeader.GetDestination ().IsEqual (Ipv4Address::GetAny ())) - { -- NS_DEBUG ("for me 4"); -+ NS_DEBUG("Ipv4L3Protocol::Forwarding (): " -+ "For me (Ipv4Addr any address)"); - return false; - } -+ - if (ipHeader.GetTtl () == 1) - { - // Should send ttl expired here - // XXX -- NS_DEBUG ("not for me -- ttl expired. drop."); -+ NS_DEBUG("Ipv4L3Protocol::Forwarding (): " -+ "Not for me (TTL expired). Drop"); - m_dropTrace (packet); - return true; - } - ipHeader.SetTtl (ipHeader.GetTtl () - 1); - -- NS_DEBUG ("forwarding."); -+ NS_DEBUG("Ipv4L3Protocol::Forwarding (): Forwarding packet."); - Lookup (ipHeader, packet, - MakeCallback (&Ipv4L3Protocol::SendRealOut, this)); - // -@@ -578,12 +592,13 @@ Ipv4L3Protocol::Forwarding (Packet const - if ((*i).first.IsEqual (ipHeader.GetSource ()) && - (*i).second.IsEqual (ipHeader.GetDestination ())) - { -- NS_DEBUG ("for me 5"); -+ NS_DEBUG("Ipv4L3Protocol::Forwarding (): " -+ "For me (Joined multicast group)"); - return false; - } - } - -- NS_DEBUG ("not for me."); -+ NS_DEBUG("Ipv4L3Protocol::Forwarding (): Not for me."); - return true; - } - -diff -r 31cb0668defd -r 25fa26a6533e src/internet-node/ipv4-loopback-interface.cc ---- a/src/internet-node/ipv4-loopback-interface.cc Sun Aug 12 15:51:12 2007 -0700 -+++ b/src/internet-node/ipv4-loopback-interface.cc Sun Aug 12 22:41:24 2007 -0700 -@@ -19,6 +19,8 @@ - * Authors: - * Mathieu Lacage , - */ -+ -+#include "ns3/debug.h" - #include "ns3/empty-trace-resolver.h" - #include "ns3/net-device.h" - #include "ns3/node.h" -@@ -26,26 +28,40 @@ - #include "ipv4-loopback-interface.h" - #include "ipv4-l3-protocol.h" - -+NS_DEBUG_COMPONENT_DEFINE ("Ipv4LoopbackInterface"); -+ - namespace ns3 { - - Ipv4LoopbackInterface::Ipv4LoopbackInterface (Ptr node) - : Ipv4Interface (0), - m_node (node) --{} -+{ -+ NS_DEBUG("Ipv4LoopbackInterface::Ipv4LoopbackInterface ()"); -+} -+ - Ipv4LoopbackInterface::~Ipv4LoopbackInterface () --{} -+{ -+ NS_DEBUG("Ipv4LoopbackInterface::~Ipv4LoopbackInterface ()"); -+} - - TraceResolver * - Ipv4LoopbackInterface::DoCreateTraceResolver (TraceContext const &context) - { -+ NS_DEBUG("Ipv4LoopbackInterface::DoCreateTraceResolver ()"); - return new EmptyTraceResolver (context); - } - - void - Ipv4LoopbackInterface::SendTo (Packet packet, Ipv4Address dest) - { -- Ptr ipv4 = m_node->QueryInterface (Ipv4L3Protocol::iid); -- ipv4->Receive (GetDevice (), packet, Ipv4L3Protocol::PROT_NUMBER, Eui48Address ("ff:ff:ff:ff:ff:ff")); -+ NS_DEBUG("Ipv4LoopbackInterface::SendTo (" << &packet << ", " << -+ dest << ")"); -+ -+ Ptr ipv4 = -+ m_node->QueryInterface (Ipv4L3Protocol::iid); -+ -+ ipv4->Receive (GetDevice (), packet, Ipv4L3Protocol::PROT_NUMBER, -+ Eui48Address ("ff:ff:ff:ff:ff:ff")); - } - - }//namespace ns3 -diff -r 31cb0668defd -r 25fa26a6533e src/internet-node/ipv4-static-routing.cc ---- a/src/internet-node/ipv4-static-routing.cc Sun Aug 12 15:51:12 2007 -0700 -+++ b/src/internet-node/ipv4-static-routing.cc Sun Aug 12 22:41:24 2007 -0700 -@@ -26,7 +26,6 @@ NS_DEBUG_COMPONENT_DEFINE ("Ipv4StaticRo - NS_DEBUG_COMPONENT_DEFINE ("Ipv4StaticRouting"); - - namespace ns3 { -- - - void - Ipv4StaticRouting::AddHostRouteTo (Ipv4Address dest, -@@ -325,7 +324,6 @@ Ipv4StaticRouting::RequestRoute (Ipv4Hea - - NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): destination = " << - ipHeader.GetDestination ()); -- - // - // First, see if this is a multicast packet we have a route for. If we - // have a route, then send the packet down each of the specified interfaces. -@@ -334,12 +332,15 @@ Ipv4StaticRouting::RequestRoute (Ipv4Hea - ipHeader.GetDestination ()); - if (mRoute) - { -+ NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): Multicast route"); - for (uint32_t i = 0; i < mRoute->GetNOutputInterfaces (); ++i) - { - Packet p = packet; - Ipv4Route route = - Ipv4Route::CreateHostRouteTo(ipHeader.GetDestination (), - mRoute->GetOutputInterface(i)); -+ NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): " -+ "Send via interface " << mRoute->GetOutputInterface(i)); - routeReply (true, route, p, ipHeader); - return true; - } -@@ -347,6 +348,7 @@ Ipv4StaticRouting::RequestRoute (Ipv4Hea - // - // See if this is a unicast packet we have a route for. - // -+ NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): Unicast route"); - Ipv4Route *route = LookupStatic (ipHeader.GetDestination ()); - if (route != 0) - { - -changeset: 1283:3760d52ef5d1 -parent: 1280:25fa26a6533e -parent: 1282:03ab1b7ad2d0 -user: Craig Dowell -date: Sun Aug 12 22:43:25 2007 -0700 -summary: branch merge - -diff -r 25fa26a6533e -r 3760d52ef5d1 examples/mixed-global-routing.cc ---- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/examples/mixed-global-routing.cc Sun Aug 12 22:43:25 2007 -0700 -@@ -0,0 +1,199 @@ -+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ -+/* -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation; -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ */ -+ -+// This script exercises global routing code in a mixed point-to-point -+// and csma/cd environment -+// -+// Network topology -+// -+// n0 -+// \ p-p -+// \ (shared csma/cd) -+// n2 -------------------------n3 -+// / | | -+// / p-p n4 n5 ---------- n6 -+// n1 p-p -+// -+// - CBR/UDP flows from n0 to n6 -+// - Tracing of queues and packet receptions to file "mixed-global-routing.tr" -+ -+#include -+#include -+#include -+#include -+ -+#include "ns3/debug.h" -+ -+#include "ns3/command-line.h" -+#include "ns3/default-value.h" -+#include "ns3/ptr.h" -+#include "ns3/random-variable.h" -+ -+#include "ns3/simulator.h" -+#include "ns3/nstime.h" -+#include "ns3/data-rate.h" -+ -+#include "ns3/ascii-trace.h" -+#include "ns3/pcap-trace.h" -+#include "ns3/internet-node.h" -+#include "ns3/point-to-point-channel.h" -+#include "ns3/point-to-point-net-device.h" -+#include "ns3/csma-channel.h" -+#include "ns3/csma-net-device.h" -+#include "ns3/csma-topology.h" -+#include "ns3/csma-ipv4-topology.h" -+#include "ns3/eui48-address.h" -+#include "ns3/ipv4-address.h" -+#include "ns3/ipv4.h" -+#include "ns3/socket.h" -+#include "ns3/inet-socket-address.h" -+#include "ns3/ipv4-route.h" -+#include "ns3/point-to-point-topology.h" -+#include "ns3/onoff-application.h" -+#include "ns3/global-route-manager.h" -+ -+using namespace ns3; -+ -+int main (int argc, char *argv[]) -+{ -+ -+ // Users may find it convenient to turn on explicit debugging -+ // for selected modules; the below lines suggest how to do this -+#if 0 -+ DebugComponentEnable ("Object"); -+ DebugComponentEnable ("Queue"); -+ DebugComponentEnable ("DropTailQueue"); -+ DebugComponentEnable ("Channel"); -+ DebugComponentEnable ("PointToPointChannel"); -+ DebugComponentEnable ("PointToPointNetDevice"); -+ DebugComponentEnable ("GlobalRouter"); -+ DebugComponentEnable ("GlobalRouteManager"); -+#endif -+ -+ // Set up some default values for the simulation. Use the Bind () -+ // technique to tell the system what subclass of Queue to use, -+ // and what the queue limit is -+ -+ // The below DefaultValue::Bind command tells the queue factory which -+ // class to instantiate, when the queue factory is invoked in the -+ // topology code -+ DefaultValue::Bind ("Queue", "DropTailQueue"); -+ -+ DefaultValue::Bind ("OnOffApplicationPacketSize", "210"); -+ DefaultValue::Bind ("OnOffApplicationDataRate", "448kb/s"); -+ -+ //DefaultValue::Bind ("DropTailQueue::m_maxPackets", 30); -+ -+ // Allow the user to override any of the defaults and the above -+ // Bind ()s at run-time, via command-line arguments -+ CommandLine::Parse (argc, argv); -+ -+ Ptr n0 = Create (); -+ Ptr n1 = Create (); -+ Ptr n2 = Create (); -+ Ptr n3 = Create (); -+ Ptr n4 = Create (); -+ Ptr n5 = Create (); -+ Ptr n6 = Create (); -+ -+ // We create the channels first without any IP addressing information -+ Ptr channel0 = -+ PointToPointTopology::AddPointToPointLink ( -+ n0, n2, DataRate (5000000), MilliSeconds (2)); -+ -+ Ptr channel1 = -+ PointToPointTopology::AddPointToPointLink ( -+ n1, n2, DataRate (5000000), MilliSeconds (2)); -+ -+ Ptr channel2 = -+ PointToPointTopology::AddPointToPointLink ( -+ n5, n6, DataRate (1500000), MilliSeconds (10)); -+ -+ // We create the channels first without any IP addressing information -+ Ptr channelc0 = -+ CsmaTopology::CreateCsmaChannel( -+ DataRate(5000000), MilliSeconds(2)); -+ -+ uint32_t n2ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n2, channelc0, -+ Eui48Address("10:54:23:54:23:50")); -+ uint32_t n3ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n3, channelc0, -+ Eui48Address("10:54:23:54:23:51")); -+ uint32_t n4ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n4, channelc0, -+ Eui48Address("10:54:23:54:23:52")); -+ uint32_t n5ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n5, channelc0, -+ Eui48Address("10:54:23:54:23:53")); -+ -+ // Later, we add IP addresses. -+ PointToPointTopology::AddIpv4Addresses ( -+ channel0, n0, Ipv4Address ("10.1.1.1"), -+ n2, Ipv4Address ("10.1.1.2")); -+ -+ PointToPointTopology::AddIpv4Addresses ( -+ channel1, n1, Ipv4Address ("10.1.2.1"), -+ n2, Ipv4Address ("10.1.2.2")); -+ -+ PointToPointTopology::AddIpv4Addresses ( -+ channel2, n5, Ipv4Address ("10.1.3.1"), -+ n6, Ipv4Address ("10.1.3.2")); -+ -+ CsmaIpv4Topology::AddIpv4Address ( -+ n2, n2ifIndex, Ipv4Address("10.250.1.1"), Ipv4Mask("255.255.255.0")); -+ -+ CsmaIpv4Topology::AddIpv4Address ( -+ n3, n3ifIndex, Ipv4Address("10.250.1.2"), Ipv4Mask("255.255.255.0")); -+ -+ CsmaIpv4Topology::AddIpv4Address ( -+ n4, n4ifIndex, Ipv4Address("10.250.1.3"), Ipv4Mask("255.255.255.0")); -+ -+ CsmaIpv4Topology::AddIpv4Address ( -+ n5, n5ifIndex, Ipv4Address("10.250.1.4"), Ipv4Mask("255.255.255.0")); -+ -+ // Create router nodes, initialize routing database and set up the routing -+ // tables in the nodes. -+ GlobalRouteManager::PopulateRoutingTables (); -+ -+ // Create the OnOff application to send UDP datagrams of size -+ // 210 bytes at a rate of 448 Kb/s -+ Ptr ooff = Create ( -+ n0, -+ InetSocketAddress ("10.1.3.2", 80), -+ "Udp", -+ ConstantVariable (1), -+ ConstantVariable (0), -+ DataRate("300bps"), -+ 50); -+ // Start the application -+ ooff->Start (Seconds (1.0)); -+ ooff->Stop (Seconds (10.0)); -+ -+ // Configure tracing of all enqueue, dequeue, and NetDevice receive events -+ // Trace output will be sent to the simple-global-routing.tr file -+ AsciiTrace asciitrace ("mixed-global-routing.tr"); -+ asciitrace.TraceAllQueues (); -+ asciitrace.TraceAllNetDeviceRx (); -+ -+ // Also configure some tcpdump traces; each interface will be traced -+ // The output files will be named simple-p2p.pcap-- -+ // and can be read by the "tcpdump -r" command (use "-tt" option to -+ // display timestamps correctly) -+ PcapTrace pcaptrace ("mixed-global-routing.pcap"); -+ pcaptrace.TraceAllIp (); -+ -+ Simulator::Run (); -+ -+ Simulator::Destroy (); -+} -diff -r 25fa26a6533e -r 3760d52ef5d1 examples/wscript ---- a/examples/wscript Sun Aug 12 22:41:24 2007 -0700 -+++ b/examples/wscript Sun Aug 12 22:43:25 2007 -0700 -@@ -22,3 +22,6 @@ def build(bld): - ['csma', 'internet-node']) - obj.source = 'csma-multicast.cc' - -+ obj = bld.create_ns3_program( 'mixed-global-routing', -+ ['point-to-point', 'internet-node', 'global-routing' , 'csma-cd']) -+ obj.source = 'mixed-global-routing.cc' -diff -r 25fa26a6533e -r 3760d52ef5d1 src/devices/csma/csma-net-device.cc ---- a/src/devices/csma/csma-net-device.cc Sun Aug 12 22:41:24 2007 -0700 -+++ b/src/devices/csma/csma-net-device.cc Sun Aug 12 22:43:25 2007 -0700 -@@ -133,7 +133,6 @@ CsmaNetDevice::Init(bool sendEnable, boo - - EnableBroadcast (Eui48Address ("ff:ff:ff:ff:ff:ff")); - EnableMulticast(); -- EnablePointToPoint(); - - SetSendEnable (sendEnable); - SetReceiveEnable (receiveEnable); -diff -r 25fa26a6533e -r 3760d52ef5d1 src/routing/global-routing/global-route-manager-impl.cc ---- a/src/routing/global-routing/global-route-manager-impl.cc Sun Aug 12 22:41:24 2007 -0700 -+++ b/src/routing/global-routing/global-route-manager-impl.cc Sun Aug 12 22:43:25 2007 -0700 -@@ -48,8 +48,7 @@ SPFVertex::SPFVertex () : - { - } - --SPFVertex::SPFVertex (GlobalRouterLSA* lsa) : -- m_vertexType (VertexRouter), -+SPFVertex::SPFVertex (GlobalRoutingLSA* lsa) : - m_vertexId (lsa->GetLinkStateId ()), - m_lsa (lsa), - m_distanceFromRoot (SPF_INFINITY), -@@ -58,6 +57,16 @@ SPFVertex::SPFVertex (GlobalRouterLSA* l - m_parent (0), - m_children () - { -+ if (lsa->GetLSType () == GlobalRoutingLSA::RouterLSA) -+ { -+ NS_DEBUG ("SPFVertex:: setting m_vertexType to VertexRouter"); -+ m_vertexType = SPFVertex::VertexRouter; -+ } -+ else if (lsa->GetLSType () == GlobalRoutingLSA::NetworkLSA) -+ { -+ NS_DEBUG ("SPFVertex:: setting m_vertexType to VertexNetwork"); -+ m_vertexType = SPFVertex::VertexNetwork; -+ } - } - - SPFVertex::~SPFVertex () -@@ -99,12 +108,12 @@ SPFVertex::GetVertexId (void) const - } - - void --SPFVertex::SetLSA (GlobalRouterLSA* lsa) -+SPFVertex::SetLSA (GlobalRoutingLSA* lsa) - { - m_lsa = lsa; - } - -- GlobalRouterLSA* -+ GlobalRoutingLSA* - SPFVertex::GetLSA (void) const - { - return m_lsa; -@@ -210,7 +219,7 @@ GlobalRouteManagerLSDB::~GlobalRouteMana - for (i= m_database.begin (); i!= m_database.end (); i++) - { - NS_DEBUG ("GlobalRouteManagerLSDB::~GlobalRouteManagerLSDB ():free LSA"); -- GlobalRouterLSA* temp = i->second; -+ GlobalRoutingLSA* temp = i->second; - delete temp; - } - NS_DEBUG ("GlobalRouteManagerLSDB::~GlobalRouteManagerLSDB (): clear map"); -@@ -225,19 +234,19 @@ GlobalRouteManagerLSDB::Initialize () - LSDBMap_t::iterator i; - for (i= m_database.begin (); i!= m_database.end (); i++) - { -- GlobalRouterLSA* temp = i->second; -- temp->SetStatus (GlobalRouterLSA::LSA_SPF_NOT_EXPLORED); -+ GlobalRoutingLSA* temp = i->second; -+ temp->SetStatus (GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED); - } - } - - void --GlobalRouteManagerLSDB::Insert (Ipv4Address addr, GlobalRouterLSA* lsa) -+GlobalRouteManagerLSDB::Insert (Ipv4Address addr, GlobalRoutingLSA* lsa) - { - NS_DEBUG ("GlobalRouteManagerLSDB::Insert ()"); - m_database.insert (LSDBPair_t (addr, lsa)); - } - -- GlobalRouterLSA* -+ GlobalRoutingLSA* - GlobalRouteManagerLSDB::GetLSA (Ipv4Address addr) const - { - NS_DEBUG ("GlobalRouteManagerLSDB::GetLSA ()"); -@@ -252,6 +261,31 @@ GlobalRouteManagerLSDB::GetLSA (Ipv4Addr - return i->second; - } - } -+ return 0; -+} -+ -+ GlobalRoutingLSA* -+GlobalRouteManagerLSDB::GetLSAByLinkData (Ipv4Address addr) const -+{ -+ NS_DEBUG ("GlobalRouteManagerLSDB::GetLSAByLinkData ()"); -+// -+// Look up an LSA by its address. -+// -+ LSDBMap_t::const_iterator i; -+ for (i= m_database.begin (); i!= m_database.end (); i++) -+ { -+ GlobalRoutingLSA* temp = i->second; -+// Iterate among temp's Link Records -+ for (uint32_t j = 0; j < temp->GetNLinkRecords (); j++) -+ { -+ GlobalRoutingLinkRecord *lr = temp->GetLinkRecord (j); -+ if ( lr->GetLinkType () == GlobalRoutingLinkRecord::TransitNetwork && -+ lr->GetLinkData () == addr) -+ { -+ return temp; -+ } -+ } -+ } - return 0; - } - -@@ -359,13 +393,12 @@ GlobalRouteManagerImpl::BuildGlobalRouti - - for (uint32_t j = 0; j < numLSAs; ++j) - { -- GlobalRouterLSA* lsa = new GlobalRouterLSA (); -+ GlobalRoutingLSA* lsa = new GlobalRoutingLSA (); - // - // This is the call to actually fetch a Link State Advertisement from the - // router. - // - rtr->GetLSA (j, *lsa); -- NS_DEBUG ("LSA " << j); - NS_DEBUG (*lsa); - // - // Write the newly discovered link state advertisement to the database. -@@ -453,52 +486,86 @@ GlobalRouteManagerImpl::SPFNext (SPFVert - GlobalRouteManagerImpl::SPFNext (SPFVertex* v, CandidateQueue& candidate) - { - SPFVertex* w = 0; -- GlobalRouterLSA* w_lsa = 0; -+ GlobalRoutingLSA* w_lsa = 0; -+ GlobalRoutingLinkRecord *l = 0; - uint32_t distance = 0; -+ uint32_t numRecordsInVertex = 0; - - NS_DEBUG ("GlobalRouteManagerImpl::SPFNext ()"); --// --// Always true for now, since all our LSAs are RouterLSAs. --// -- if (v->GetVertexType () == SPFVertex::VertexRouter) -- { -- if (true) -+ -+// V points to a Router-LSA or Network-LSA -+// Loop over the links in router LSA or attached routers in Network LSA -+ if (v->GetVertexType () == SPFVertex::VertexRouter) -+ { -+ numRecordsInVertex = v->GetLSA ()->GetNLinkRecords (); -+ } -+ if (v->GetVertexType () == SPFVertex::VertexNetwork) -+ { -+ numRecordsInVertex = v->GetLSA ()->GetNAttachedRouters (); -+ } -+ -+ for (uint32_t i = 0; i < numRecordsInVertex; i++) -+ { -+// Get w_lsa: In case of V is Router-LSA -+ if (v->GetVertexType () == SPFVertex::VertexRouter) - { - NS_DEBUG ("SPFNext: Examining " << v->GetVertexId () << "'s " << - v->GetLSA ()->GetNLinkRecords () << " link records"); --// --// Walk the list of link records in the link state advertisement associated --// with the "current" router (represented by vertex ). --// -- for (uint32_t i = 0; i < v->GetLSA ()->GetNLinkRecords (); ++i) -- { - // - // (a) If this is a link to a stub network, examine the next link in V's LSA. - // Links to stub networks will be considered in the second stage of the - // shortest path calculation. - // -- GlobalRouterLinkRecord *l = v->GetLSA ()->GetLinkRecord (i); -- if (l->GetLinkType () == GlobalRouterLinkRecord::StubNetwork) -- { -- NS_DEBUG ("SPFNext: Found a Stub record to " << -- l->GetLinkId ()); -- continue; -- } -+ l = v->GetLSA ()->GetLinkRecord (i); -+ if (l->GetLinkType () == GlobalRoutingLinkRecord::StubNetwork) -+ { -+ NS_DEBUG ("SPFNext: Found a Stub record to " << -+ l->GetLinkId ()); -+ continue; -+ } - // - // (b) Otherwise, W is a transit vertex (router or transit network). Look up - // the vertex W's LSA (router-LSA or network-LSA) in Area A's link state - // database. - // -- if (l->GetLinkType () == GlobalRouterLinkRecord::PointToPoint) -- { -+ if (l->GetLinkType () == GlobalRoutingLinkRecord::PointToPoint) -+ { - // - // Lookup the link state advertisement of the new link -- we call it in - // the link state database. - // -- w_lsa = m_lsdb->GetLSA (l->GetLinkId ()); -- NS_ASSERT (w_lsa); -- NS_DEBUG ("SPFNext: Found a P2P record from " << -- v->GetVertexId () << " to " << w_lsa->GetLinkStateId ()); -+ w_lsa = m_lsdb->GetLSA (l->GetLinkId ()); -+ NS_ASSERT (w_lsa); -+ NS_DEBUG ("SPFNext: Found a P2P record from " << -+ v->GetVertexId () << " to " << w_lsa->GetLinkStateId ()); -+ } -+ else if (l->GetLinkType () == -+ GlobalRoutingLinkRecord::TransitNetwork) -+ { -+ w_lsa = m_lsdb->GetLSA (l->GetLinkId ()); -+ NS_ASSERT (w_lsa); -+ NS_DEBUG ("SPFNext: Found a Transit record from " << -+ v->GetVertexId () << " to " << w_lsa->GetLinkStateId ()); -+ } -+ else -+ { -+ NS_ASSERT_MSG (0, "illegal Link Type"); -+ } -+ } -+// Get w_lsa: In case of V is Network-LSA -+ if (v->GetVertexType () == SPFVertex::VertexNetwork) -+ { -+ w_lsa = m_lsdb->GetLSAByLinkData -+ (v->GetLSA ()->GetAttachedRouter (i)); -+ if (!w_lsa) -+ { -+ continue; -+ } -+ NS_DEBUG ("SPFNext: Found a Network LSA from " << -+ v->GetVertexId () << " to " << w_lsa->GetLinkStateId ()); -+ } -+ -+// Note: w_lsa at this point may be either RouterLSA or NetworkLSA - // - // (c) If vertex W is already on the shortest-path tree, examine the next - // link in the LSA. -@@ -506,57 +573,56 @@ GlobalRouteManagerImpl::SPFNext (SPFVert - // If the link is to a router that is already in the shortest path first tree - // then we have it covered -- ignore it. - // -- if (w_lsa->GetStatus () == -- GlobalRouterLSA::LSA_SPF_IN_SPFTREE) -- { -- NS_DEBUG ("SPFNext: Skipping-> LSA "<< -- w_lsa->GetLinkStateId () << " already in SPF tree"); -- continue; -- } --// --// The link is to a router we haven't dealt with yet. -+ if (w_lsa->GetStatus () == GlobalRoutingLSA::LSA_SPF_IN_SPFTREE) -+ { -+ NS_DEBUG ("SPFNext: Skipping-> LSA "<< -+ w_lsa->GetLinkStateId () << " already in SPF tree"); -+ continue; -+ } - // - // (d) Calculate the link state cost D of the resulting path from the root to - // vertex W. D is equal to the sum of the link state cost of the (already - // calculated) shortest path to vertex V and the advertised cost of the link - // between vertices V and W. - // -- distance = v->GetDistanceFromRoot () + l->GetMetric (); -- -- NS_DEBUG ("SPFNext: Considering w_lsa " << -- w_lsa->GetLinkStateId ()); -- -- if (w_lsa->GetStatus () == -- GlobalRouterLSA::LSA_SPF_NOT_EXPLORED) -- { --// --// If we haven't yet considered the link represented by we have to create --// a new SPFVertex to represent it. --// -- w = new SPFVertex (w_lsa); --// -+ if (v->GetLSA ()->GetLSType () == GlobalRoutingLSA::RouterLSA) -+ { -+ distance = v->GetDistanceFromRoot () + l->GetMetric (); -+ } -+ else -+ { -+ distance = v->GetDistanceFromRoot (); -+ } -+ -+ NS_DEBUG ("SPFNext: Considering w_lsa " << w_lsa->GetLinkStateId ()); -+ -+// Is there already vertex w in candidate list? -+ if (w_lsa->GetStatus () == GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED) -+ { -+ -+// prepare vertex w -+ w = new SPFVertex (w_lsa); -+// Calculate nexthop to w - // We need to figure out how to actually get to the new router represented - // by . This will (among other things) find the next hop address to send - // packets destined for this network to, and also find the outbound interface - // used to forward the packets. - // -- if (SPFNexthopCalculation (v, w, l, distance)) -- { -- w_lsa->SetStatus ( -- GlobalRouterLSA::LSA_SPF_CANDIDATE); -+ if (SPFNexthopCalculation (v, w, l, distance)) -+ { -+ w_lsa->SetStatus (GlobalRoutingLSA::LSA_SPF_CANDIDATE); - // - // Push this new vertex onto the priority queue (ordered by distance from the - // root node). - // -- candidate.Push (w); -- NS_DEBUG ("SPFNext: Pushing " << -- w->GetVertexId () << ", parent vertexId: " << -- v->GetVertexId ()); -- } -- } -- } else if (w_lsa->GetStatus () == -- GlobalRouterLSA::LSA_SPF_CANDIDATE) -- { -+ candidate.Push (w); -+ NS_DEBUG ("SPFNext: Pushing " << -+ w->GetVertexId () << ", parent vertexId: " << -+ v->GetVertexId ()); -+ } -+ } -+ else if (w_lsa->GetStatus () == GlobalRoutingLSA::LSA_SPF_CANDIDATE) -+ { - // - // We have already considered the link represented by . What wse have to - // do now is to decide if this new router represents a route with a shorter -@@ -564,23 +630,23 @@ GlobalRouteManagerImpl::SPFNext (SPFVert - // - // So, locate the vertex in the candidate queue and take a look at the - // distance. -- w = candidate.Find (w_lsa->GetLinkStateId ()); -- if (w->GetDistanceFromRoot () < distance) -- { -+ w = candidate.Find (w_lsa->GetLinkStateId ()); -+ if (w->GetDistanceFromRoot () < distance) -+ { - // - // This is not a shorter path, so don't do anything. - // -- continue; -- } -- else if (w->GetDistanceFromRoot () == distance) -- { -+ continue; -+ } -+ else if (w->GetDistanceFromRoot () == distance) -+ { - // - // This path is one with an equal cost. Do nothing for now -- we're not doing - // equal-cost multipath cases yet. - // -- } -- else -- { -+ } -+ else -+ { - // - // this path represents a new, lower-cost path to (the vertex we found in - // the current link record of the link state advertisement of the current root -@@ -589,27 +655,26 @@ GlobalRouteManagerImpl::SPFNext (SPFVert - // N.B. the nexthop_calculation is conditional, if it finds a valid nexthop - // it will call spf_add_parents, which will flush the old parents - // -- if (SPFNexthopCalculation (v, w, l, distance)) -- { -+ if (SPFNexthopCalculation (v, w, l, distance)) -+ { - // - // If we've changed the cost to get to the vertex represented by , we - // must reorder the priority queue keyed to that cost. - // -- candidate.Reorder (); -- } -- } -- } // point-to-point -- } // for loop -- } -- } -+ candidate.Reorder (); -+ } -+ } // new lower cost path found -+ } // end W is already on the candidate list -+ } // end loop over the links in V's LSA - } - - // - // This method is derived from quagga ospf_next_hop_calculation() 16.1.1. - // --// Calculate the next hop IP address and the outgoing interface required to --// get packets from the root through (parent) to vertex (destination), --// over a given distance. -+// Calculate nexthop from root through V (parent) to vertex W (destination) -+// with given distance from root->W. -+// -+// As appropriate, set w's parent, distance, and nexthop information - // - // For now, this is greatly simplified from the quagga code - // -@@ -617,10 +682,19 @@ GlobalRouteManagerImpl::SPFNexthopCalcul - GlobalRouteManagerImpl::SPFNexthopCalculation ( - SPFVertex* v, - SPFVertex* w, -- GlobalRouterLinkRecord* l, -+ GlobalRoutingLinkRecord* l, - uint32_t distance) - { - NS_DEBUG ("GlobalRouteManagerImpl::SPFNexthopCalculation ()"); -+ -+// If w is a NetworkVertex, l should be null -+/* -+ if (w->GetVertexType () == SPFVertex::VertexNetwork && l) -+ { -+ NS_ASSERT_MSG(0, "Error: SPFNexthopCalculation parameter problem"); -+ } -+*/ -+ - // - // The vertex m_spfroot is a distinguished vertex representing the node at - // the root of the calculations. That is, it is the node for which we are -@@ -669,7 +743,8 @@ GlobalRouteManagerImpl::SPFNexthopCalcul - // return the link record describing the link from to . Think of it as - // SPFGetLink. - // -- GlobalRouterLinkRecord *linkRemote = 0; -+ NS_ASSERT(l); -+ GlobalRoutingLinkRecord *linkRemote = 0; - linkRemote = SPFGetNextLink (w, v, linkRemote); - // - // At this point, is the Global Router Link Record describing the point- -@@ -695,6 +770,56 @@ GlobalRouteManagerImpl::SPFNexthopCalcul - v->GetVertexId () << " to " << w->GetVertexId () << - " goes through next hop " << w->GetNextHop () << - " via outgoing interface " << w->GetOutgoingInterfaceId ()); -+ } // end W is a router vertes -+ else -+ { -+ NS_ASSERT (w->GetVertexType () == SPFVertex::VertexNetwork); -+// W is a directly connected network; no next hop is required -+ GlobalRoutingLSA* w_lsa = w->GetLSA (); -+ NS_ASSERT (w_lsa->GetLSType () == GlobalRoutingLSA::NetworkLSA); -+// Find outgoing interface ID for this network -+ w->SetOutgoingInterfaceId ( -+ FindOutgoingInterfaceId (w_lsa->GetLinkStateId (), -+ w_lsa->GetNetworkLSANetworkMask () )); -+ w->SetDistanceFromRoot (distance); -+ w->SetParent (v); -+ NS_DEBUG ("SPFNexthopCalculation: Next hop from " << -+ v->GetVertexId () << " to network " << w->GetVertexId () << -+ " via outgoing interface " << w->GetOutgoingInterfaceId ()); -+ return 1; -+ } -+ } // end v is the root -+ else if (v->GetVertexType () == SPFVertex::VertexNetwork) -+ { -+// See if any of v's parents are the root -+ if (v->GetParent () == m_spfroot) -+ { -+// 16.1.1 para 5. ...the parent vertex is a network that -+// directly connects the calculating router to the destination -+// router. The list of next hops is then determined by -+// examining the destination's router-LSA... -+ NS_ASSERT (w->GetVertexType () == SPFVertex::VertexRouter); -+ GlobalRoutingLinkRecord *linkRemote = 0; -+ while ((linkRemote = SPFGetNextLink (w, v, linkRemote))) -+ { -+/* ...For each link in the router-LSA that points back to the -+ * parent network, the link's Link Data field provides the IP -+ * address of a next hop router. The outgoing interface to -+ * use can then be derived from the next hop IP address (or -+ * it can be inherited from the parent network). -+ */ -+ w->SetNextHop(linkRemote->GetLinkData ()); -+ w->SetOutgoingInterfaceId (v->GetOutgoingInterfaceId ()); -+ NS_DEBUG ("SPFNexthopCalculation: Next hop from " << -+ v->GetVertexId () << " to " << w->GetVertexId () << -+ " goes through next hop " << w->GetNextHop () << -+ " via outgoing interface " << w->GetOutgoingInterfaceId ()); -+ } -+ } -+ else -+ { -+ w->SetNextHop (v->GetNextHop ()); -+ w->SetOutgoingInterfaceId (v->GetOutgoingInterfaceId ()); - } - } - else -@@ -736,19 +861,17 @@ GlobalRouteManagerImpl::SPFNexthopCalcul - // to . If prev_link is not NULL, we return a Global Router Link Record - // representing a possible *second* link from to . - // --// BUGBUG FIXME: This seems to be a bug. Shouldn't this function look for --// any link records after pre_link and not just after the first? --// -- GlobalRouterLinkRecord* -+ GlobalRoutingLinkRecord* - GlobalRouteManagerImpl::SPFGetNextLink ( - SPFVertex* v, - SPFVertex* w, -- GlobalRouterLinkRecord* prev_link) -+ GlobalRoutingLinkRecord* prev_link) - { - NS_DEBUG ("GlobalRouteManagerImpl::SPFGetNextLink ()"); - - bool skip = true; -- GlobalRouterLinkRecord* l; -+ bool found_prev_link = false; -+ GlobalRoutingLinkRecord* l; - // - // If prev_link is 0, we are really looking for the first link, not the next - // link. -@@ -756,6 +879,7 @@ GlobalRouteManagerImpl::SPFGetNextLink ( - if (prev_link == 0) - { - skip = false; -+ found_prev_link = true; - } - // - // Iterate through the Global Router Link Records advertised by the vertex -@@ -765,10 +889,6 @@ GlobalRouteManagerImpl::SPFGetNextLink ( - for (uint32_t i = 0; i < v->GetLSA ()->GetNLinkRecords (); ++i) - { - l = v->GetLSA ()->GetLinkRecord (i); -- if (l->GetLinkType () != GlobalRouterLinkRecord::PointToPoint) -- { -- continue; -- } - // - // The link ID of a link record representing a point-to-point link is set to - // the router ID of the neighboring router -- the router to which the link -@@ -777,8 +897,16 @@ GlobalRouteManagerImpl::SPFGetNextLink ( - // We're just checking to see if the link is actually the link from to - // . - // -- if (l->GetLinkId () == w->GetVertexId ()) { -- NS_DEBUG ("SPFGetNextLink: Found matching link l: linkId = " << -+ if (l->GetLinkId () == w->GetVertexId ()) -+ { -+ if (!found_prev_link) -+ { -+ NS_DEBUG ("SPFGetNextLink: Skipping links before prev_link found"); -+ found_prev_link = true; -+ continue; -+ } -+ -+ NS_DEBUG ("SPFGetNextLink: Found matching link l: linkId = " << - l->GetLinkId () << " linkData = " << l->GetLinkData ()); - // - // If skip is false, don't (not too surprisingly) skip the link found -- it's -@@ -849,7 +977,7 @@ GlobalRouteManagerImpl::SPFCalculate (Ip - // - m_spfroot= v; - v->SetDistanceFromRoot (0); -- v->GetLSA ()->SetStatus (GlobalRouterLSA::LSA_SPF_IN_SPFTREE); -+ v->GetLSA ()->SetStatus (GlobalRoutingLSA::LSA_SPF_IN_SPFTREE); - - for (;;) - { -@@ -894,7 +1022,7 @@ GlobalRouteManagerImpl::SPFCalculate (Ip - // Update the status field of the vertex to indicate that it is in the SPF - // tree. - // -- v->GetLSA ()->SetStatus (GlobalRouterLSA::LSA_SPF_IN_SPFTREE); -+ v->GetLSA ()->SetStatus (GlobalRoutingLSA::LSA_SPF_IN_SPFTREE); - // - // The current vertex has a parent pointer. By calling this rather oddly - // named method (blame quagga) we add the current vertex to the list of -@@ -932,7 +1060,18 @@ GlobalRouteManagerImpl::SPFCalculate (Ip - // through its point-to-point links, adding a *host* route to the local IP - // address (at the side) for each of those links. - // -- SPFIntraAddRouter (v); -+ if (v->GetVertexType () == SPFVertex::VertexRouter) -+ { -+ SPFIntraAddRouter (v); -+ } -+ else if (v->GetVertexType () == SPFVertex::VertexNetwork) -+ { -+ SPFIntraAddTransit (v); -+ } -+ else -+ { -+ NS_ASSERT_MSG(0, "illegal SPFVertex type"); -+ } - // - // RFC2328 16.1. (5). - // -@@ -1026,6 +1165,80 @@ GlobalRouteManagerImpl::FindOutgoingInte - } - - // -+// XXX This should probably be a method on Ipv4 -+// -+// Return the interface index corresponding to a given IP address -+// -+ uint32_t -+GlobalRouteManagerImpl::FindOutgoingInterfaceId (Ipv4Address a, Ipv4Mask amask) -+{ -+// -+// We have an IP address and a vertex ID of the root of the SPF tree. -+// The question is what interface index does this address correspond to. -+// The answer is a little complicated since we have to find a pointer to -+// the node corresponding to the vertex ID, find the Ipv4 interface on that -+// node in order to iterate the interfaces and find the one corresponding to -+// the address in question. -+// -+ Ipv4Address routerId = m_spfroot->GetVertexId (); -+// -+// Walk the list of nodes in the system looking for the one corresponding to -+// the node at the root of the SPF tree. This is the node for which we are -+// building the routing table. -+// -+ std::vector >::iterator i = NodeList::Begin (); -+ for (; i != NodeList::End (); i++) -+ { -+ Ptr node = *i; -+ -+ Ptr rtr = -+ node->QueryInterface (GlobalRouter::iid); -+// -+// If the node doesn't have a GlobalRouter interface it can't be the one -+// we're interested in. -+// -+ if (rtr == 0) -+ { -+ continue; -+ } -+ -+ if (rtr->GetRouterId () == routerId) -+ { -+// -+// This is the node we're building the routing table for. We're going to need -+// the Ipv4 interface to look for the ipv4 interface index. Since this node -+// is participating in routing IP version 4 packets, it certainly must have -+// an Ipv4 interface. -+// -+ Ptr ipv4 = node->QueryInterface (Ipv4::iid); -+ NS_ASSERT_MSG (ipv4, -+ "GlobalRouteManagerImpl::FindOutgoingInterfaceId (): " -+ "QI for interface failed"); -+// -+// Look through the interfaces on this node for one that has the IP address -+// we're looking for. If we find one, return the corresponding interface -+// index. -+// -+ for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i++) -+ { -+ if (ipv4->GetAddress (i).CombineMask(amask) == -+ a.CombineMask(amask) ) -+ { -+ NS_DEBUG ( -+ "GlobalRouteManagerImpl::FindOutgoingInterfaceId (): " -+ "Interface match for " << a); -+ return i; -+ } -+ } -+ } -+ } -+// -+// Couldn't find it. -+// -+ return 0; -+} -+ -+// - // This method is derived from quagga ospf_intra_add_router () - // - // This is where we are actually going to add the host routes to the routing -@@ -1109,7 +1322,7 @@ GlobalRouteManagerImpl::SPFIntraAddRoute - // Link Records corresponding to links off of that vertex / node. We're going - // to be interested in the records corresponding to point-to-point links. - // -- GlobalRouterLSA *lsa = v->GetLSA (); -+ GlobalRoutingLSA *lsa = v->GetLSA (); - NS_ASSERT_MSG (lsa, - "GlobalRouteManagerImpl::SPFIntraAddRouter (): " - "Expected valid LSA in SPFVertex* v"); -@@ -1128,8 +1341,8 @@ GlobalRouteManagerImpl::SPFIntraAddRoute - // - // We are only concerned about point-to-point links - // -- GlobalRouterLinkRecord *lr = lsa->GetLinkRecord (j); -- if (lr->GetLinkType () != GlobalRouterLinkRecord::PointToPoint) -+ GlobalRoutingLinkRecord *lr = lsa->GetLinkRecord (j); -+ if (lr->GetLinkType () != GlobalRoutingLinkRecord::PointToPoint) - { - continue; - } -@@ -1161,6 +1374,91 @@ GlobalRouteManagerImpl::SPFIntraAddRoute - return; - } - } -+} -+ void -+GlobalRouteManagerImpl::SPFIntraAddTransit (SPFVertex* v) -+{ -+ NS_DEBUG ("GlobalRouteManagerImpl::SPFIntraAddTransit ()"); -+ -+ NS_ASSERT_MSG (m_spfroot, -+ "GlobalRouteManagerImpl::SPFIntraAddTransit (): Root pointer not set"); -+// -+// The root of the Shortest Path First tree is the router to which we are -+// going to write the actual routing table entries. The vertex corresponding -+// to this router has a vertex ID which is the router ID of that node. We're -+// going to use this ID to discover which node it is that we're actually going -+// to update. -+// -+ Ipv4Address routerId = m_spfroot->GetVertexId (); -+ -+ NS_DEBUG ("GlobalRouteManagerImpl::SPFIntraAddTransit (): " -+ "Vertex ID = " << routerId); -+// -+// We need to walk the list of nodes looking for the one that has the router -+// ID corresponding to the root vertex. This is the one we're going to write -+// the routing information to. -+// -+ std::vector >::iterator i = NodeList::Begin (); -+ for (; i != NodeList::End (); i++) -+ { -+ Ptr node = *i; -+// -+// The router ID is accessible through the GlobalRouter interface, so we need -+// to QI for that interface. If there's no GlobalRouter interface, the node -+// in question cannot be the router we want, so we continue. -+// -+ Ptr rtr = -+ node->QueryInterface (GlobalRouter::iid); -+ -+ if (rtr == 0) -+ { -+ NS_DEBUG ("GlobalRouteManagerImpl::SPFIntraAddTransit (): " -+ "No GlobalRouter interface on node " << node->GetId ()); -+ continue; -+ } -+// -+// If the router ID of the current node is equal to the router ID of the -+// root of the SPF tree, then this node is the one for which we need to -+// write the routing tables. -+// -+ NS_DEBUG ("GlobalRouteManagerImpl::SPFIntraAddTransit (): " -+ "Considering router " << rtr->GetRouterId ()); -+ -+ if (rtr->GetRouterId () == routerId) -+ { -+ NS_DEBUG ("GlobalRouteManagerImpl::SPFIntraAddTransit (): " -+ "setting routes for node " << node->GetId ()); -+// -+// Routing information is updated using the Ipv4 interface. We need to QI -+// for that interface. If the node is acting as an IP version 4 router, it -+// should absolutely have an Ipv4 interface. -+// -+ Ptr ipv4 = node->QueryInterface (Ipv4::iid); -+ NS_ASSERT_MSG (ipv4, -+ "GlobalRouteManagerImpl::SPFIntraAddTransit (): " -+ "QI for interface failed"); -+// -+// Get the Global Router Link State Advertisement from the vertex we're -+// adding the routes to. The LSA will have a number of attached Global Router -+// Link Records corresponding to links off of that vertex / node. We're going -+// to be interested in the records corresponding to point-to-point links. -+// -+ GlobalRoutingLSA *lsa = v->GetLSA (); -+ NS_ASSERT_MSG (lsa, -+ "GlobalRouteManagerImpl::SPFIntraAddTransit (): " -+ "Expected valid LSA in SPFVertex* v"); -+ Ipv4Mask tempmask = lsa->GetNetworkLSANetworkMask (); -+ Ipv4Address tempip = lsa->GetLinkStateId (); -+ tempip = tempip.CombineMask (tempmask); -+ ipv4->AddNetworkRouteTo (tempip, tempmask, v->GetNextHop (), -+ v->GetOutgoingInterfaceId ()); -+ NS_DEBUG ("GlobalRouteManagerImpl::SPFIntraAddNetwork (): " -+ " Node " << node->GetId () << -+ " add network route to " << tempip << -+ " using next hop " << v->GetNextHop () << -+ " via interface " << v->GetOutgoingInterfaceId ()); -+ } -+ } - } - - // Derived from quagga ospf_vertex_add_parents () -@@ -1275,81 +1573,81 @@ GlobalRouteManagerImplTest::RunTests (vo - // link2: 10.1.3.1/30, 10.1.3.2/30 - // - // Router 0 -- GlobalRouterLinkRecord* lr0 = new GlobalRouterLinkRecord ( -- GlobalRouterLinkRecord::PointToPoint, -+ GlobalRoutingLinkRecord* lr0 = new GlobalRoutingLinkRecord ( -+ GlobalRoutingLinkRecord::PointToPoint, - "0.0.0.2", // router ID 0.0.0.2 - "10.1.1.1", // local ID - 1); // metric - -- GlobalRouterLinkRecord* lr1 = new GlobalRouterLinkRecord ( -- GlobalRouterLinkRecord::StubNetwork, -+ GlobalRoutingLinkRecord* lr1 = new GlobalRoutingLinkRecord ( -+ GlobalRoutingLinkRecord::StubNetwork, - "10.1.1.1", - "255.255.255.252", - 1); - -- GlobalRouterLSA* lsa0 = new GlobalRouterLSA (); -+ GlobalRoutingLSA* lsa0 = new GlobalRoutingLSA (); - lsa0->SetLinkStateId ("0.0.0.0"); - lsa0->SetAdvertisingRouter ("0.0.0.0"); - lsa0->AddLinkRecord (lr0); - lsa0->AddLinkRecord (lr1); - - // Router 1 -- GlobalRouterLinkRecord* lr2 = new GlobalRouterLinkRecord ( -- GlobalRouterLinkRecord::PointToPoint, -+ GlobalRoutingLinkRecord* lr2 = new GlobalRoutingLinkRecord ( -+ GlobalRoutingLinkRecord::PointToPoint, - "0.0.0.2", - "10.1.2.1", - 1); - -- GlobalRouterLinkRecord* lr3 = new GlobalRouterLinkRecord ( -- GlobalRouterLinkRecord::StubNetwork, -+ GlobalRoutingLinkRecord* lr3 = new GlobalRoutingLinkRecord ( -+ GlobalRoutingLinkRecord::StubNetwork, - "10.1.2.1", - "255.255.255.252", - 1); - -- GlobalRouterLSA* lsa1 = new GlobalRouterLSA (); -+ GlobalRoutingLSA* lsa1 = new GlobalRoutingLSA (); - lsa1->SetLinkStateId ("0.0.0.1"); - lsa1->SetAdvertisingRouter ("0.0.0.1"); - lsa1->AddLinkRecord (lr2); - lsa1->AddLinkRecord (lr3); - - // Router 2 -- GlobalRouterLinkRecord* lr4 = new GlobalRouterLinkRecord ( -- GlobalRouterLinkRecord::PointToPoint, -+ GlobalRoutingLinkRecord* lr4 = new GlobalRoutingLinkRecord ( -+ GlobalRoutingLinkRecord::PointToPoint, - "0.0.0.0", - "10.1.1.2", - 1); - -- GlobalRouterLinkRecord* lr5 = new GlobalRouterLinkRecord ( -- GlobalRouterLinkRecord::StubNetwork, -+ GlobalRoutingLinkRecord* lr5 = new GlobalRoutingLinkRecord ( -+ GlobalRoutingLinkRecord::StubNetwork, - "10.1.1.2", - "255.255.255.252", - 1); - -- GlobalRouterLinkRecord* lr6 = new GlobalRouterLinkRecord ( -- GlobalRouterLinkRecord::PointToPoint, -+ GlobalRoutingLinkRecord* lr6 = new GlobalRoutingLinkRecord ( -+ GlobalRoutingLinkRecord::PointToPoint, - "0.0.0.1", - "10.1.2.2", - 1); - -- GlobalRouterLinkRecord* lr7 = new GlobalRouterLinkRecord ( -- GlobalRouterLinkRecord::StubNetwork, -+ GlobalRoutingLinkRecord* lr7 = new GlobalRoutingLinkRecord ( -+ GlobalRoutingLinkRecord::StubNetwork, - "10.1.2.2", - "255.255.255.252", - 1); - -- GlobalRouterLinkRecord* lr8 = new GlobalRouterLinkRecord ( -- GlobalRouterLinkRecord::PointToPoint, -+ GlobalRoutingLinkRecord* lr8 = new GlobalRoutingLinkRecord ( -+ GlobalRoutingLinkRecord::PointToPoint, - "0.0.0.3", - "10.1.3.2", - 1); - -- GlobalRouterLinkRecord* lr9 = new GlobalRouterLinkRecord ( -- GlobalRouterLinkRecord::StubNetwork, -+ GlobalRoutingLinkRecord* lr9 = new GlobalRoutingLinkRecord ( -+ GlobalRoutingLinkRecord::StubNetwork, - "10.1.3.2", - "255.255.255.252", - 1); - -- GlobalRouterLSA* lsa2 = new GlobalRouterLSA (); -+ GlobalRoutingLSA* lsa2 = new GlobalRoutingLSA (); - lsa2->SetLinkStateId ("0.0.0.2"); - lsa2->SetAdvertisingRouter ("0.0.0.2"); - lsa2->AddLinkRecord (lr4); -@@ -1360,19 +1658,19 @@ GlobalRouteManagerImplTest::RunTests (vo - lsa2->AddLinkRecord (lr9); - - // Router 3 -- GlobalRouterLinkRecord* lr10 = new GlobalRouterLinkRecord ( -- GlobalRouterLinkRecord::PointToPoint, -+ GlobalRoutingLinkRecord* lr10 = new GlobalRoutingLinkRecord ( -+ GlobalRoutingLinkRecord::PointToPoint, - "0.0.0.2", - "10.1.2.1", - 1); - -- GlobalRouterLinkRecord* lr11 = new GlobalRouterLinkRecord ( -- GlobalRouterLinkRecord::StubNetwork, -+ GlobalRoutingLinkRecord* lr11 = new GlobalRoutingLinkRecord ( -+ GlobalRoutingLinkRecord::StubNetwork, - "10.1.2.1", - "255.255.255.252", - 1); - -- GlobalRouterLSA* lsa3 = new GlobalRouterLSA (); -+ GlobalRoutingLSA* lsa3 = new GlobalRoutingLSA (); - lsa3->SetLinkStateId ("0.0.0.3"); - lsa3->SetAdvertisingRouter ("0.0.0.3"); - lsa3->AddLinkRecord (lr10); -diff -r 25fa26a6533e -r 3760d52ef5d1 src/routing/global-routing/global-route-manager-impl.h ---- a/src/routing/global-routing/global-route-manager-impl.h Sun Aug 12 22:41:24 2007 -0700 -+++ b/src/routing/global-routing/global-route-manager-impl.h Sun Aug 12 22:43:25 2007 -0700 -@@ -102,10 +102,10 @@ public: - * - * @see SPFVertex::SPFVertex () - * @see VertexType -- * @see GlobalRouterLSA -+ * @see GlobalRoutingLSA - * @param lsa The Link State Advertisement used for finding initial values. - */ -- SPFVertex(GlobalRouterLSA* lsa); -+ SPFVertex(GlobalRoutingLSA* lsa); - - /** - * @brief Destroy an SPFVertex (Shortest Path First Vertex). -@@ -181,12 +181,12 @@ public: - * @internal - * - * @see GlobalRouter -- * @see GlobalRouterLSA -+ * @see GlobalRoutingLSA - * @see GlobalRouter::DiscoverLSAs () -- * @returns A pointer to the GlobalRouterLSA found by the router represented -+ * @returns A pointer to the GlobalRoutingLSA found by the router represented - * by this SPFVertex object. - */ -- GlobalRouterLSA* GetLSA (void) const; -+ GlobalRoutingLSA* GetLSA (void) const; - - /** - * @brief Set the Global Router Link State Advertisement returned by the -@@ -196,13 +196,13 @@ public: - * - * @see SPFVertex::GetLSA () - * @see GlobalRouter -- * @see GlobalRouterLSA -+ * @see GlobalRoutingLSA - * @see GlobalRouter::DiscoverLSAs () - * @warning Ownership of the LSA is transferred to the "this" SPFVertex. You - * must not delete the LSA after calling this method. -- * @param lsa A pointer to the GlobalRouterLSA. -- */ -- void SetLSA (GlobalRouterLSA* lsa); -+ * @param lsa A pointer to the GlobalRoutingLSA. -+ */ -+ void SetLSA (GlobalRoutingLSA* lsa); - - /** - * @brief Get the distance from the root vertex to "this" SPFVertex object. -@@ -283,8 +283,8 @@ public: - * SPFVertex." - * - * @see GlobalRouter -- * @see GlobalRouterLSA -- * @see GlobalRouterLinkRecord -+ * @see GlobalRoutingLSA -+ * @see GlobalRoutingLinkRecord - * @returns The interface index to use when forwarding packets to the host - * or network represented by "this" SPFVertex. - */ -@@ -325,8 +325,8 @@ public: - * by "this" SPFVertex. - * - * @see GlobalRouter -- * @see GlobalRouterLSA -- * @see GlobalRouterLinkRecord -+ * @see GlobalRoutingLSA -+ * @see GlobalRoutingLinkRecord - * @param id The interface index to use when forwarding packets to the host or - * network represented by "this" SPFVertex. - */ -@@ -368,8 +368,8 @@ public: - * by 'this' SPFVertex." - * - * @see GlobalRouter -- * @see GlobalRouterLSA -- * @see GlobalRouterLinkRecord -+ * @see GlobalRoutingLSA -+ * @see GlobalRoutingLinkRecord - * @returns The IP address to use when forwarding packets to the host - * or network represented by "this" SPFVertex. - */ -@@ -411,8 +411,8 @@ public: - * host represented by 'this' SPFVertex." - * - * @see GlobalRouter -- * @see GlobalRouterLSA -- * @see GlobalRouterLinkRecord -+ * @see GlobalRoutingLSA -+ * @see GlobalRoutingLinkRecord - * @param nextHop The IP address to use when forwarding packets to the host - * or network represented by "this" SPFVertex. - */ -@@ -543,7 +543,7 @@ private: - private: - VertexType m_vertexType; - Ipv4Address m_vertexId; -- GlobalRouterLSA* m_lsa; -+ GlobalRoutingLSA* m_lsa; - uint32_t m_distanceFromRoot; - uint32_t m_rootOif; - Ipv4Address m_nextHop; -@@ -604,33 +604,47 @@ public: - * State Database. - * @internal - * -- * The IPV4 address and the GlobalRouterLSA given as parameters are converted -+ * The IPV4 address and the GlobalRoutingLSA given as parameters are converted - * to an STL pair and are inserted into the database map. - * -- * @see GlobalRouterLSA -+ * @see GlobalRoutingLSA - * @see Ipv4Address - * @param addr The IP address associated with the LSA. Typically the Router - * ID. - * @param lsa A pointer to the Link State Advertisement for the router. - */ -- void Insert(Ipv4Address addr, GlobalRouterLSA* lsa); -+ void Insert(Ipv4Address addr, GlobalRoutingLSA* lsa); - - /** - * @brief Look up the Link State Advertisement associated with the given -- * IP Address. -+ * link state ID (address). - * @internal - * - * The database map is searched for the given IPV4 address and corresponding -- * GlobalRouterLSA is returned. -- * -- * @see GlobalRouterLSA -+ * GlobalRoutingLSA is returned. -+ * -+ * @see GlobalRoutingLSA - * @see Ipv4Address - * @param addr The IP address associated with the LSA. Typically the Router - * ID. - * @returns A pointer to the Link State Advertisement for the router specified - * by the IP address addr. - */ -- GlobalRouterLSA* GetLSA (Ipv4Address addr) const; -+ GlobalRoutingLSA* GetLSA (Ipv4Address addr) const; -+/** -+ * @brief Look up the Link State Advertisement associated with the given -+ * link state ID (address). This is a variation of the GetLSA call -+ * to allow the LSA to be found by matching addr with the LinkData field -+ * of the TransitNetwork link record. -+ * @internal -+ * -+ * @see GetLSA -+ * @param addr The IP address associated with the LSA. Typically the Router -+ * @returns A pointer to the Link State Advertisement for the router specified -+ * by the IP address addr. -+ * ID. -+ */ -+ GlobalRoutingLSA* GetLSAByLinkData (Ipv4Address addr) const; - - /** - * @brief Set all LSA flags to an initialized state, for SPF computation -@@ -641,14 +655,14 @@ public: - * prior to each SPF calculation to reset the state of the SPFVertex structures - * that will reference the LSAs during the calculation. - * -- * @see GlobalRouterLSA -+ * @see GlobalRoutingLSA - * @see SPFVertex - */ - void Initialize (); - - private: -- typedef std::map LSDBMap_t; -- typedef std::pair LSDBPair_t; -+ typedef std::map LSDBMap_t; -+ typedef std::pair LSDBPair_t; - - LSDBMap_t m_database; - /** -@@ -734,12 +748,14 @@ private: - void SPFCalculate (Ipv4Address root); - void SPFNext (SPFVertex*, CandidateQueue&); - int SPFNexthopCalculation (SPFVertex* v, SPFVertex* w, -- GlobalRouterLinkRecord* l, uint32_t distance); -+ GlobalRoutingLinkRecord* l, uint32_t distance); - void SPFVertexAddParent (SPFVertex* v); -- GlobalRouterLinkRecord* SPFGetNextLink (SPFVertex* v, SPFVertex* w, -- GlobalRouterLinkRecord* prev_link); -+ GlobalRoutingLinkRecord* SPFGetNextLink (SPFVertex* v, SPFVertex* w, -+ GlobalRoutingLinkRecord* prev_link); - void SPFIntraAddRouter (SPFVertex* v); -+ void SPFIntraAddTransit (SPFVertex* v); - uint32_t FindOutgoingInterfaceId (Ipv4Address a); -+ uint32_t FindOutgoingInterfaceId (Ipv4Address a, Ipv4Mask amask); - }; - - } // namespace ns3 -diff -r 25fa26a6533e -r 3760d52ef5d1 src/routing/global-routing/global-router-interface.cc ---- a/src/routing/global-routing/global-router-interface.cc Sun Aug 12 22:41:24 2007 -0700 -+++ b/src/routing/global-routing/global-router-interface.cc Sun Aug 12 22:43:25 2007 -0700 -@@ -28,21 +28,21 @@ namespace ns3 { - - // --------------------------------------------------------------------------- - // --// GlobalRouterLinkRecord Implementation -+// GlobalRoutingLinkRecord Implementation - // - // --------------------------------------------------------------------------- - --GlobalRouterLinkRecord::GlobalRouterLinkRecord () -+GlobalRoutingLinkRecord::GlobalRoutingLinkRecord () - : - m_linkId ("0.0.0.0"), - m_linkData ("0.0.0.0"), - m_linkType (Unknown), - m_metric (0) - { -- NS_DEBUG("GlobalRouterLinkRecord::GlobalRouterLinkRecord ()"); --} -- --GlobalRouterLinkRecord::GlobalRouterLinkRecord ( -+ NS_DEBUG("GlobalRoutingLinkRecord::GlobalRoutingLinkRecord ()"); -+} -+ -+GlobalRoutingLinkRecord::GlobalRoutingLinkRecord ( - LinkType linkType, - Ipv4Address linkId, - Ipv4Address linkData, -@@ -53,116 +53,126 @@ GlobalRouterLinkRecord::GlobalRouterLink - m_linkType (linkType), - m_metric (metric) - { -- NS_DEBUG("GlobalRouterLinkRecord::GlobalRouterLinkRecord (" << -+ NS_DEBUG("GlobalRoutingLinkRecord::GlobalRoutingLinkRecord (" << - linkType << ", " << linkId << ", " << linkData << ", " << metric << ")"); - } - --GlobalRouterLinkRecord::~GlobalRouterLinkRecord () --{ -- NS_DEBUG("GlobalRouterLinkRecord::~GlobalRouterLinkRecord ()"); -+GlobalRoutingLinkRecord::~GlobalRoutingLinkRecord () -+{ -+ NS_DEBUG("GlobalRoutingLinkRecord::~GlobalRoutingLinkRecord ()"); - } - - Ipv4Address --GlobalRouterLinkRecord::GetLinkId (void) const --{ -- NS_DEBUG("GlobalRouterLinkRecord::GetLinkId ()"); -+GlobalRoutingLinkRecord::GetLinkId (void) const -+{ -+ NS_DEBUG("GlobalRoutingLinkRecord::GetLinkId ()"); - return m_linkId; - } - - void --GlobalRouterLinkRecord::SetLinkId (Ipv4Address addr) --{ -- NS_DEBUG("GlobalRouterLinkRecord::SetLinkId ()"); -+GlobalRoutingLinkRecord::SetLinkId (Ipv4Address addr) -+{ -+ NS_DEBUG("GlobalRoutingLinkRecord::SetLinkId ()"); - m_linkId = addr; - } - - Ipv4Address --GlobalRouterLinkRecord::GetLinkData (void) const --{ -- NS_DEBUG("GlobalRouterLinkRecord::GetLinkData ()"); -+GlobalRoutingLinkRecord::GetLinkData (void) const -+{ -+ NS_DEBUG("GlobalRoutingLinkRecord::GetLinkData ()"); - return m_linkData; - } - - void --GlobalRouterLinkRecord::SetLinkData (Ipv4Address addr) --{ -- NS_DEBUG("GlobalRouterLinkRecord::SetLinkData ()"); -+GlobalRoutingLinkRecord::SetLinkData (Ipv4Address addr) -+{ -+ NS_DEBUG("GlobalRoutingLinkRecord::SetLinkData ()"); - m_linkData = addr; - } - -- GlobalRouterLinkRecord::LinkType --GlobalRouterLinkRecord::GetLinkType (void) const --{ -- NS_DEBUG("GlobalRouterLinkRecord::GetLinkType ()"); -+ GlobalRoutingLinkRecord::LinkType -+GlobalRoutingLinkRecord::GetLinkType (void) const -+{ -+ NS_DEBUG("GlobalRoutingLinkRecord::GetLinkType ()"); - return m_linkType; - } - - void --GlobalRouterLinkRecord::SetLinkType ( -- GlobalRouterLinkRecord::LinkType linkType) --{ -- NS_DEBUG("GlobalRouterLinkRecord::SetLinkType ()"); -+GlobalRoutingLinkRecord::SetLinkType ( -+ GlobalRoutingLinkRecord::LinkType linkType) -+{ -+ NS_DEBUG("GlobalRoutingLinkRecord::SetLinkType ()"); - m_linkType = linkType; - } - - uint32_t --GlobalRouterLinkRecord::GetMetric (void) const --{ -- NS_DEBUG("GlobalRouterLinkRecord::GetMetric ()"); -+GlobalRoutingLinkRecord::GetMetric (void) const -+{ -+ NS_DEBUG("GlobalRoutingLinkRecord::GetMetric ()"); - return m_metric; - } - - void --GlobalRouterLinkRecord::SetMetric (uint32_t metric) --{ -- NS_DEBUG("GlobalRouterLinkRecord::SetMetric ()"); -+GlobalRoutingLinkRecord::SetMetric (uint32_t metric) -+{ -+ NS_DEBUG("GlobalRoutingLinkRecord::SetMetric ()"); - m_metric = metric; - } - - // --------------------------------------------------------------------------- - // --// GlobalRouterLSA Implementation -+// GlobalRoutingLSA Implementation - // - // --------------------------------------------------------------------------- - --GlobalRouterLSA::GlobalRouterLSA() -+GlobalRoutingLSA::GlobalRoutingLSA() - : -+ m_lsType (GlobalRoutingLSA::Unknown), - m_linkStateId("0.0.0.0"), - m_advertisingRtr("0.0.0.0"), - m_linkRecords(), -- m_status(GlobalRouterLSA::LSA_SPF_NOT_EXPLORED) --{ -- NS_DEBUG("GlobalRouterLSA::GlobalRouterLSA ()"); --} -- --GlobalRouterLSA::GlobalRouterLSA ( -- GlobalRouterLSA::SPFStatus status, -+ m_networkLSANetworkMask("0.0.0.0"), -+ m_attachedRouters(), -+ m_status(GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED) -+{ -+ NS_DEBUG("GlobalRoutingLSA::GlobalRoutingLSA ()"); -+} -+ -+GlobalRoutingLSA::GlobalRoutingLSA ( -+ GlobalRoutingLSA::SPFStatus status, - Ipv4Address linkStateId, - Ipv4Address advertisingRtr) - : -+ m_lsType (GlobalRoutingLSA::Unknown), - m_linkStateId(linkStateId), - m_advertisingRtr(advertisingRtr), - m_linkRecords(), -+ m_networkLSANetworkMask("0.0.0.0"), -+ m_attachedRouters(), - m_status(status) - { -- NS_DEBUG("GlobalRouterLSA::GlobalRouterLSA (" << status << ", " << -+ NS_DEBUG("GlobalRoutingLSA::GlobalRoutingLSA (" << status << ", " << - linkStateId << ", " << advertisingRtr << ")"); - } - --GlobalRouterLSA::GlobalRouterLSA (GlobalRouterLSA& lsa) -- : m_linkStateId(lsa.m_linkStateId), m_advertisingRtr(lsa.m_advertisingRtr), -+GlobalRoutingLSA::GlobalRoutingLSA (GlobalRoutingLSA& lsa) -+ : m_lsType(lsa.m_lsType), m_linkStateId(lsa.m_linkStateId), -+ m_advertisingRtr(lsa.m_advertisingRtr), -+ m_networkLSANetworkMask(lsa.m_networkLSANetworkMask), - m_status(lsa.m_status) - { - NS_ASSERT_MSG(IsEmpty(), -- "GlobalRouterLSA::GlobalRouterLSA (): Non-empty LSA in constructor"); -+ "GlobalRoutingLSA::GlobalRoutingLSA (): Non-empty LSA in constructor"); - CopyLinkRecords (lsa); - } - -- GlobalRouterLSA& --GlobalRouterLSA::operator= (const GlobalRouterLSA& lsa) --{ -+ GlobalRoutingLSA& -+GlobalRoutingLSA::operator= (const GlobalRoutingLSA& lsa) -+{ -+ m_lsType = lsa.m_lsType; - m_linkStateId = lsa.m_linkStateId; - m_advertisingRtr = lsa.m_advertisingRtr; -+ m_networkLSANetworkMask = lsa.m_networkLSANetworkMask, - m_status = lsa.m_status; - - ClearLinkRecords (); -@@ -171,14 +181,14 @@ GlobalRouterLSA::operator= (const Global - } - - void --GlobalRouterLSA::CopyLinkRecords (const GlobalRouterLSA& lsa) -+GlobalRoutingLSA::CopyLinkRecords (const GlobalRoutingLSA& lsa) - { - for (ListOfLinkRecords_t::const_iterator i = lsa.m_linkRecords.begin (); - i != lsa.m_linkRecords.end (); - i++) - { -- GlobalRouterLinkRecord *pSrc = *i; -- GlobalRouterLinkRecord *pDst = new GlobalRouterLinkRecord; -+ GlobalRoutingLinkRecord *pSrc = *i; -+ GlobalRoutingLinkRecord *pDst = new GlobalRoutingLinkRecord; - - pDst->SetLinkType (pSrc->GetLinkType ()); - pDst->SetLinkId (pSrc->GetLinkId ()); -@@ -187,48 +197,50 @@ GlobalRouterLSA::CopyLinkRecords (const - m_linkRecords.push_back(pDst); - pDst = 0; - } --} -- --GlobalRouterLSA::~GlobalRouterLSA() --{ -- NS_DEBUG("GlobalRouterLSA::~GlobalRouterLSA ()"); -+ -+ m_attachedRouters = lsa.m_attachedRouters; -+} -+ -+GlobalRoutingLSA::~GlobalRoutingLSA() -+{ -+ NS_DEBUG("GlobalRoutingLSA::~GlobalRoutingLSA ()"); - ClearLinkRecords (); - } - - void --GlobalRouterLSA::ClearLinkRecords(void) -+GlobalRoutingLSA::ClearLinkRecords(void) - { - for ( ListOfLinkRecords_t::iterator i = m_linkRecords.begin (); - i != m_linkRecords.end (); - i++) - { -- NS_DEBUG("GlobalRouterLSA::ClearLinkRecords (): free link record"); -- -- GlobalRouterLinkRecord *p = *i; -+ NS_DEBUG("GlobalRoutingLSA::ClearLinkRecords (): free link record"); -+ -+ GlobalRoutingLinkRecord *p = *i; - delete p; - p = 0; - - *i = 0; - } -- NS_DEBUG("GlobalRouterLSA::ClearLinkRecords(): clear list"); -+ NS_DEBUG("GlobalRoutingLSA::ClearLinkRecords(): clear list"); - m_linkRecords.clear(); - } - - uint32_t --GlobalRouterLSA::AddLinkRecord (GlobalRouterLinkRecord* lr) -+GlobalRoutingLSA::AddLinkRecord (GlobalRoutingLinkRecord* lr) - { - m_linkRecords.push_back (lr); - return m_linkRecords.size (); - } - - uint32_t --GlobalRouterLSA::GetNLinkRecords (void) const -+GlobalRoutingLSA::GetNLinkRecords (void) const - { - return m_linkRecords.size (); - } - -- GlobalRouterLinkRecord * --GlobalRouterLSA::GetLinkRecord (uint32_t n) const -+ GlobalRoutingLinkRecord * -+GlobalRoutingLSA::GetLinkRecord (uint32_t n) const - { - uint32_t j = 0; - for ( ListOfLinkRecords_t::const_iterator i = m_linkRecords.begin (); -@@ -240,70 +252,146 @@ GlobalRouterLSA::GetLinkRecord (uint32_t - return *i; - } - } -- NS_ASSERT_MSG(false, "GlobalRouterLSA::GetLinkRecord (): invalid index"); -+ NS_ASSERT_MSG(false, "GlobalRoutingLSA::GetLinkRecord (): invalid index"); - return 0; - } - - bool --GlobalRouterLSA::IsEmpty (void) const -+GlobalRoutingLSA::IsEmpty (void) const - { - return m_linkRecords.size () == 0; - } - -+ GlobalRoutingLSA::LSType -+GlobalRoutingLSA::GetLSType (void) const -+{ -+ return m_lsType; -+} -+ -+ void -+GlobalRoutingLSA::SetLSType (GlobalRoutingLSA::LSType typ) -+{ -+ m_lsType = typ; -+} -+ - Ipv4Address --GlobalRouterLSA::GetLinkStateId (void) const -+GlobalRoutingLSA::GetLinkStateId (void) const - { - return m_linkStateId; - } - - void --GlobalRouterLSA::SetLinkStateId (Ipv4Address addr) -+GlobalRoutingLSA::SetLinkStateId (Ipv4Address addr) - { - m_linkStateId = addr; - } - - Ipv4Address --GlobalRouterLSA::GetAdvertisingRouter (void) const -+GlobalRoutingLSA::GetAdvertisingRouter (void) const - { - return m_advertisingRtr; - } - - void --GlobalRouterLSA::SetAdvertisingRouter (Ipv4Address addr) -+GlobalRoutingLSA::SetAdvertisingRouter (Ipv4Address addr) - { - m_advertisingRtr = addr; - } - -- GlobalRouterLSA::SPFStatus --GlobalRouterLSA::GetStatus (void) const -+ void -+GlobalRoutingLSA::SetNetworkLSANetworkMask (Ipv4Mask mask) -+{ -+ m_networkLSANetworkMask = mask; -+} -+ -+ Ipv4Mask -+GlobalRoutingLSA::GetNetworkLSANetworkMask (void) const -+{ -+ return m_networkLSANetworkMask; -+} -+ -+ GlobalRoutingLSA::SPFStatus -+GlobalRoutingLSA::GetStatus (void) const - { - return m_status; - } - -- void --GlobalRouterLSA::SetStatus (GlobalRouterLSA::SPFStatus status) -+ uint32_t -+GlobalRoutingLSA::AddAttachedRouter (Ipv4Address addr) -+{ -+ m_attachedRouters.push_back (addr); -+ return m_attachedRouters.size (); -+} -+ -+ uint32_t -+GlobalRoutingLSA::GetNAttachedRouters (void) const -+{ -+ return m_attachedRouters.size (); -+} -+ -+ Ipv4Address -+GlobalRoutingLSA::GetAttachedRouter (uint32_t n) const -+{ -+ uint32_t j = 0; -+ for ( ListOfAttachedRouters_t::const_iterator i = m_attachedRouters.begin (); -+ i != m_attachedRouters.end (); -+ i++, j++) -+ { -+ if (j == n) -+ { -+ return *i; -+ } -+ } -+ NS_ASSERT_MSG(false, "GlobalRoutingLSA::GetAttachedRouter (): invalid index"); -+ return Ipv4Address("0.0.0.0"); -+} -+ -+ void -+GlobalRoutingLSA::SetStatus (GlobalRoutingLSA::SPFStatus status) - { - m_status = status; - } - - void --GlobalRouterLSA::Print (std::ostream &os) const --{ -- os << "m_linkStateId = " << m_linkStateId << std::endl << -+GlobalRoutingLSA::Print (std::ostream &os) const -+{ -+ os << "m_lsType = " << m_lsType << std::endl << -+ "m_linkStateId = " << m_linkStateId << std::endl << - "m_advertisingRtr = " << m_advertisingRtr << std::endl; - -- for ( ListOfLinkRecords_t::const_iterator i = m_linkRecords.begin (); -- i != m_linkRecords.end (); -- i++) -- { -- GlobalRouterLinkRecord *p = *i; -+ if (m_lsType == GlobalRoutingLSA::RouterLSA) -+ { -+ for ( ListOfLinkRecords_t::const_iterator i = m_linkRecords.begin (); -+ i != m_linkRecords.end (); -+ i++) -+ { -+ GlobalRoutingLinkRecord *p = *i; -+ os << "----------" << std::endl; -+ os << "m_linkId = " << p->GetLinkId () << std::endl; -+ os << "m_linkData = " << p->GetLinkData () << std::endl; -+ } -+ } -+ else if (m_lsType == GlobalRoutingLSA::NetworkLSA) -+ { - os << "----------" << std::endl; -- os << "m_linkId = " << p->GetLinkId () << std::endl; -- os << "m_linkData = " << p->GetLinkData () << std::endl; -- } --} -- --std::ostream& operator<< (std::ostream& os, GlobalRouterLSA& lsa) -+ os << "m_networkLSANetworkMask = " << m_networkLSANetworkMask -+ << std::endl; -+ for ( ListOfAttachedRouters_t::const_iterator i = -+ m_attachedRouters.begin (); -+ i != m_attachedRouters.end (); -+ i++) -+ { -+ Ipv4Address p = *i; -+ os << "attachedRouter = " << p << std::endl; -+ } -+ } -+ else -+ { -+ NS_ASSERT_MSG(0, "Illegal LSA LSType: " << m_lsType); -+ } -+} -+ -+std::ostream& operator<< (std::ostream& os, GlobalRoutingLSA& lsa) - { - lsa.Print (os); - return os; -@@ -350,7 +438,7 @@ GlobalRouter::ClearLSAs () - { - NS_DEBUG("GlobalRouter::ClearLSAs (): free LSA"); - -- GlobalRouterLSA *p = *i; -+ GlobalRoutingLSA *p = *i; - delete p; - p = 0; - -@@ -373,11 +461,16 @@ GlobalRouter::GetRouterId (void) const - uint32_t - GlobalRouter::DiscoverLSAs (void) - { -- NS_DEBUG("GlobalRouter::DiscoverLSAs ()"); -+ NS_DEBUG("GlobalRouter::DiscoverLSAs () for node " << m_node->GetId () ); - NS_ASSERT_MSG(m_node, - "GlobalRouter::DiscoverLSAs (): interface not set"); - - ClearLSAs (); -+ -+// While building the router-LSA, keep a list of those NetDevices for -+// which I am the designated router and need to later build a NetworkLSA -+ std::list > listOfDRInterfaces; -+ - // - // We're aggregated to a node. We need to ask the node for a pointer to its - // Ipv4 interface. This is where the information regarding the attached -@@ -387,116 +480,250 @@ GlobalRouter::DiscoverLSAs (void) - NS_ASSERT_MSG(ipv4Local, - "GlobalRouter::DiscoverLSAs (): QI for interface failed"); - // --// We are, for now at least, only going to report RouterLSAs in this method. --// What this means is that there is going to be one advertisement with some --// number of link records. This means that GetNumLSAs will actually always --// return exactly one. --// -- GlobalRouterLSA *pLSA = new GlobalRouterLSA; -+// Each node originates a Router-LSA -+// -+ GlobalRoutingLSA *pLSA = new GlobalRoutingLSA; -+ pLSA->SetLSType (GlobalRoutingLSA::RouterLSA); - pLSA->SetLinkStateId (m_routerId); - pLSA->SetAdvertisingRouter (m_routerId); -- pLSA->SetStatus (GlobalRouterLSA::LSA_SPF_NOT_EXPLORED); -+ pLSA->SetStatus (GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED); - // - // We need to ask the node for the number of net devices attached. This isn't - // necessarily equal to the number of links to adjacent nodes (other routers) - // as the number of devices may include those for stub networks (e.g., --// ethernets, etc.). So we have to walk through the list of net devices and --// pay attention to those that are directly connected to another router through --// a point-to-point channel. -+// ethernets, etc.). - // - uint32_t numDevices = m_node->GetNDevices(); - NS_DEBUG("GlobalRouter::DiscoverLSAs (): numDevices = " << numDevices); --// --// Loop through the devices looking for those connected to a point-to-point --// channel. --// - for (uint32_t i = 0; i < numDevices; ++i) - { - Ptr ndLocal = m_node->GetDevice(i); - -- if (!ndLocal->IsPointToPoint ()) -- { -- NS_DEBUG("GlobalRouter::DiscoverLSAs (): non-point-to-point device"); -- continue; -- } -- -- NS_DEBUG("GlobalRouter::DiscoverLSAs (): Point-to-point device"); -+ if (ndLocal->IsBroadcast () && !ndLocal->IsPointToPoint () ) -+ { -+ NS_DEBUG("GlobalRouter::DiscoverLSAs (): broadcast link"); -+ GlobalRoutingLinkRecord *plr = new GlobalRoutingLinkRecord; -+// -+// We need to determine whether we are on a transit or stub network -+// If we find at least one more router on this channel, we are a transit -+// - // - // Now, we have to find the Ipv4 interface whose netdevice is the one we - // just found. This is still the IP on the local side of the channel. There - // is a function to do this used down in the guts of the stack, but it's not - // exported so we had to whip up an equivalent. - // -- uint32_t ifIndexLocal = FindIfIndexForDevice(m_node, ndLocal); --// --// Now that we have the Ipv4 interface index, we can get the address and mask --// we need. --// -- Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal); -- Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal); -- NS_DEBUG("Working with local address " << addrLocal); -+ uint32_t ifIndexLocal = FindIfIndexForDevice(m_node, ndLocal); -+ Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal); -+ Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal); -+ NS_DEBUG("Working with local address " << addrLocal); - // - // Now, we're going to walk over to the remote net device on the other end of - // the point-to-point channel we now know we have. This is where our adjacent - // router (to use OSPF lingo) is running. - // -- Ptr ch = ndLocal->GetChannel(); -- Ptr ndRemote = GetAdjacent(ndLocal, ch); -+ Ptr ch = ndLocal->GetChannel(); -+ uint32_t nDevices = ch->GetNDevices(); -+ if (nDevices == 1) -+ { -+ // This is a stub broadcast interface -+ NS_DEBUG("GlobalRouter::DiscoverLSAs (): Router-LSA stub broadcast link"); -+ // XXX in future, need to consider if >1 includes other routers -+ plr->SetLinkType (GlobalRoutingLinkRecord::StubNetwork); -+ // Link ID is IP network number of attached network -+ plr->SetLinkId (addrLocal.CombineMask(maskLocal)); -+ // Link Data is network mask; convert to Ipv4Address -+ Ipv4Address maskLocalAddr; -+ maskLocalAddr.Set(maskLocal.GetHostOrder ()); -+ plr->SetLinkData (maskLocalAddr); -+ // Cost is interface's configured output cost (NOTYET) -+ plr->SetMetric (1); -+ pLSA->AddLinkRecord(plr); -+ plr = 0; -+ continue; -+ } -+ else -+ { -+ NS_DEBUG("GlobalRouter::DiscoverLSAs (): Router-LSA Broadcast link"); -+ // multiple routers on a broadcast interface -+ // lowest IP address is designated router -+ plr->SetLinkType (GlobalRoutingLinkRecord::TransitNetwork); -+ // Link ID is IP interface address of designated router -+ Ipv4Address desigRtr = -+ FindDesignatedRouterForLink (m_node, ndLocal); -+ if (desigRtr == addrLocal) -+ { -+ listOfDRInterfaces.push_back (ndLocal); -+ NS_DEBUG("GlobalRouter::DiscoverLSAs (): " << -+ m_node->GetId () << " is a DR"); -+ } -+ plr->SetLinkId (desigRtr); -+ // Link Data is router's own IP address -+ plr->SetLinkData (addrLocal); -+ // Cost is interface's configured output cost (NOTYET) -+ plr->SetMetric (1); -+ pLSA->AddLinkRecord (plr); -+ plr = 0; -+ continue; -+ } -+ } -+ else if (ndLocal->IsPointToPoint () ) -+ { -+ NS_DEBUG("GlobalRouter::DiscoverLSAs (): Router-LSA Point-to-point device"); -+// -+// Now, we have to find the Ipv4 interface whose netdevice is the one we -+// just found. This is still the IP on the local side of the channel. There -+// is a function to do this used down in the guts of the stack, but it's not -+// exported so we had to whip up an equivalent. -+// -+ uint32_t ifIndexLocal = FindIfIndexForDevice(m_node, ndLocal); -+// -+// Now that we have the Ipv4 interface index, we can get the address and mask -+// we need. -+// -+ Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal); -+ Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal); -+ NS_DEBUG("Working with local address " << addrLocal); -+// -+// Now, we're going to walk over to the remote net device on the other end of -+// the point-to-point channel we now know we have. This is where our adjacent -+// router (to use OSPF lingo) is running. -+// -+ Ptr ch = ndLocal->GetChannel(); -+ Ptr ndRemote = GetAdjacent(ndLocal, ch); - // - // The adjacent net device is aggregated to a node. We need to ask that net - // device for its node, then ask that node for its Ipv4 interface. - // -- Ptr nodeRemote = ndRemote->GetNode(); -- Ptr ipv4Remote = nodeRemote->QueryInterface (Ipv4::iid); -- NS_ASSERT_MSG(ipv4Remote, -- "GlobalRouter::DiscoverLSAs (): QI for remote failed"); -+ Ptr nodeRemote = ndRemote->GetNode(); -+ Ptr ipv4Remote = nodeRemote->QueryInterface (Ipv4::iid); -+ NS_ASSERT_MSG(ipv4Remote, -+ "GlobalRouter::DiscoverLSAs (): QI for remote failed"); - // - // Per the OSPF spec, we're going to need the remote router ID, so we might as - // well get it now. - // -- Ptr srRemote = -- nodeRemote->QueryInterface (GlobalRouter::iid); -- NS_ASSERT_MSG(srRemote, -- "GlobalRouter::DiscoverLSAs (): QI for remote failed"); -- Ipv4Address rtrIdRemote = srRemote->GetRouterId(); -- NS_DEBUG("Working with remote router " << rtrIdRemote); -+ Ptr srRemote = -+ nodeRemote->QueryInterface (GlobalRouter::iid); -+ NS_ASSERT_MSG(srRemote, -+ "GlobalRouter::DiscoverLSAs():QI for remote failed"); -+ Ipv4Address rtrIdRemote = srRemote->GetRouterId(); -+ NS_DEBUG("Working with remote router " << rtrIdRemote); - // - // Now, just like we did above, we need to get the IP interface index for the - // net device on the other end of the point-to-point channel. - // -- uint32_t ifIndexRemote = FindIfIndexForDevice(nodeRemote, ndRemote); -+ uint32_t ifIndexRemote = FindIfIndexForDevice(nodeRemote, ndRemote); - // - // Now that we have the Ipv4 interface, we can get the (remote) address and - // mask we need. - // -- Ipv4Address addrRemote = ipv4Remote->GetAddress(ifIndexRemote); -- Ipv4Mask maskRemote = ipv4Remote->GetNetworkMask(ifIndexRemote); -- NS_DEBUG("Working with remote address " << addrRemote); -+ Ipv4Address addrRemote = ipv4Remote->GetAddress(ifIndexRemote); -+ Ipv4Mask maskRemote = ipv4Remote->GetNetworkMask(ifIndexRemote); -+ NS_DEBUG("Working with remote address " << addrRemote); - // - // Now we can fill out the link records for this link. There are always two - // link records; the first is a point-to-point record describing the link and - // the second is a stub network record with the network number. - // -- GlobalRouterLinkRecord *plr = new GlobalRouterLinkRecord; -- plr->SetLinkType (GlobalRouterLinkRecord::PointToPoint); -- plr->SetLinkId (rtrIdRemote); -- plr->SetLinkData (addrLocal); -- pLSA->AddLinkRecord(plr); -- plr = 0; -- -- plr = new GlobalRouterLinkRecord; -- plr->SetLinkType (GlobalRouterLinkRecord::StubNetwork); -- plr->SetLinkId (addrRemote); -- plr->SetLinkData (Ipv4Address(maskRemote.GetHostOrder())); // Frown -- pLSA->AddLinkRecord(plr); -- plr = 0; -+ GlobalRoutingLinkRecord *plr = new GlobalRoutingLinkRecord; -+ plr->SetLinkType (GlobalRoutingLinkRecord::PointToPoint); -+ plr->SetLinkId (rtrIdRemote); -+ plr->SetLinkData (addrLocal); -+ pLSA->AddLinkRecord (plr); -+ plr = 0; -+ -+ plr = new GlobalRoutingLinkRecord; -+ plr->SetLinkType (GlobalRoutingLinkRecord::StubNetwork); -+ plr->SetLinkId (addrRemote); -+ plr->SetLinkData (Ipv4Address(maskRemote.GetHostOrder())); // Frown -+ pLSA->AddLinkRecord (plr); -+ plr = 0; -+ } -+ else -+ { -+ NS_ASSERT_MSG(0, "GlobalRouter::DiscoverLSAs (): unknown link type"); -+ } -+ - } - // - // The LSA goes on a list of LSAs in case we want to begin exporting other - // kinds of advertisements (than Router LSAs). - m_LSAs.push_back (pLSA); - NS_DEBUG(*pLSA); -+ -+ -+// Now, determine whether we need to build a NetworkLSA -+ if (listOfDRInterfaces.size () > 0) -+ { -+ for (std::list >::iterator i = listOfDRInterfaces.begin (); -+ i != listOfDRInterfaces.end (); i++) -+ { -+// Build one NetworkLSA for each interface that is a DR -+ Ptr ndLocal = *i; -+ uint32_t ifIndexLocal = FindIfIndexForDevice(m_node, ndLocal); -+ Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal); -+ Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal); -+ -+ GlobalRoutingLSA *pLSA = new GlobalRoutingLSA; -+ pLSA->SetLSType (GlobalRoutingLSA::NetworkLSA); -+ pLSA->SetLinkStateId (addrLocal); -+ pLSA->SetAdvertisingRouter (m_routerId); -+ pLSA->SetNetworkLSANetworkMask (maskLocal); -+ pLSA->SetStatus (GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED); -+// Build list of AttachedRouters -+ Ptr ch = ndLocal->GetChannel(); -+ uint32_t nDevices = ch->GetNDevices(); -+ NS_ASSERT (nDevices); -+ for (uint32_t i = 0; i < nDevices; i++) -+ { -+ Ptr tempNd = ch->GetDevice (i); -+ NS_ASSERT (tempNd); -+ Ptr tempNode = tempNd->GetNode (); -+ uint32_t tempIfIndex = FindIfIndexForDevice (tempNode, tempNd); -+ Ptr tempIpv4 = tempNode->QueryInterface (Ipv4::iid); -+ NS_ASSERT (tempIpv4); -+ Ipv4Address tempAddr = tempIpv4->GetAddress(tempIfIndex); -+ pLSA->AddAttachedRouter (tempAddr); -+ } -+ m_LSAs.push_back (pLSA); -+ NS_DEBUG(*pLSA); -+ } -+ } -+ - return m_LSAs.size (); -+} -+ -+ Ipv4Address -+GlobalRouter::FindDesignatedRouterForLink (Ptr node, -+ Ptr ndLocal) const -+{ -+ uint32_t ifIndexLocal = FindIfIndexForDevice(node, ndLocal); -+ Ptr ipv4Local = m_node->QueryInterface (Ipv4::iid); -+ NS_ASSERT (ipv4Local); -+ Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal); -+ Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal); -+ -+ Ptr ch = ndLocal->GetChannel(); -+ uint32_t nDevices = ch->GetNDevices(); -+ NS_ASSERT (nDevices); -+ Ipv4Address lowest = addrLocal; -+ // iterate all NetDevices and return the lowest numbered IP address -+ for (uint32_t i = 0; i < nDevices; i++) -+ { -+ Ptr tempNd = ch->GetDevice (i); -+ NS_ASSERT (tempNd); -+ Ptr tempNode = tempNd->GetNode (); -+ uint32_t tempIfIndex = FindIfIndexForDevice (tempNode, tempNd); -+ Ptr tempIpv4 = tempNode->QueryInterface (Ipv4::iid); -+ NS_ASSERT (tempIpv4); -+ Ipv4Address tempAddr = tempIpv4->GetAddress(tempIfIndex); -+ if (tempAddr < addrLocal) -+ { -+ addrLocal = tempAddr; -+ } -+ } -+ return addrLocal; - } - - uint32_t -@@ -510,7 +737,7 @@ GlobalRouter::GetNumLSAs (void) const - // Get the nth link state advertisement from this router. - // - bool --GlobalRouter::GetLSA (uint32_t n, GlobalRouterLSA &lsa) const -+GlobalRouter::GetLSA (uint32_t n, GlobalRoutingLSA &lsa) const - { - NS_ASSERT_MSG(lsa.IsEmpty(), "GlobalRouter::GetLSA (): Must pass empty LSA"); - // -@@ -525,7 +752,7 @@ GlobalRouter::GetLSA (uint32_t n, Global - { - if (j == n) - { -- GlobalRouterLSA *p = *i; -+ GlobalRoutingLSA *p = *i; - lsa = *p; - return true; - } -diff -r 25fa26a6533e -r 3760d52ef5d1 src/routing/global-routing/global-router-interface.h ---- a/src/routing/global-routing/global-router-interface.h Sun Aug 12 22:41:24 2007 -0700 -+++ b/src/routing/global-routing/global-router-interface.h Sun Aug 12 22:43:25 2007 -0700 -@@ -31,16 +31,16 @@ namespace ns3 { - /** - * @brief A single link record for a link state advertisement. - * -- * The GlobalRouterLinkRecord is modeled after the OSPF link record field of -+ * The GlobalRoutingLinkRecord is modeled after the OSPF link record field of - * a Link State Advertisement. Right now we will only see two types of link - * records corresponding to a stub network and a point-to-point link (channel). - */ --class GlobalRouterLinkRecord -+class GlobalRoutingLinkRecord - { - public: - /** - * @enum LinkType -- * @brief Enumeration of the possible types of Global Router Link Records. -+ * @brief Enumeration of the possible types of Global Routing Link Records. - * - * These values are defined in the OSPF spec. We currently only use - * PointToPoint and StubNetwork types. -@@ -54,16 +54,16 @@ public: - }; - - /** -- * @brief Construct an empty ("uninitialized") Global Router Link Record. -+ * @brief Construct an empty ("uninitialized") Global Routing Link Record. - * - * The Link ID and Link Data Ipv4 addresses are set to "0.0.0.0"; - * The Link Type is set to Unknown; - * The metric is set to 0. - */ -- GlobalRouterLinkRecord (); -- --/** -- * Construct an initialized Global Router Link Record. -+ GlobalRoutingLinkRecord (); -+ -+/** -+ * Construct an initialized Global Routing Link Record. - * - * @param linkType The type of link record to construct. - * @param linkId The link ID for the record. -@@ -73,21 +73,21 @@ public: - * @see SetLinkId - * @see SetLinkData - */ -- GlobalRouterLinkRecord ( -+ GlobalRoutingLinkRecord ( - LinkType linkType, - Ipv4Address linkId, - Ipv4Address linkData, - uint32_t metric); - - /** -- * @brief Destroy a Global Router Link Record. -+ * @brief Destroy a Global Routing Link Record. - * - * Currently does nothing. Here as a placeholder only. - */ -- ~GlobalRouterLinkRecord (); -- --/** -- * Get the Link ID field of the Global Router Link Record. -+ ~GlobalRoutingLinkRecord (); -+ -+/** -+ * Get the Link ID field of the Global Routing Link Record. - * - * For an OSPF type 1 link (PointToPoint) the Link ID will be the Router ID - * of the neighboring router. -@@ -100,7 +100,7 @@ public: - Ipv4Address GetLinkId(void) const; - - /** -- * @brief Set the Link ID field of the Global Router Link Record. -+ * @brief Set the Link ID field of the Global Routing Link Record. - * - * For an OSPF type 1 link (PointToPoint) the Link ID must be the Router ID - * of the neighboring router. -@@ -113,7 +113,7 @@ public: - void SetLinkId(Ipv4Address addr); - - /** -- * @brief Get the Link Data field of the Global Router Link Record. -+ * @brief Get the Link Data field of the Global Routing Link Record. - * - * For an OSPF type 1 link (PointToPoint) the Link Data will be the IP - * address of the node of the local side of the link. -@@ -126,7 +126,7 @@ public: - Ipv4Address GetLinkData(void) const; - - /** -- * @brief Set the Link Data field of the Global Router Link Record. -+ * @brief Set the Link Data field of the Global Routing Link Record. - * - * For an OSPF type 1 link (PointToPoint) the Link Data must be the IP - * address of the node of the local side of the link. -@@ -139,29 +139,29 @@ public: - void SetLinkData(Ipv4Address addr); - - /** -- * @brief Get the Link Type field of the Global Router Link Record. -+ * @brief Get the Link Type field of the Global Routing Link Record. - * - * The Link Type describes the kind of link a given record represents. The - * values are defined by OSPF. - * - * @see LinkType -- * @returns The LinkType of the current Global Router Link Record. -+ * @returns The LinkType of the current Global Routing Link Record. - */ - LinkType GetLinkType(void) const; - - /** -- * @brief Set the Link Type field of the Global Router Link Record. -+ * @brief Set the Link Type field of the Global Routing Link Record. - * - * The Link Type describes the kind of link a given record represents. The - * values are defined by OSPF. - * - * @see LinkType -- * @param linkType The new LinkType for the current Global Router Link Record. -+ * @param linkType The new LinkType for the current Global Routing Link Record. - */ - void SetLinkType(LinkType linkType); - - /** -- * @brief Get the Metric Data field of the Global Router Link Record. -+ * @brief Get the Metric Data field of the Global Routing Link Record. - * - * The metric is an abstract cost associated with forwarding a packet across - * a link. A sum of metrics must have a well-defined meaning. That is, you -@@ -169,12 +169,12 @@ public: - * two hops relate to the cost of sending a packet); rather you should use - * something like delay. - * -- * @returns The metric field of the Global Router Link Record. -+ * @returns The metric field of the Global Routing Link Record. - */ - uint32_t GetMetric(void) const; - - /** -- * @brief Set the Metric Data field of the Global Router Link Record. -+ * @brief Set the Metric Data field of the Global Routing Link Record. - * - * The metric is an abstract cost associated with forwarding a packet across - * a link. A sum of metrics must have a well-defined meaning. That is, you -@@ -182,7 +182,7 @@ public: - * two hops relate to the cost of sending a packet); rather you should use - * something like delay. - * -- * @param metric The new metric for the current Global Router Link Record. -+ * @param metric The new metric for the current Global Routing Link Record. - */ - void SetMetric(uint32_t metric); - -@@ -211,7 +211,7 @@ private: - Ipv4Address m_linkData; // for links to RouterLSA, - - /** -- * The type of the Global Router Link Record. Defined in the OSPF spec. -+ * The type of the Global Routing Link Record. Defined in the OSPF spec. - * We currently only use PointToPoint and StubNetwork types. - */ - LinkType m_linkType; -@@ -236,12 +236,24 @@ private: - * combined with a list of Link Records. Since it's global, there's - * no need for age or sequence number. See RFC 2328, Appendix A. - */ --class GlobalRouterLSA -+class GlobalRoutingLSA - { - public: - /** -+ * @enum LSType -+ * @brief corresponds to LS type field of RFC 2328 OSPF LSA header -+ */ -+ enum LSType { -+ Unknown = 0, /**< Uninitialized Type */ -+ RouterLSA, -+ NetworkLSA, -+ SummaryLSA, -+ SummaryLSA_ASBR, -+ ASExternalLSAs -+ }; -+/** - * @enum SPFStatus -- * @brief Enumeration of the possible values of the status flag in the Router -+ * @brief Enumeration of the possible values of the status flag in the Routing - * Link State Advertisements. - */ - enum SPFStatus { -@@ -249,17 +261,16 @@ public: - LSA_SPF_CANDIDATE, /**< Vertex is in the SPF candidate queue */ - LSA_SPF_IN_SPFTREE /**< Vertex is in the SPF tree */ - }; -- --/** -- * @brief Create a blank Global Router Link State Advertisement. -+/** -+ * @brief Create a blank Global Routing Link State Advertisement. - * - * On completion Ipv4Address variables initialized to 0.0.0.0 and the - * list of Link State Records is empty. - */ -- GlobalRouterLSA(); -- --/** -- * @brief Create an initialized Global Router Link State Advertisement. -+ GlobalRoutingLSA(); -+ -+/** -+ * @brief Create an initialized Global Routing Link State Advertisement. - * - * On completion the list of Link State Records is empty. - * -@@ -267,42 +278,42 @@ public: - * @param linkStateId The Ipv4Address for the link state ID field. - * @param advertisingRtr The Ipv4Address for the advertising router field. - */ -- GlobalRouterLSA(SPFStatus status, Ipv4Address linkStateId, -+ GlobalRoutingLSA(SPFStatus status, Ipv4Address linkStateId, - Ipv4Address advertisingRtr); - - /** -- * @brief Copy constructor for a Global Router Link State Advertisement. -+ * @brief Copy constructor for a Global Routing Link State Advertisement. - * - * Takes a piece of memory and constructs a semantically identical copy of - * the given LSA. - * - * @param lsa The existing LSA to be used as the source. - */ -- GlobalRouterLSA (GlobalRouterLSA& lsa); -- --/** -- * @brief Destroy an existing Global Router Link State Advertisement. -- * -- * Any Global Router Link Records present in the list are freed. -- */ -- ~GlobalRouterLSA(); -- --/** -- * @brief Assignment operator for a Global Router Link State Advertisement. -- * -- * Takes an existing Global Router Link State Advertisement and overwrites -+ GlobalRoutingLSA (GlobalRoutingLSA& lsa); -+ -+/** -+ * @brief Destroy an existing Global Routing Link State Advertisement. -+ * -+ * Any Global Routing Link Records present in the list are freed. -+ */ -+ ~GlobalRoutingLSA(); -+ -+/** -+ * @brief Assignment operator for a Global Routing Link State Advertisement. -+ * -+ * Takes an existing Global Routing Link State Advertisement and overwrites - * it to make a semantically identical copy of a given prototype LSA. - * -- * If there are any Global Router Link Records present in the existing -+ * If there are any Global Routing Link Records present in the existing - * LSA, they are freed before the assignment happens. - * - * @param lsa The existing LSA to be used as the source. - * @returns Reference to the overwritten LSA. - */ -- GlobalRouterLSA& operator= (const GlobalRouterLSA& lsa); -- --/** -- * @brief Copy any Global Router Link Records in a given Global Router Link -+ GlobalRoutingLSA& operator= (const GlobalRoutingLSA& lsa); -+ -+/** -+ * @brief Copy any Global Routing Link Records in a given Global Routing Link - * State Advertisement to the current LSA. - * - * Existing Link Records are not deleted -- this is a concatenation of Link -@@ -311,57 +322,66 @@ public: - * @see ClearLinkRecords () - * @param lsa The LSA to copy the Link Records from. - */ -- void CopyLinkRecords (const GlobalRouterLSA& lsa); -- --/** -- * @brief Add a given Global Router Link Record to the LSA. -- * -- * @param lr The Global Router Link Record to be added. -+ void CopyLinkRecords (const GlobalRoutingLSA& lsa); -+ -+/** -+ * @brief Add a given Global Routing Link Record to the LSA. -+ * -+ * @param lr The Global Routing Link Record to be added. - * @returns The number of link records in the list. - */ -- uint32_t AddLinkRecord (GlobalRouterLinkRecord* lr); -- --/** -- * @brief Return the number of Global Router Link Records in the LSA. -+ uint32_t AddLinkRecord (GlobalRoutingLinkRecord* lr); -+ -+/** -+ * @brief Return the number of Global Routing Link Records in the LSA. - * - * @returns The number of link records in the list. - */ - uint32_t GetNLinkRecords (void) const; - - /** -- * @brief Return a pointer to the specified Global Router Link Record. -+ * @brief Return a pointer to the specified Global Routing Link Record. - * - * @param n The LSA number desired. - * @returns The number of link records in the list. - */ -- GlobalRouterLinkRecord* GetLinkRecord (uint32_t n) const; -- --/** -- * @brief Release all of the Global Router Link Records present in the Global -- * Router Link State Advertisement and make the list of link records empty. -+ GlobalRoutingLinkRecord* GetLinkRecord (uint32_t n) const; -+ -+/** -+ * @brief Release all of the Global Routing Link Records present in the Global -+ * Routing Link State Advertisement and make the list of link records empty. - */ - void ClearLinkRecords(void); - - /** -- * @brief Check to see if the list of Global Router Link Records present in the -- * Global Router Link State Advertisement is empty. -+ * @brief Check to see if the list of Global Routing Link Records present in the -+ * Global Routing Link State Advertisement is empty. - * - * @returns True if the list is empty, false otherwise. - */ - bool IsEmpty(void) const; - - /** -- * @brief Print the contents of the Global Router Link State Advertisement and -- * any Global Router Link Records present in the list. Quite verbose. -+ * @brief Print the contents of the Global Routing Link State Advertisement and -+ * any Global Routing Link Records present in the list. Quite verbose. - */ - void Print (std::ostream &os) const; -+ -+/** -+ * @brief Return the LSType field of the LSA -+ */ -+ LSType GetLSType (void) const; -+/** -+ * @brief Set the LS type field of the LSA -+ */ -+ void SetLSType (LSType typ); - - /** - * @brief Get the Link State ID as defined by the OSPF spec. We always set it - * to the router ID of the router making the advertisement. - * - * @see RoutingEnvironment::AllocateRouterId () -- * @see GlobalRouter::GetRouterId () -+ * @see GlobalRouting::GetRouterId () - * @returns The Ipv4Address stored as the link state ID. - */ - Ipv4Address GetLinkStateId (void) const; -@@ -371,7 +391,7 @@ public: - * to the router ID of the router making the advertisement. - * - * @see RoutingEnvironment::AllocateRouterId () -- * @see GlobalRouter::GetRouterId () -+ * @see GlobalRouting::GetRouterId () - */ - void SetLinkStateId (Ipv4Address addr); - -@@ -380,7 +400,7 @@ public: - * set it to the router ID of the router making the advertisement. - * - * @see RoutingEnvironment::AllocateRouterId () -- * @see GlobalRouter::GetRouterId () -+ * @see GlobalRouting::GetRouterId () - * @returns The Ipv4Address stored as the advetising router. - */ - Ipv4Address GetAdvertisingRouter (void) const; -@@ -390,9 +410,46 @@ public: - * set it to the router ID of the router making the advertisement. - * - * @see RoutingEnvironment::AllocateRouterId () -- * @see GlobalRouter::GetRouterId () -+ * @see GlobalRouting::GetRouterId () - */ - void SetAdvertisingRouter (Ipv4Address rtr); -+ -+/** -+ * @brief For a Network LSA, set the Network Mask field that precedes -+ * the list of attached routers. -+ */ -+ void SetNetworkLSANetworkMask (Ipv4Mask mask); -+ -+/** -+ * @brief For a Network LSA, get the Network Mask field that precedes -+ * the list of attached routers. -+ * -+ * @returns the NetworkLSANetworkMask -+ */ -+ Ipv4Mask GetNetworkLSANetworkMask (void) const; -+ -+/** -+ * @brief Add an attached router to the list in the NetworkLSA -+ * -+ * @param address The Ipv4Address of the interface on the network link -+ * @returns The number of addresses in the list. -+ */ -+ uint32_t AddAttachedRouter (Ipv4Address addr); -+ -+/** -+ * @brief Return the number of attached routers listed in the NetworkLSA -+ * -+ * @returns The number of attached routers. -+ */ -+ uint32_t GetNAttachedRouters (void) const; -+ -+/** -+ * @brief Return an Ipv4Address corresponding to the specified attached router -+ * -+ * @param n The attached router number desired (number in the list). -+ * @returns The Ipv4Address of the requested router -+ */ -+ Ipv4Address GetAttachedRouter (uint32_t n) const; - - /** - * @brief Get the SPF status of the advertisement. -@@ -411,11 +468,16 @@ public: - - private: - /** -+ * The type of the LSA. Each LSA type has a separate advertisement -+ * format. -+ */ -+ LSType m_lsType; -+/** - * The Link State ID is defined by the OSPF spec. We always set it to the - * router ID of the router making the advertisement. - * - * @see RoutingEnvironment::AllocateRouterId () -- * @see GlobalRouter::GetRouterId () -+ * @see GlobalRouting::GetRouterId () - */ - Ipv4Address m_linkStateId; - -@@ -424,14 +486,14 @@ private: - * the router ID of the router making the advertisement. - * - * @see RoutingEnvironment::AllocateRouterId () -- * @see GlobalRouter::GetRouterId () -+ * @see GlobalRouting::GetRouterId () - */ - Ipv4Address m_advertisingRtr; - - /** - * A convenience typedef to avoid too much writers cramp. - */ -- typedef std::list ListOfLinkRecords_t; -+ typedef std::list ListOfLinkRecords_t; - - /** - * Each Link State Advertisement contains a number of Link Records that -@@ -441,9 +503,29 @@ private: - * m_linkRecords is an STL list container to hold the Link Records that have - * been discovered and prepared for the advertisement. - * -- * @see GlobalRouter::DiscoverLSAs () -+ * @see GlobalRouting::DiscoverLSAs () - */ - ListOfLinkRecords_t m_linkRecords; -+ -+/** -+ * Each Network LSA contains the network mask of the attached network -+ */ -+ Ipv4Mask m_networkLSANetworkMask; -+ -+/** -+ * A convenience typedef to avoid too much writers cramp. -+ */ -+ typedef std::list ListOfAttachedRouters_t; -+ -+/** -+ * Each Network LSA contains a list of attached routers -+ * -+ * m_attachedRouters is an STL list container to hold the addresses that have -+ * been discovered and prepared for the advertisement. -+ * -+ * @see GlobalRouting::DiscoverLSAs () -+ */ -+ ListOfAttachedRouters_t m_attachedRouters; - - /** - * This is a tristate flag used internally in the SPF computation to mark -@@ -454,7 +536,7 @@ private: - SPFStatus m_status; - }; - --std::ostream& operator<< (std::ostream& os, GlobalRouterLSA& lsa); -+std::ostream& operator<< (std::ostream& os, GlobalRoutingLSA& lsa); - - /** - * @brief An interface aggregated to a node to provide global routing info -@@ -496,7 +578,7 @@ public: - - /** - * @brief Walk the connected channels, discover the adjacent routers and build -- * the associated number of Global Router Link State Advertisements that -+ * the associated number of Global Routing Link State Advertisements that - * this router can export. - * - * This is a fairly expensive operation in that every time it is called -@@ -507,14 +589,14 @@ public: - * advertisements after a network topology change by calling DiscoverLSAs - * and then by reading those advertisements. - * -- * @see GlobalRouterLSA -+ * @see GlobalRoutingLSA - * @see GlobalRouter::GetLSA () -- * @returns The number of Global Router Link State Advertisements. -+ * @returns The number of Global Routing Link State Advertisements. - */ - uint32_t DiscoverLSAs (void); - - /** -- * @brief Get the Number of Global Router Link State Advertisements that this -+ * @brief Get the Number of Global Routing Link State Advertisements that this - * router can export. - * - * To get meaningful information you must have previously called DiscoverLSAs. -@@ -522,19 +604,19 @@ public: - * GetLSA () to retrieve the actual advertisement. - * - * @see GlobalRouterLSA -- * @see GlobalRouter::DiscoverLSAs () -- * @see GlobalRouter::GetLSA () -- * @returns The number of Global Router Link State Advertisements. -+ * @see GlobalRouting::DiscoverLSAs () -+ * @see GlobalRouting::GetLSA () -+ * @returns The number of Global Routing Link State Advertisements. - */ - uint32_t GetNumLSAs (void) const; - - /** -- * @brief Get a Global Router Link State Advertisements that this router has -+ * @brief Get a Global Routing Link State Advertisements that this router has - * said that it can export. - * - * This is a fairly inexpensive expensive operation in that the hard work -- * was done in GetNumLSAs. We just copy the indicated Global Router Link -- * State Advertisement into the requested GlobalRouterLSA object. -+ * was done in GetNumLSAs. We just copy the indicated Global Routing Link -+ * State Advertisement into the requested GlobalRoutingLSA object. - * - * You must call GlobalRouter::GetNumLSAs before calling this method in - * order to discover the adjacent routers and build the advertisements. -@@ -542,13 +624,13 @@ public: - * The parameter n (requested LSA number) must be in the range 0 to - * GetNumLSAs() - 1. - * -- * @see GlobalRouterLSA -- * @see GlobalRouter::GetNumLSAs () -+ * @see GlobalRoutingLSA -+ * @see GlobalRouting::GetNumLSAs () - * @param n The index number of the LSA you want to read. -- * @param lsa The GlobalRouterLSA class to receive the LSA information. -+ * @param lsa The GlobalRoutingLSA class to receive the LSA information. - * @returns The number of Global Router Link State Advertisements. - */ -- bool GetLSA (uint32_t n, GlobalRouterLSA &lsa) const; -+ bool GetLSA (uint32_t n, GlobalRoutingLSA &lsa) const; - - private: - virtual ~GlobalRouter (); -@@ -556,10 +638,12 @@ private: - - Ptr GetAdjacent(Ptr nd, Ptr ch) const; - uint32_t FindIfIndexForDevice(Ptr node, Ptr nd) const; -+ Ipv4Address FindDesignatedRouterForLink (Ptr node, -+ Ptr ndLocal) const; - - Ptr m_node; - -- typedef std::list ListOfLSAs_t; -+ typedef std::list ListOfLSAs_t; - ListOfLSAs_t m_LSAs; - - Ipv4Address m_routerId; - -changeset: 1284:3aef7d7a71c2 -user: Craig Dowell -date: Mon Aug 13 12:08:01 2007 -0700 -summary: more multicast plumbing - -diff -r 3760d52ef5d1 -r 3aef7d7a71c2 examples/csma-multicast.cc ---- a/examples/csma-multicast.cc Sun Aug 12 22:43:25 2007 -0700 -+++ b/examples/csma-multicast.cc Mon Aug 13 12:08:01 2007 -0700 -@@ -65,7 +65,7 @@ main (int argc, char *argv[]) - { - // Users may find it convenient to turn on explicit debugging - // for selected modules; the below lines suggest how to do this --#if 0 -+#if 0 - DebugComponentEnable("Me"); - DebugComponentEnable("Object"); - DebugComponentEnable("Queue"); -@@ -87,16 +87,9 @@ main (int argc, char *argv[]) - #endif - - DebugComponentEnable("Me"); -- DebugComponentEnable("OnOffApplication"); -- DebugComponentEnable("UdpSocket"); -+ DebugComponentEnable("CsmaChannel"); -+ DebugComponentEnable("CsmaNetDevice"); - DebugComponentEnable("UdpL4Protocol"); -- DebugComponentEnable("Ipv4L3Protocol"); -- DebugComponentEnable("Ipv4StaticRouting"); -- DebugComponentEnable("CsmaNetDevice"); -- DebugComponentEnable("CsmaChannel"); -- DebugComponentEnable("Ipv4Interface"); -- DebugComponentEnable("ArpIpv4Interface"); -- DebugComponentEnable("Ipv4LoopbackInterface"); - - // Set up some default values for the simulation. Use the Bind() - // technique to tell the system what subclass of Queue to use, -@@ -125,29 +118,47 @@ main (int argc, char *argv[]) - DataRate(5000000), MilliSeconds(2)); - - NS_DEBUG("Build Topology."); -- uint32_t n0ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n0, channel0, -- Eui48Address("10:54:23:54:23:50")); -- uint32_t n1ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n1, channel0, -- Eui48Address("10:54:23:54:23:51")); -- uint32_t n2ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n2, channel0, -- Eui48Address("10:54:23:54:23:52")); -- uint32_t n3ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n3, channel0, -- Eui48Address("10:54:23:54:23:53")); -+ uint32_t netDeviceNumberNode0 = CsmaIpv4Topology::AddIpv4CsmaNode (n0, -+ channel0, Eui48Address("10:54:23:54:23:50")); -+ uint32_t netDeviceNumberNode1 = CsmaIpv4Topology::AddIpv4CsmaNode (n1, -+ channel0, Eui48Address("10:54:23:54:23:51")); -+ uint32_t netDeviceNumberNode2 = CsmaIpv4Topology::AddIpv4CsmaNode (n2, -+ channel0, Eui48Address("10:54:23:54:23:52")); -+ uint32_t netDeviceNumberNode3 = CsmaIpv4Topology::AddIpv4CsmaNode (n3, -+ channel0, Eui48Address("10:54:23:54:23:53")); -+ -+ NS_DEBUG ("netDeviceNumberNode0 = " << netDeviceNumberNode0); -+ NS_DEBUG ("netDeviceNumberNode1 = " << netDeviceNumberNode1); -+ NS_DEBUG ("netDeviceNumberNode2 = " << netDeviceNumberNode2); -+ NS_DEBUG ("netDeviceNumberNode3 = " << netDeviceNumberNode3); - - // Later, we add IP addresses. - NS_DEBUG("Assign IP Addresses."); -- -- CsmaIpv4Topology::AddIpv4Address ( -- n0, n0ifIndex, Ipv4Address("10.1.1.1"), Ipv4Mask("255.255.255.0")); -- -- CsmaIpv4Topology::AddIpv4Address ( -- n1, n1ifIndex, Ipv4Address("10.1.1.2"), Ipv4Mask("255.255.255.0")); -- -- CsmaIpv4Topology::AddIpv4Address ( -- n2, n2ifIndex, Ipv4Address("10.1.1.3"), Ipv4Mask("255.255.255.0")); -+ // XXX BUGBUG -+ // Need a better way to get the interface index. The point-to-point topology -+ // as implemented can't return the index since it creates interfaces on both -+ // sides (i.e., AddIpv4Addresses, not AddIpv4Address). Need a method on -+ // Ipv4 to find the interface index corresponding to a given ipv4 address. -+ uint32_t ifIndexNode0 = CsmaIpv4Topology::AddIpv4Address (n0, -+ netDeviceNumberNode0, Ipv4Address ("10.1.1.1"), -+ Ipv4Mask ("255.255.255.0")); -+ -+ uint32_t ifIndexNode1 = CsmaIpv4Topology::AddIpv4Address (n1, -+ netDeviceNumberNode1, Ipv4Address ("10.1.1.2"), -+ Ipv4Mask ("255.255.255.0")); -+ -+ uint32_t ifIndexNode2 = CsmaIpv4Topology::AddIpv4Address (n2, -+ netDeviceNumberNode2, Ipv4Address ("10.1.1.3"), -+ Ipv4Mask ("255.255.255.0")); - -- CsmaIpv4Topology::AddIpv4Address ( -- n3, n3ifIndex, Ipv4Address("10.1.1.4"), Ipv4Mask("255.255.255.0")); -+ uint32_t ifIndexNode3 = CsmaIpv4Topology::AddIpv4Address (n3, -+ netDeviceNumberNode3, Ipv4Address ("10.1.1.4"), -+ Ipv4Mask ("255.255.255.0")); -+ -+ NS_DEBUG ("ifIndexNode0 = " << ifIndexNode0); -+ NS_DEBUG ("ifIndexNode1 = " << ifIndexNode1); -+ NS_DEBUG ("ifIndexNode2 = " << ifIndexNode2); -+ NS_DEBUG ("ifIndexNode3 = " << ifIndexNode3); - - // Configure multicasting - NS_DEBUG("Configure multicasting."); -@@ -158,22 +169,21 @@ main (int argc, char *argv[]) - ipv4 = n0->QueryInterface (Ipv4::iid); - - std::vector outputInterfaces (1); -- outputInterfaces[0] = n0ifIndex; -+ outputInterfaces[0] = ifIndexNode0; - - ipv4->AddMulticastRoute (multicastSource, multicastGroup, 0, - outputInterfaces); - - ipv4 = n1->QueryInterface (Ipv4::iid); -- ipv4->JoinMulticastGroup (multicastSource, multicastGroup); -+ // ipv4->JoinMulticastGroup (multicastSource, multicastGroup); - - ipv4 = n2->QueryInterface (Ipv4::iid); -- ipv4->JoinMulticastGroup (multicastSource, multicastGroup); -+ // ipv4->JoinMulticastGroup (multicastSource, multicastGroup); - - ipv4 = n3->QueryInterface (Ipv4::iid); -- ipv4->JoinMulticastGroup (multicastSource, multicastGroup); -- -- // Create the OnOff application to send UDP datagrams of size -- // 210 bytes at a rate of 448 Kb/s -+ // ipv4->JoinMulticastGroup (multicastSource, multicastGroup); -+ -+ // Create the OnOff application to send UDP datagrams - // from n0 to the multicast group - NS_DEBUG("Create Applications."); - Ptr ooff = Create ( -@@ -181,10 +191,12 @@ main (int argc, char *argv[]) - InetSocketAddress (multicastGroup, 80), - "Udp", - ConstantVariable(1), -- ConstantVariable(0)); -+ ConstantVariable(0), -+ DataRate ("128b/s"), -+ 128); - // Start the application -- ooff->Start(Seconds(1.0)); -- ooff->Stop (Seconds(10.0)); -+ ooff->Start(Seconds(1.)); -+ ooff->Stop (Seconds(10.)); - - // Configure tracing of all enqueue, dequeue, and NetDevice receive events - // Trace output will be sent to the csma-one-subnet.tr file -diff -r 3760d52ef5d1 -r 3aef7d7a71c2 src/applications/onoff-application.cc ---- a/src/applications/onoff-application.cc Sun Aug 12 22:43:25 2007 -0700 -+++ b/src/applications/onoff-application.cc Mon Aug 13 12:08:01 2007 -0700 -@@ -199,9 +199,12 @@ void OnOffApplication::ScheduleNextTx() - if (m_totBytes < m_maxBytes) - { - uint32_t bits = m_pktSize * 8 - m_residualBits; -+ NS_DEBUG("OnOffApplication::ScheduleNextTx (): bits = " << bits); - Time nextTime(Seconds (bits / - static_cast(m_cbrRate.GetBitRate()))); // Time till next packet -- m_sendEvent = Simulator::Schedule(nextTime, &OnOffApplication::SendPacket, this); -+ NS_DEBUG("OnOffApplication::ScheduleNextTx (): nextTime = " << nextTime); -+ m_sendEvent = Simulator::Schedule(nextTime, -+ &OnOffApplication::SendPacket, this); - } - else - { // All done, cancel any pending events -@@ -214,6 +217,8 @@ void OnOffApplication::ScheduleStartEven - NS_DEBUG("OnOffApplication::ScheduleStartEvent ()"); - - Time offInterval = Seconds(m_offTime->GetValue()); -+ NS_DEBUG("OnOffApplication::ScheduleStartEvent (): " -+ "start at " << offInterval); - m_startStopEvent = Simulator::Schedule(offInterval, &OnOffApplication::StartSending, this); - } - -diff -r 3760d52ef5d1 -r 3aef7d7a71c2 src/devices/csma/csma-ipv4-topology.cc ---- a/src/devices/csma/csma-ipv4-topology.cc Sun Aug 12 22:43:25 2007 -0700 -+++ b/src/devices/csma/csma-ipv4-topology.cc Mon Aug 13 12:08:01 2007 -0700 -@@ -91,24 +91,22 @@ CsmaIpv4Topology::AddIpv4RawCsmaNode(Ptr - nd1->Attach (ch); - } - --void --CsmaIpv4Topology::AddIpv4Address(Ptr n1, -- int ndNum, -- const Ipv4Address& addr1, -- const Ipv4Mask& netmask1) -+uint32_t -+CsmaIpv4Topology::AddIpv4Address( -+ Ptr node, -+ uint32_t netDeviceNumber, -+ const Ipv4Address address, -+ const Ipv4Mask mask) - { -- // Duplex link is assumed to be subnetted as a /30 -- // May run this unnumbered in the future? -- Ipv4Mask netmask(netmask1); -+ Ptr nd = node->GetDevice(netDeviceNumber); - -- Ptr nd1 = n1->GetDevice(ndNum); -+ Ptr ipv4 = node->QueryInterface (Ipv4::iid); -+ uint32_t ifIndex = ipv4->AddInterface (nd); - -- Ptr ip1 = n1->QueryInterface (Ipv4::iid); -- uint32_t index1 = ip1->AddInterface (nd1); -- -- ip1->SetAddress (index1, addr1); -- ip1->SetNetworkMask (index1, netmask); -- ip1->SetUp (index1); -+ ipv4->SetAddress (ifIndex, address); -+ ipv4->SetNetworkMask (ifIndex, mask); -+ ipv4->SetUp (ifIndex); -+ return ifIndex; - } - - void -diff -r 3760d52ef5d1 -r 3aef7d7a71c2 src/devices/csma/csma-ipv4-topology.h ---- a/src/devices/csma/csma-ipv4-topology.h Sun Aug 12 22:43:25 2007 -0700 -+++ b/src/devices/csma/csma-ipv4-topology.h Mon Aug 13 12:08:01 2007 -0700 -@@ -94,18 +94,23 @@ public: - - - /** -- * \param n1 Node -- * \param ndNum NetDevice number with which to associate address -- * \param addr1 Ipv4 Address for ndNum of n1 -- * \param network network mask for ndNum of node n1 -+ * \brief Create an Ipv4 interface for a net device and assign an -+ * Ipv4Address to that interface. -+ * -+ * \param node The node to which to add the new address and corresponding -+ * interface. -+ * \param netDeviceNumber The NetDevice index number with which to associate -+ * the address. -+ * \param address The Ipv4 Address for the interface. -+ * \param network The network mask for the interface - * - * Add an Ipv4Address to the Ipv4 interface associated with the -- * ndNum CsmaIpv4NetDevices on the provided -- * CsmaIpv4Channel -+ * ndNum CsmaIpv4NetDevices on the provided CsmaIpv4Channel - */ -- static void AddIpv4Address(Ptr n1, int ndNum, -- const Ipv4Address& addr1, -- const Ipv4Mask& netmask1); -+ static uint32_t AddIpv4Address(Ptr node, -+ uint32_t netDeviceNumber, -+ const Ipv4Address address, -+ const Ipv4Mask mask); - - /** - * \param nd1 Node -diff -r 3760d52ef5d1 -r 3aef7d7a71c2 src/internet-node/arp-ipv4-interface.cc ---- a/src/internet-node/arp-ipv4-interface.cc Sun Aug 12 22:43:25 2007 -0700 -+++ b/src/internet-node/arp-ipv4-interface.cc Mon Aug 13 12:08:01 2007 -0700 -@@ -81,6 +81,14 @@ ArpIpv4Interface::SendTo (Packet p, Ipv4 - hardwareDestination = GetDevice ()->GetBroadcast (); - found = true; - } -+ else if (dest.IsMulticast ()) -+ { -+ NS_DEBUG ("ArpIpv4Interface::SendTo (): IsMulticast"); -+ // XXX BUGBUG -+ // Need real multicast addresses -+ hardwareDestination = GetDevice ()->GetBroadcast (); -+ found = true; -+ } - else - { - NS_DEBUG ("ArpIpv4Interface::SendTo (): ARP Lookup"); -diff -r 3760d52ef5d1 -r 3aef7d7a71c2 src/internet-node/ipv4-l3-protocol.cc ---- a/src/internet-node/ipv4-l3-protocol.cc Sun Aug 12 22:43:25 2007 -0700 -+++ b/src/internet-node/ipv4-l3-protocol.cc Mon Aug 13 12:08:01 2007 -0700 -@@ -246,12 +246,26 @@ Ipv4L3Protocol::SetDefaultRoute (Ipv4Add - } - - void --Ipv4L3Protocol::Lookup (Ipv4Header const &ipHeader, -- Packet packet, -- Ipv4RoutingProtocol::RouteReplyCallback routeReply) --{ -- NS_DEBUG("Ipv4L3Protocol::Lookup (" << &ipHeader << ", " << &packet << -- &routeReply << ")"); -+Ipv4L3Protocol::Lookup ( -+ Ipv4Header const &ipHeader, -+ Packet packet, -+ Ipv4RoutingProtocol::RouteReplyCallback routeReply) -+{ -+ NS_DEBUG("Ipv4L3Protocol::Lookup (" << &ipHeader << -+ ", " << &packet << &routeReply << ")"); -+ -+ Lookup (Ipv4RoutingProtocol::IF_INDEX_ANY, ipHeader, packet, routeReply); -+} -+ -+void -+Ipv4L3Protocol::Lookup ( -+ uint32_t ifIndex, -+ Ipv4Header const &ipHeader, -+ Packet packet, -+ Ipv4RoutingProtocol::RouteReplyCallback routeReply) -+{ -+ NS_DEBUG("Ipv4L3Protocol::Lookup (" << ifIndex << ", " << &ipHeader << -+ ", " << &packet << &routeReply << ")"); - - for (Ipv4RoutingProtocolList::const_iterator rprotoIter = - m_routingProtocols.begin (); -@@ -259,7 +273,8 @@ Ipv4L3Protocol::Lookup (Ipv4Header const - rprotoIter++) - { - NS_DEBUG("Ipv4L3Protocol::Lookup (): Requesting route"); -- if ((*rprotoIter).second->RequestRoute (ipHeader, packet, routeReply)) -+ if ((*rprotoIter).second->RequestRoute (ifIndex, ipHeader, packet, -+ routeReply)) - return; - } - -@@ -405,7 +420,9 @@ Ipv4L3Protocol::Receive( Ptr - protocol << ", " << from << ")"); - - uint32_t index = 0; -- for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++) -+ for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); -+ i != m_interfaces.end (); -+ i++) - { - if ((*i)->GetDevice () == device) - { -@@ -423,7 +440,7 @@ Ipv4L3Protocol::Receive( Ptr - return; - } - -- if (Forwarding (packet, ipHeader, device)) -+ if (Forwarding (index, packet, ipHeader, device)) - { - return; - } -@@ -521,10 +538,14 @@ Ipv4L3Protocol::SendRealOut (bool found, - } - - bool --Ipv4L3Protocol::Forwarding (Packet const &packet, Ipv4Header &ipHeader, Ptr device) --{ -- NS_DEBUG("Ipv4L3Protocol::Forwarding (" << &packet << ", " << &ipHeader << -- ", " << device << ")"); -+Ipv4L3Protocol::Forwarding ( -+ uint32_t ifIndex, -+ Packet const &packet, -+ Ipv4Header &ipHeader, -+ Ptr device) -+{ -+ NS_DEBUG("Ipv4L3Protocol::Forwarding (" << ifIndex << ", " << &packet << -+ ", " << &ipHeader << ", " << device << ")"); - - for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); - i != m_interfaces.end (); i++) -@@ -579,7 +600,7 @@ Ipv4L3Protocol::Forwarding (Packet const - ipHeader.SetTtl (ipHeader.GetTtl () - 1); - - NS_DEBUG("Ipv4L3Protocol::Forwarding (): Forwarding packet."); -- Lookup (ipHeader, packet, -+ Lookup (ifIndex, ipHeader, packet, - MakeCallback (&Ipv4L3Protocol::SendRealOut, this)); - // - // If this is a to a multicast address and this node is a member of the -diff -r 3760d52ef5d1 -r 3aef7d7a71c2 src/internet-node/ipv4-l3-protocol.h ---- a/src/internet-node/ipv4-l3-protocol.h Sun Aug 12 22:43:25 2007 -0700 -+++ b/src/internet-node/ipv4-l3-protocol.h Mon Aug 13 12:08:01 2007 -0700 -@@ -195,12 +195,19 @@ protected: - virtual void DoDispose (void); - - private: -+ void Lookup (uint32_t ifIndex, -+ Ipv4Header const &ipHeader, -+ Packet packet, -+ Ipv4RoutingProtocol::RouteReplyCallback routeReply); - - void SendRealOut (bool found, - Ipv4Route const &route, - Packet packet, - Ipv4Header const &ipHeader); -- bool Forwarding (Packet const &packet, Ipv4Header &ipHeader, Ptr device); -+ bool Forwarding (uint32_t ifIndex, -+ Packet const &packet, -+ Ipv4Header &ipHeader, -+ Ptr device); - void ForwardUp (Packet p, Ipv4Header const&ip); - uint32_t AddIpv4Interface (Ipv4Interface *interface); - void SetupLoopback (void); -diff -r 3760d52ef5d1 -r 3aef7d7a71c2 src/internet-node/ipv4-static-routing.cc ---- a/src/internet-node/ipv4-static-routing.cc Sun Aug 12 22:43:25 2007 -0700 -+++ b/src/internet-node/ipv4-static-routing.cc Mon Aug 13 12:08:01 2007 -0700 -@@ -196,7 +196,8 @@ Ipv4MulticastRoute * - Ipv4MulticastRoute * - Ipv4StaticRouting::LookupStatic ( - Ipv4Address origin, -- Ipv4Address group) -+ Ipv4Address group, -+ uint32_t ifIndex) - { - for (MulticastRoutesI i = m_multicastRoutes.begin (); - i != m_multicastRoutes.end (); -@@ -207,7 +208,11 @@ Ipv4StaticRouting::LookupStatic ( - origin == Ipv4Address::GetAny ()) && - group == route->GetGroup ()) - { -- return *i; -+ if (ifIndex == Ipv4RoutingProtocol::IF_INDEX_ANY || -+ ifIndex == route->GetInputInterface ()) -+ { -+ return *i; -+ } - } - } - return 0; -@@ -312,9 +317,11 @@ Ipv4StaticRouting::RemoveRoute (uint32_t - } - - bool --Ipv4StaticRouting::RequestRoute (Ipv4Header const &ipHeader, -- Packet packet, -- RouteReplyCallback routeReply) -+Ipv4StaticRouting::RequestRoute ( -+ uint32_t ifIndex, -+ Ipv4Header const &ipHeader, -+ Packet packet, -+ RouteReplyCallback routeReply) - { - NS_DEBUG ("Ipv4StaticRouting::RequestRoute (" << &ipHeader << ", " << - &packet << ", " << &routeReply << ")"); -@@ -328,27 +335,35 @@ Ipv4StaticRouting::RequestRoute (Ipv4Hea - // First, see if this is a multicast packet we have a route for. If we - // have a route, then send the packet down each of the specified interfaces. - // -- Ipv4MulticastRoute *mRoute = LookupStatic(ipHeader.GetSource (), -- ipHeader.GetDestination ()); -- if (mRoute) -- { -- NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): Multicast route"); -- for (uint32_t i = 0; i < mRoute->GetNOutputInterfaces (); ++i) -- { -- Packet p = packet; -- Ipv4Route route = -- Ipv4Route::CreateHostRouteTo(ipHeader.GetDestination (), -- mRoute->GetOutputInterface(i)); -+ if (ipHeader.GetDestination ().IsMulticast ()) -+ { -+ NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): Multicast destination"); -+ -+ Ipv4MulticastRoute *mRoute = LookupStatic(ipHeader.GetSource (), -+ ipHeader.GetDestination (), ifIndex); -+ -+ if (mRoute) -+ { - NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): " -- "Send via interface " << mRoute->GetOutputInterface(i)); -- routeReply (true, route, p, ipHeader); -- return true; -- } -+ "Multicast route found"); -+ for (uint32_t i = 0; i < mRoute->GetNOutputInterfaces (); ++i) -+ { -+ Packet p = packet; -+ Ipv4Route route = -+ Ipv4Route::CreateHostRouteTo(ipHeader.GetDestination (), -+ mRoute->GetOutputInterface(i)); -+ NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): " -+ "Send via interface " << mRoute->GetOutputInterface(i)); -+ routeReply (true, route, p, ipHeader); -+ return true; -+ } -+ } -+ return false; // Let other routing protocols try to handle this - } - // - // See if this is a unicast packet we have a route for. - // -- NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): Unicast route"); -+ NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): Unicast destination"); - Ipv4Route *route = LookupStatic (ipHeader.GetDestination ()); - if (route != 0) - { -diff -r 3760d52ef5d1 -r 3aef7d7a71c2 src/internet-node/ipv4-static-routing.h ---- a/src/internet-node/ipv4-static-routing.h Sun Aug 12 22:43:25 2007 -0700 -+++ b/src/internet-node/ipv4-static-routing.h Mon Aug 13 12:08:01 2007 -0700 -@@ -51,7 +51,8 @@ public: - public: - Ipv4StaticRouting () : m_defaultRoute (0) {} - -- virtual bool RequestRoute (Ipv4Header const &ipHeader, -+ virtual bool RequestRoute (uint32_t ifIndex, -+ Ipv4Header const &ipHeader, - Packet packet, - RouteReplyCallback routeReply); - -@@ -105,7 +106,8 @@ private: - typedef std::list::iterator MulticastRoutesI; - - Ipv4Route *LookupStatic (Ipv4Address dest); -- Ipv4MulticastRoute *LookupStatic (Ipv4Address origin, Ipv4Address group); -+ Ipv4MulticastRoute *LookupStatic (Ipv4Address origin, Ipv4Address group, -+ uint32_t ifIndex); - - HostRoutes m_hostRoutes; - NetworkRoutes m_networkRoutes; -diff -r 3760d52ef5d1 -r 3aef7d7a71c2 src/node/ipv4-address.cc ---- a/src/node/ipv4-address.cc Sun Aug 12 22:43:25 2007 -0700 -+++ b/src/node/ipv4-address.cc Mon Aug 13 12:08:01 2007 -0700 -@@ -171,8 +171,11 @@ bool - bool - Ipv4Address::IsMulticast (void) const - { -- // XXX -- return false; -+// -+// Multicast addresses are defined as ranging from 224.0.0.0 through -+// 239.255.255.255 (which is E0000000 through EFFFFFFF in hex). -+// -+ return (m_address >= 0xe0000000 && m_address <= 0xefffffff); - } - - uint32_t -diff -r 3760d52ef5d1 -r 3aef7d7a71c2 src/node/ipv4.h ---- a/src/node/ipv4.h Sun Aug 12 22:43:25 2007 -0700 -+++ b/src/node/ipv4.h Mon Aug 13 12:08:01 2007 -0700 -@@ -70,6 +70,7 @@ public: - /** - * \brief Asynchronously requests a route for a given packet and IP header - * -+ * \param ifIndex The interface index on which the packet was received. - * \param ipHeader IP header of the packet - * \param packet packet that is being sent or forwarded - * \param routeReply callback that will receive the route reply -@@ -99,9 +100,12 @@ public: - * immediately after the IP header, although most routing do not - * insert any extra header. - */ -- virtual bool RequestRoute (const Ipv4Header &ipHeader, -+ virtual bool RequestRoute (uint32_t ifIndex, -+ const Ipv4Header &ipHeader, - Packet packet, - RouteReplyCallback routeReply) = 0; -+ -+ static const uint32_t IF_INDEX_ANY = 0xffffffff; - }; - - /** - -changeset: 1285:a6fb891b59fd -user: Craig Dowell -date: Mon Aug 13 14:58:06 2007 -0700 -summary: cleanup. more complex multicast example - -diff -r 3aef7d7a71c2 -r a6fb891b59fd examples/csma-multicast.cc ---- a/examples/csma-multicast.cc Mon Aug 13 12:08:01 2007 -0700 -+++ b/examples/csma-multicast.cc Mon Aug 13 14:58:06 2007 -0700 -@@ -16,31 +16,27 @@ - - // Network topology - // --// n0 n1 n2 n3 --// | | | | --// ===================== --// --// - CBR/UDP flows from n0 to n1, and from n3 to n0 --// - UDP packet size of 210 bytes, with per-packet interval 0.00375 sec. --// (i.e., DataRate of 448,000 bps) --// - DropTail queues --// - Tracing of queues and packet receptions to file "csma-one-subnet.tr" -- --#include --#include --#include --#include -+// Lan1 -+// =========== -+// | | | -+// n0 n1 n2 n3 n4 -+// | | | -+// =========== -+// Lan0 -+// -+// - Multicast source is at node n0; -+// - Multicast forwarded by node n2 onto LAN1; -+// - Nodes n0, n1, n2, n3, and n4 receive the multicast frame. -+// - Node n4 listens for the data (actual listener not yet implementted) - - #include "ns3/command-line.h" - #include "ns3/default-value.h" - #include "ns3/ptr.h" - #include "ns3/random-variable.h" - #include "ns3/debug.h" -- - #include "ns3/simulator.h" - #include "ns3/nstime.h" - #include "ns3/data-rate.h" -- - #include "ns3/ascii-trace.h" - #include "ns3/pcap-trace.h" - #include "ns3/internet-node.h" -@@ -58,15 +54,18 @@ - - using namespace ns3; - --NS_DEBUG_COMPONENT_DEFINE ("Me"); -+NS_DEBUG_COMPONENT_DEFINE ("CsmaMulticast"); - - int - main (int argc, char *argv[]) - { -- // Users may find it convenient to turn on explicit debugging -- // for selected modules; the below lines suggest how to do this -+// -+// Users may find it convenient to turn on explicit debugging -+// for selected modules; the below lines suggest how to do this -+// - #if 0 -- DebugComponentEnable("Me"); -+ DebugComponentEnable("CsmaMulticast"); -+ - DebugComponentEnable("Object"); - DebugComponentEnable("Queue"); - DebugComponentEnable("DropTailQueue"); -@@ -86,105 +85,182 @@ main (int argc, char *argv[]) - DebugComponentEnable("Ipv4LoopbackInterface"); - #endif - -- DebugComponentEnable("Me"); -+ DebugComponentEnable("UdpSocket"); -+ DebugComponentEnable("UdpL4Protocol"); -+ DebugComponentEnable("Ipv4L3Protocol"); -+ DebugComponentEnable("Ipv4StaticRouting"); -+ DebugComponentEnable("Ipv4Interface"); -+ DebugComponentEnable("ArpIpv4Interface"); -+ DebugComponentEnable("Ipv4LoopbackInterface"); -+ -+ DebugComponentEnable("CsmaMulticast"); - DebugComponentEnable("CsmaChannel"); - DebugComponentEnable("CsmaNetDevice"); -- DebugComponentEnable("UdpL4Protocol"); -- -- // Set up some default values for the simulation. Use the Bind() -- // technique to tell the system what subclass of Queue to use, -- // and what the queue limit is -- -- // The below Bind command tells the queue factory which class to -- // instantiate, when the queue factory is invoked in the topology code -+// -+// Set up default values for the simulation. Use the DefaultValue::Bind() -+// technique to tell the system what subclass of Queue to use. The Bind -+// command command tells the queue factory which class to instantiate when the -+// queue factory is invoked in the topology code -+// - DefaultValue::Bind ("Queue", "DropTailQueue"); -- -- // Allow the user to override any of the defaults and the above -- // Bind()s at run-time, via command-line arguments -+// -+// Allow the user to override any of the defaults and the above Bind() at -+// run-time, via command-line arguments -+// - CommandLine::Parse (argc, argv); -- -- // Here, we will explicitly create four nodes. In more sophisticated -- // topologies, we could configure a node factory. -+// -+// Explicitly create the nodes required by the topology (shown above). -+// - NS_DEBUG("Create nodes."); - Ptr n0 = Create (); - Ptr n1 = Create (); - Ptr n2 = Create (); - Ptr n3 = Create (); -+ Ptr n4 = Create (); - - NS_DEBUG("Create channels."); -- // We create the channels first without any IP addressing information -- Ptr channel0 = -+// -+// Explicitly create the channels required by the topology (shown above). -+// -+ Ptr lan0 = - CsmaTopology::CreateCsmaChannel( - DataRate(5000000), MilliSeconds(2)); - -+ Ptr lan1 = -+ CsmaTopology::CreateCsmaChannel( -+ DataRate(5000000), MilliSeconds(2)); -+ - NS_DEBUG("Build Topology."); -- uint32_t netDeviceNumberNode0 = CsmaIpv4Topology::AddIpv4CsmaNode (n0, -- channel0, Eui48Address("10:54:23:54:23:50")); -- uint32_t netDeviceNumberNode1 = CsmaIpv4Topology::AddIpv4CsmaNode (n1, -- channel0, Eui48Address("10:54:23:54:23:51")); -- uint32_t netDeviceNumberNode2 = CsmaIpv4Topology::AddIpv4CsmaNode (n2, -- channel0, Eui48Address("10:54:23:54:23:52")); -- uint32_t netDeviceNumberNode3 = CsmaIpv4Topology::AddIpv4CsmaNode (n3, -- channel0, Eui48Address("10:54:23:54:23:53")); -- -- NS_DEBUG ("netDeviceNumberNode0 = " << netDeviceNumberNode0); -- NS_DEBUG ("netDeviceNumberNode1 = " << netDeviceNumberNode1); -- NS_DEBUG ("netDeviceNumberNode2 = " << netDeviceNumberNode2); -- NS_DEBUG ("netDeviceNumberNode3 = " << netDeviceNumberNode3); -- -- // Later, we add IP addresses. -+// -+// Now fill out the topology by creating the net devices required to connect -+// the nodes to the channels and hooking them up. AddIpv4CsmaNetDevice will -+// create a net device, add a MAC address (in memory of the pink flamingo) and -+// connect the net device to a nodes and also to a channel. the -+// AddIpv4CsmaNetDevice method returns a net device index for the net device -+// created on the node. Interpret nd0 as the net device we created for node -+// zero. Interpret nd2Lan0 as the net device we created for node two to -+// connect to Lan0. -+// -+ uint32_t nd0 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n0, lan0, -+ Eui48Address("08:00:2e:00:00:00")); -+ uint32_t nd1 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n1, lan0, -+ Eui48Address("08:00:2e:00:00:01")); -+ uint32_t nd2Lan0 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n2, lan0, -+ Eui48Address("08:00:2e:00:00:02")); -+ -+ uint32_t nd2Lan1 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n2, lan1, -+ Eui48Address("08:00:2e:00:00:00")); -+ uint32_t nd3 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n3, lan1, -+ Eui48Address("08:00:2e:00:00:01")); -+ uint32_t nd4 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n4, lan1, -+ Eui48Address("08:00:2e:00:00:02")); -+ -+ NS_DEBUG ("nd0 = " << nd0); -+ NS_DEBUG ("nd1 = " << nd1); -+ NS_DEBUG ("nd2Lan0 = " << nd2Lan0); -+ NS_DEBUG ("nd2Lan1 = " << nd2Lan1); -+ NS_DEBUG ("nd3 = " << nd3); -+ NS_DEBUG ("nd4 = " << nd3); -+// -+// We've got the "hardware" in place. Now we need to add IP addresses. -+// - NS_DEBUG("Assign IP Addresses."); -- // XXX BUGBUG -- // Need a better way to get the interface index. The point-to-point topology -- // as implemented can't return the index since it creates interfaces on both -- // sides (i.e., AddIpv4Addresses, not AddIpv4Address). Need a method on -- // Ipv4 to find the interface index corresponding to a given ipv4 address. -- uint32_t ifIndexNode0 = CsmaIpv4Topology::AddIpv4Address (n0, -- netDeviceNumberNode0, Ipv4Address ("10.1.1.1"), -- Ipv4Mask ("255.255.255.0")); -- -- uint32_t ifIndexNode1 = CsmaIpv4Topology::AddIpv4Address (n1, -- netDeviceNumberNode1, Ipv4Address ("10.1.1.2"), -- Ipv4Mask ("255.255.255.0")); -- -- uint32_t ifIndexNode2 = CsmaIpv4Topology::AddIpv4Address (n2, -- netDeviceNumberNode2, Ipv4Address ("10.1.1.3"), -- Ipv4Mask ("255.255.255.0")); -- -- uint32_t ifIndexNode3 = CsmaIpv4Topology::AddIpv4Address (n3, -- netDeviceNumberNode3, Ipv4Address ("10.1.1.4"), -- Ipv4Mask ("255.255.255.0")); -- -- NS_DEBUG ("ifIndexNode0 = " << ifIndexNode0); -- NS_DEBUG ("ifIndexNode1 = " << ifIndexNode1); -- NS_DEBUG ("ifIndexNode2 = " << ifIndexNode2); -- NS_DEBUG ("ifIndexNode3 = " << ifIndexNode3); -- -- // Configure multicasting -+// -+// XXX BUGBUG -+// Need a better way to get the interface index. The point-to-point topology -+// as implemented can't return the index since it creates interfaces on both -+// sides (i.e., it does AddIpv4Addresses, not AddIpv4Address). We need a -+// method on Ipv4 to find the interface index corresponding to a given ipv4 -+// address. -+// -+// First, assign IP addresses to the net devices and associated interfaces -+// on Lan0. The AddIpv4Address method returns an Ipv4 interface index. -+// Interpret ifIndexNd0 as the interface index to use to reference the -+// net device we created on node zero when coming in from the Ipv4 interface. -+// Net device numbers and interface indices are distinct. Interpret -+// ifIndexNd2Lan0 as the interface index to use to reference the -+// net device we created that connects node two to lan zero. -+// -+ uint32_t ifIndexNd0 = CsmaIpv4Topology::AddIpv4Address (n0, nd0, -+ Ipv4Address ("10.1.1.1"), Ipv4Mask ("255.255.255.0")); -+ -+ uint32_t ifIndexNd1 = CsmaIpv4Topology::AddIpv4Address (n1, nd1, -+ Ipv4Address ("10.1.1.2"), Ipv4Mask ("255.255.255.0")); -+ -+ uint32_t ifIndexNd2Lan0 = CsmaIpv4Topology::AddIpv4Address (n2, nd2Lan0, -+ Ipv4Address ("10.1.1.3"), Ipv4Mask ("255.255.255.0")); -+// -+// Assign IP addresses to the net devices and associated interfaces on Lan1 -+// -+ uint32_t ifIndexNd2Lan1 = CsmaIpv4Topology::AddIpv4Address (n2, nd2Lan1, -+ Ipv4Address ("10.1.2.1"), Ipv4Mask ("255.255.255.0")); -+ -+ uint32_t ifIndexNd3 = CsmaIpv4Topology::AddIpv4Address (n3, nd1, -+ Ipv4Address ("10.1.2.2"), Ipv4Mask ("255.255.255.0")); -+ -+ uint32_t ifIndexNd4 = CsmaIpv4Topology::AddIpv4Address (n4, nd4, -+ Ipv4Address ("10.1.2.3"), Ipv4Mask ("255.255.255.0")); -+ -+ NS_DEBUG ("ifIndexNd0 = " << ifIndexNd0); -+ NS_DEBUG ("ifIndexNd1 = " << ifIndexNd1); -+ NS_DEBUG ("ifIndexNd2Lan0 = " << ifIndexNd2Lan0); -+ NS_DEBUG ("ifIndexNd2Lan1 = " << ifIndexNd2Lan1); -+ NS_DEBUG ("ifIndexNd3 = " << ifIndexNd3); -+ NS_DEBUG ("ifIndexNd4 = " << ifIndexNd4); - NS_DEBUG("Configure multicasting."); -+// -+// Now we can configure multicasting. As described above, the multicast -+// source is at node zero, which we assigned the IP address of 10.1.1.1 -+// earlier. We need to define a multicast group to send packets to. This -+// can be any multicast address from 224.0.0.0 through 239.255.255.255 -+// (avoiding the reserved routing protocol addresses). We just pick a -+// convenient number. -+// - Ipv4Address multicastSource ("10.1.1.1"); - Ipv4Address multicastGroup ("225.0.0.0"); -- -+// -+// We are going to manually configure multicast routing. This means telling -+// node two that it should expect multicast data coming from IP address -+// 10.1.1.1 over its IP interface connected to Lan0. These are called -+// multicastSource and ifIndexNd2Lan0 respectively. When node two receives -+// these packets, they should be forwarded out the interface that connects it -+// to Lan1 which is called ifIndexNd2Lan1. All we need to do is to call the -+// AddMulticastRoute method on node two's Ipv4 interface and provide this -+// information. (Note: the vector of output interfaces is in case there are -+// multiple net devices on a node). -+// - Ptr ipv4; -+ ipv4 = n2->QueryInterface (Ipv4::iid); -+ -+ std::vector outputInterfaces (1); -+ outputInterfaces[0] = ifIndexNd2Lan1; -+ -+ ipv4->AddMulticastRoute (multicastSource, multicastGroup, ifIndexNd2Lan0, -+ outputInterfaces); -+// -+// We also need to explain to the node zero forwarding code that when it sees -+// a packet destined for the multicast group it needs to send it out its -+// one and only interface. The 0xffffffff in the call means that the input -+// interface qualification is not applicable in this case (the packet has -+// not been received over an interface, it has been created locally). -+// - ipv4 = n0->QueryInterface (Ipv4::iid); - -- std::vector outputInterfaces (1); -- outputInterfaces[0] = ifIndexNode0; -- -- ipv4->AddMulticastRoute (multicastSource, multicastGroup, 0, -+ outputInterfaces[0] = ifIndexNd0;; -+ -+ ipv4->AddMulticastRoute (multicastSource, multicastGroup, 0xffffffff, - outputInterfaces); -- -- ipv4 = n1->QueryInterface (Ipv4::iid); -- // ipv4->JoinMulticastGroup (multicastSource, multicastGroup); -- -- ipv4 = n2->QueryInterface (Ipv4::iid); -- // ipv4->JoinMulticastGroup (multicastSource, multicastGroup); -- -- ipv4 = n3->QueryInterface (Ipv4::iid); -- // ipv4->JoinMulticastGroup (multicastSource, multicastGroup); -- -- // Create the OnOff application to send UDP datagrams -- // from n0 to the multicast group -+// -+// As described above, node four will be the only node listening for the -+// multicast data. To enable forwarding bits up the protocol stack, we need -+// to tell the stack to join the multicast group. -+// -+ ipv4 = n4->QueryInterface (Ipv4::iid); -+ ipv4->JoinMulticastGroup (multicastSource, multicastGroup); -+// -+// Create an OnOff application to send UDP datagrams from node zero to the -+// multicast group (node four will be listening). -+// - NS_DEBUG("Create Applications."); - Ptr ooff = Create ( - n0, -@@ -192,27 +268,33 @@ main (int argc, char *argv[]) - "Udp", - ConstantVariable(1), - ConstantVariable(0), -- DataRate ("128b/s"), -+ DataRate ("255b/s"), - 128); -- // Start the application -+// -+// Tell the application when to start and stop. -+// - ooff->Start(Seconds(1.)); - ooff->Stop (Seconds(10.)); -- -- // Configure tracing of all enqueue, dequeue, and NetDevice receive events -- // Trace output will be sent to the csma-one-subnet.tr file -+// -+// Configure tracing of all enqueue, dequeue, and NetDevice receive events. -+// Trace output will be sent to the file "csma-multicast.tr" -+// - NS_DEBUG("Configure Tracing."); - AsciiTrace asciitrace ("csma-multicast.tr"); - asciitrace.TraceAllNetDeviceRx (); - asciitrace.TraceAllQueues (); -- -- // Also configure some tcpdump traces; each interface will be traced -- // The output files will be named -- // simple-point-to-point.pcap-- -- // and can be read by the "tcpdump -r" command (use "-tt" option to -- // display timestamps correctly) -+// -+// Also configure some tcpdump traces; each interface will be traced. -+// The output files will be named: -+// csma-multicast.pcap-- -+// and can be read by the "tcpdump -r" command (use "-tt" option to -+// display timestamps correctly) -+// - PcapTrace pcaptrace ("csma-multicast.pcap"); - pcaptrace.TraceAllIp (); -- -+// -+// Now, do the actual simulation. -+// - NS_DEBUG("Run Simulation."); - Simulator::Run (); - Simulator::Destroy (); -diff -r 3aef7d7a71c2 -r a6fb891b59fd examples/csma-one-subnet.cc ---- a/examples/csma-one-subnet.cc Mon Aug 13 12:08:01 2007 -0700 -+++ b/examples/csma-one-subnet.cc Mon Aug 13 14:58:06 2007 -0700 -@@ -14,35 +14,25 @@ - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - --// Port of ns-2/tcl/ex/simple.tcl to ns-3 --// - // Network topology - // - // n0 n1 n2 n3 - // | | | | --// ===================== --// --// - CBR/UDP flows from n0 to n1, and from n3 to n0 --// - UDP packet size of 210 bytes, with per-packet interval 0.00375 sec. --// (i.e., DataRate of 448,000 bps) -+// ================= -+// LAN -+// -+// - CBR/UDP flows from n0 to n1 and from n3 to n0 - // - DropTail queues - // - Tracing of queues and packet receptions to file "csma-one-subnet.tr" -- --#include --#include --#include --#include - - #include "ns3/command-line.h" - #include "ns3/default-value.h" - #include "ns3/ptr.h" - #include "ns3/random-variable.h" - #include "ns3/debug.h" -- - #include "ns3/simulator.h" - #include "ns3/nstime.h" - #include "ns3/data-rate.h" -- - #include "ns3/ascii-trace.h" - #include "ns3/pcap-trace.h" - #include "ns3/internet-node.h" -@@ -60,15 +50,18 @@ - - using namespace ns3; - --NS_DEBUG_COMPONENT_DEFINE ("Me"); -+NS_DEBUG_COMPONENT_DEFINE ("CsmaOneSubnet"); - - int - main (int argc, char *argv[]) - { -- // Users may find it convenient to turn on explicit debugging -- // for selected modules; the below lines suggest how to do this -+// -+// Users may find it convenient to turn on explicit debugging -+// for selected modules; the below lines suggest how to do this -+// - #if 0 -- DebugComponentEnable("Me"); -+ DebugComponentEnable("CsmaOneSubnet"); -+ - DebugComponentEnable("Object"); - DebugComponentEnable("Queue"); - DebugComponentEnable("DropTailQueue"); -@@ -88,71 +81,90 @@ main (int argc, char *argv[]) - DebugComponentEnable("Ipv4LoopbackInterface"); - #endif - -- DebugComponentEnable("Me"); -- DebugComponentEnable("OnOffApplication"); -- DebugComponentEnable("UdpSocket"); -- DebugComponentEnable("UdpL4Protocol"); -- DebugComponentEnable("Ipv4L3Protocol"); -- DebugComponentEnable("Ipv4StaticRouting"); -- DebugComponentEnable("CsmaNetDevice"); -- DebugComponentEnable("CsmaChannel"); -- DebugComponentEnable("Ipv4Interface"); -- DebugComponentEnable("ArpIpv4Interface"); -- DebugComponentEnable("Ipv4LoopbackInterface"); -- -- // Set up some default values for the simulation. Use the Bind() -- // technique to tell the system what subclass of Queue to use, -- // and what the queue limit is -- -- // The below Bind command tells the queue factory which class to -- // instantiate, when the queue factory is invoked in the topology code -+// -+// Set up default values for the simulation. Use the DefaultValue::Bind() -+// technique to tell the system what subclass of Queue to use. The Bind -+// command command tells the queue factory which class to instantiate when the -+// queue factory is invoked in the topology code -+// - DefaultValue::Bind ("Queue", "DropTailQueue"); -- -- // Allow the user to override any of the defaults and the above -- // Bind()s at run-time, via command-line arguments -+// -+// Allow the user to override any of the defaults and the above Bind() at -+// run-time, via command-line arguments -+// - CommandLine::Parse (argc, argv); -- -- // Here, we will explicitly create four nodes. In more sophisticated -- // topologies, we could configure a node factory. -+// -+// Explicitly create the nodes required by the topology (shown above). -+// - NS_DEBUG("Create nodes."); - Ptr n0 = Create (); - Ptr n1 = Create (); - Ptr n2 = Create (); - Ptr n3 = Create (); - -- // We create the channels first without any IP addressing information - NS_DEBUG("Create channels."); -- Ptr channel0 = -- CsmaTopology::CreateCsmaChannel( -- DataRate(5000000), MilliSeconds(2)); -+// -+// Explicitly create the channels required by the topology (shown above). -+// -+ Ptr lan = CsmaTopology::CreateCsmaChannel( -+ DataRate(5000000), MilliSeconds(2)); - - NS_DEBUG("Build Topology."); -- uint32_t n0ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n0, channel0, -- Eui48Address("10:54:23:54:23:50")); -- uint32_t n1ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n1, channel0, -- Eui48Address("10:54:23:54:23:51")); -- uint32_t n2ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n2, channel0, -- Eui48Address("10:54:23:54:23:52")); -- uint32_t n3ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n3, channel0, -- Eui48Address("10:54:23:54:23:53")); -- -- // Later, we add IP addresses. -+// -+// Now fill out the topology by creating the net devices required to connect -+// the nodes to the channels and hooking them up. AddIpv4CsmaNetDevice will -+// create a net device, add a MAC address (in memory of the pink flamingo) and -+// connect the net device to a nodes and also to a channel. the -+// AddIpv4CsmaNetDevice method returns a net device index for the net device -+// created on the node. Interpret nd0 as the net device we created for node -+// zero. -+// -+ uint32_t nd0 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n0, lan, -+ Eui48Address("08:00:2e:00:00:00")); -+ -+ uint32_t nd1 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n1, lan, -+ Eui48Address("08:00:2e:00:00:01")); -+ -+ uint32_t nd2 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n2, lan, -+ Eui48Address("08:00:2e:00:00:02")); -+ -+ uint32_t nd3 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n3, lan, -+ Eui48Address("08:00:2e:00:00:03")); -+ -+ NS_DEBUG ("nd0 = " << nd0); -+ NS_DEBUG ("nd1 = " << nd1); -+ NS_DEBUG ("nd2 = " << nd2); -+ NS_DEBUG ("nd3 = " << nd3); -+// -+// We've got the "hardware" in place. Now we need to add IP addresses. -+// - NS_DEBUG("Assign IP Addresses."); -- CsmaIpv4Topology::AddIpv4Address ( -- n0, n0ifIndex, Ipv4Address("10.1.1.1"), Ipv4Mask("255.255.255.0")); -- -- CsmaIpv4Topology::AddIpv4Address ( -- n1, n1ifIndex, Ipv4Address("10.1.1.2"), Ipv4Mask("255.255.255.0")); -- -- CsmaIpv4Topology::AddIpv4Address ( -- n2, n2ifIndex, Ipv4Address("10.1.1.3"), Ipv4Mask("255.255.255.0")); -+// -+// XXX BUGBUG -+// Need a better way to get the interface index. The point-to-point topology -+// as implemented can't return the index since it creates interfaces on both -+// sides (i.e., it does AddIpv4Addresses, not AddIpv4Address). We need a -+// method on Ipv4 to find the interface index corresponding to a given ipv4 -+// address. -+// -+// Assign IP addresses to the net devices and associated interfaces -+// on the lan. The AddIpv4Address method returns an Ipv4 interface index -+// which we do not need here. -+// -+ CsmaIpv4Topology::AddIpv4Address (n0, nd0, Ipv4Address("10.1.1.1"), -+ Ipv4Mask("255.255.255.0")); -+ -+ CsmaIpv4Topology::AddIpv4Address (n1, nd1, Ipv4Address("10.1.1.2"), -+ Ipv4Mask("255.255.255.0")); -+ -+ CsmaIpv4Topology::AddIpv4Address (n2, nd2, Ipv4Address("10.1.1.3"), -+ Ipv4Mask("255.255.255.0")); - -- CsmaIpv4Topology::AddIpv4Address ( -- n3, n3ifIndex, Ipv4Address("10.1.1.4"), Ipv4Mask("255.255.255.0")); -- -- // Create the OnOff application to send UDP datagrams of size -- // 210 bytes at a rate of 448 Kb/s -- // from n0 to n1 -+ CsmaIpv4Topology::AddIpv4Address (n3, nd3, Ipv4Address("10.1.1.4"), -+ Ipv4Mask("255.255.255.0")); -+// -+// Create an OnOff application to send UDP datagrams from node zero to node 1. -+// - NS_DEBUG("Create Applications."); - Ptr ooff = Create ( - n0, -@@ -160,36 +172,43 @@ main (int argc, char *argv[]) - "Udp", - ConstantVariable(1), - ConstantVariable(0)); -- // Start the application -+// -+// Tell the application when to start and stop. -+// - ooff->Start(Seconds(1.0)); - ooff->Stop (Seconds(10.0)); -- -- // Create a similar flow from n3 to n0, starting at time 1.1 seconds -+// -+// Create a similar flow from n3 to n0, starting at time 1.1 seconds -+// - ooff = Create ( - n3, - InetSocketAddress ("10.1.1.1", 80), - "Udp", - ConstantVariable(1), - ConstantVariable(0)); -- // Start the application -+ - ooff->Start(Seconds(1.1)); - ooff->Stop (Seconds(10.0)); -- -- // Configure tracing of all enqueue, dequeue, and NetDevice receive events -- // Trace output will be sent to the csma-one-subnet.tr file -- NS_DEBUG("Configure Tracing."); -+// -+// Configure tracing of all enqueue, dequeue, and NetDevice receive events. -+// Trace output will be sent to the file "csma-one-subnet.tr" -+// -+ NS_DEBUG("Configure Tracing."); - AsciiTrace asciitrace ("csma-one-subnet.tr"); - asciitrace.TraceAllNetDeviceRx (); - asciitrace.TraceAllQueues (); -- -- // Also configure some tcpdump traces; each interface will be traced -- // The output files will be named -- // simple-point-to-point.pcap-- -- // and can be read by the "tcpdump -r" command (use "-tt" option to -- // display timestamps correctly) -+// -+// Also configure some tcpdump traces; each interface will be traced. -+// The output files will be named: -+// csma-one-subnet.pcap-- -+// and can be read by the "tcpdump -r" command (use "-tt" option to -+// display timestamps correctly) -+// - PcapTrace pcaptrace ("csma-one-subnet.pcap"); - pcaptrace.TraceAllIp (); -- -+// -+// Now, do the actual simulation. -+// - NS_DEBUG("Run Simulation."); - Simulator::Run (); - Simulator::Destroy (); -diff -r 3aef7d7a71c2 -r a6fb891b59fd examples/mixed-global-routing.cc ---- a/examples/mixed-global-routing.cc Mon Aug 13 12:08:01 2007 -0700 -+++ b/examples/mixed-global-routing.cc Mon Aug 13 14:58:06 2007 -0700 -@@ -128,13 +128,13 @@ int main (int argc, char *argv[]) - CsmaTopology::CreateCsmaChannel( - DataRate(5000000), MilliSeconds(2)); - -- uint32_t n2ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n2, channelc0, -+ uint32_t n2ifIndex = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n2, channelc0, - Eui48Address("10:54:23:54:23:50")); -- uint32_t n3ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n3, channelc0, -+ uint32_t n3ifIndex = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n3, channelc0, - Eui48Address("10:54:23:54:23:51")); -- uint32_t n4ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n4, channelc0, -+ uint32_t n4ifIndex = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n4, channelc0, - Eui48Address("10:54:23:54:23:52")); -- uint32_t n5ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n5, channelc0, -+ uint32_t n5ifIndex = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n5, channelc0, - Eui48Address("10:54:23:54:23:53")); - - // Later, we add IP addresses. -diff -r 3aef7d7a71c2 -r a6fb891b59fd src/devices/csma/csma-ipv4-topology.cc ---- a/src/devices/csma/csma-ipv4-topology.cc Mon Aug 13 12:08:01 2007 -0700 -+++ b/src/devices/csma/csma-ipv4-topology.cc Mon Aug 13 14:58:06 2007 -0700 -@@ -35,19 +35,20 @@ namespace ns3 { - namespace ns3 { - - uint32_t --CsmaIpv4Topology::AddIpv4CsmaNode(Ptr n1, -- Ptr ch, -- Eui48Address addr) -+CsmaIpv4Topology::AddIpv4CsmaNetDevice( -+ Ptr node, -+ Ptr channel, -+ Eui48Address addr) - { - Ptr q = Queue::CreateDefault (); - - // assume full-duplex -- Ptr nd0 = Create (n1, addr, -- ns3::CsmaNetDevice::IP_ARP, -- true, true); -- nd0->AddQueue(q); -- nd0->Attach (ch); -- return nd0->GetIfIndex (); -+ Ptr nd = Create (node, addr, -+ ns3::CsmaNetDevice::IP_ARP, true, true); -+ -+ nd->AddQueue(q); -+ nd->Attach (channel); -+ return nd->GetIfIndex (); - } - - -diff -r 3aef7d7a71c2 -r a6fb891b59fd src/devices/csma/csma-ipv4-topology.h ---- a/src/devices/csma/csma-ipv4-topology.h Mon Aug 13 12:08:01 2007 -0700 -+++ b/src/devices/csma/csma-ipv4-topology.h Mon Aug 13 14:58:06 2007 -0700 -@@ -61,9 +61,9 @@ public: - * - * \return ifIndex of the device - */ -- static uint32_t AddIpv4CsmaNode( Ptr n1, -- Ptr ch, -- Eui48Address addr); -+ static uint32_t AddIpv4CsmaNetDevice(Ptr node, -+ Ptr channel, -+ Eui48Address addr); - - /** - * \param n1 Node to be attached to the Csma channel - -changeset: 1286:2b63aafb050b -user: Craig Dowell -date: Mon Aug 13 16:21:39 2007 -0700 -summary: set source address in socket - -diff -r a6fb891b59fd -r 2b63aafb050b examples/csma-multicast.cc ---- a/examples/csma-multicast.cc Mon Aug 13 14:58:06 2007 -0700 -+++ b/examples/csma-multicast.cc Mon Aug 13 16:21:39 2007 -0700 -@@ -123,12 +123,10 @@ main (int argc, char *argv[]) - // Explicitly create the channels required by the topology (shown above). - // - Ptr lan0 = -- CsmaTopology::CreateCsmaChannel( -- DataRate(5000000), MilliSeconds(2)); -+ CsmaTopology::CreateCsmaChannel(DataRate(5000000), MilliSeconds(2)); - - Ptr lan1 = -- CsmaTopology::CreateCsmaChannel( -- DataRate(5000000), MilliSeconds(2)); -+ CsmaTopology::CreateCsmaChannel(DataRate(5000000), MilliSeconds(2)); - - NS_DEBUG("Build Topology."); - // -diff -r a6fb891b59fd -r 2b63aafb050b src/internet-node/ipv4-end-point.cc ---- a/src/internet-node/ipv4-end-point.cc Mon Aug 13 14:58:06 2007 -0700 -+++ b/src/internet-node/ipv4-end-point.cc Mon Aug 13 16:21:39 2007 -0700 -@@ -42,6 +42,13 @@ Ipv4EndPoint::GetLocalAddress (void) - { - return m_localAddr; - } -+ -+void -+Ipv4EndPoint::SetLocalAddress (Ipv4Address address) -+{ -+ m_localAddr = address; -+} -+ - uint16_t - Ipv4EndPoint::GetLocalPort (void) - { -diff -r a6fb891b59fd -r 2b63aafb050b src/internet-node/ipv4-end-point.h ---- a/src/internet-node/ipv4-end-point.h Mon Aug 13 14:58:06 2007 -0700 -+++ b/src/internet-node/ipv4-end-point.h Mon Aug 13 16:21:39 2007 -0700 -@@ -37,6 +37,8 @@ public: - ~Ipv4EndPoint (); - - Ipv4Address GetLocalAddress (void); -+ void SetLocalAddress (Ipv4Address address); -+ - uint16_t GetLocalPort (void); - Ipv4Address GetPeerAddress (void); - uint16_t GetPeerPort (void); -diff -r a6fb891b59fd -r 2b63aafb050b src/internet-node/ipv4-impl.cc ---- a/src/internet-node/ipv4-impl.cc Mon Aug 13 14:58:06 2007 -0700 -+++ b/src/internet-node/ipv4-impl.cc Mon Aug 13 16:21:39 2007 -0700 -@@ -174,11 +174,28 @@ Ipv4Impl::GetNetworkMask (uint32_t i) co - { - return m_ipv4->GetNetworkMask (i); - } -+ - Ipv4Address - Ipv4Impl::GetAddress (uint32_t i) const - { - return m_ipv4->GetAddress (i); - } -+ -+Ipv4Address -+Ipv4Impl::GetSourceAddress (Ipv4Address destination) const -+{ -+ uint32_t ifIndex; -+ bool result = m_ipv4->GetIfIndexForDestination (destination, ifIndex); -+ if (result) -+ { -+ return m_ipv4->GetAddress (ifIndex); -+ } -+ else -+ { -+ return Ipv4Address::GetAny (); -+ } -+} -+ - uint16_t - Ipv4Impl::GetMtu (uint32_t i) const - { -diff -r a6fb891b59fd -r 2b63aafb050b src/internet-node/ipv4-impl.h ---- a/src/internet-node/ipv4-impl.h Mon Aug 13 14:58:06 2007 -0700 -+++ b/src/internet-node/ipv4-impl.h Mon Aug 13 16:21:39 2007 -0700 -@@ -81,6 +81,8 @@ public: - virtual void SetNetworkMask (uint32_t i, Ipv4Mask mask); - virtual Ipv4Mask GetNetworkMask (uint32_t t) const; - virtual Ipv4Address GetAddress (uint32_t i) const; -+ virtual Ipv4Address GetSourceAddress (Ipv4Address destination) const; -+ - virtual uint16_t GetMtu (uint32_t i) const; - virtual bool IsUp (uint32_t i) const; - virtual void SetUp (uint32_t i); -diff -r a6fb891b59fd -r 2b63aafb050b src/internet-node/ipv4-l3-protocol.cc ---- a/src/internet-node/ipv4-l3-protocol.cc Mon Aug 13 14:58:06 2007 -0700 -+++ b/src/internet-node/ipv4-l3-protocol.cc Mon Aug 13 16:21:39 2007 -0700 -@@ -691,6 +691,28 @@ Ipv4L3Protocol::GetAddress (uint32_t i) - return interface->GetAddress (); - } - -+bool -+Ipv4L3Protocol::GetIfIndexForDestination ( -+ Ipv4Address destination, uint32_t& ifIndex) const -+{ -+ NS_DEBUG("Ipv4L3Protocol::GetIfIndexForDestination (" << destination << -+ ", " << &ifIndex << ")"); -+ -+ for (Ipv4RoutingProtocolList::const_iterator i = m_routingProtocols.begin (); -+ i != m_routingProtocols.end (); -+ i++) -+ { -+ NS_DEBUG("Ipv4L3Protocol::Lookup (): Requesting Source Address"); -+ uint32_t ifIndex; -+ -+ if ((*i).second->RequestIfIndex (destination, ifIndex)) -+ { -+ return true; -+ } -+ } -+ return false; -+} -+ - uint16_t - Ipv4L3Protocol::GetMtu (uint32_t i) const - { -diff -r a6fb891b59fd -r 2b63aafb050b src/internet-node/ipv4-l3-protocol.h ---- a/src/internet-node/ipv4-l3-protocol.h Mon Aug 13 14:58:06 2007 -0700 -+++ b/src/internet-node/ipv4-l3-protocol.h Mon Aug 13 16:21:39 2007 -0700 -@@ -182,6 +182,8 @@ public: - void SetNetworkMask (uint32_t i, Ipv4Mask mask); - Ipv4Mask GetNetworkMask (uint32_t t) const; - Ipv4Address GetAddress (uint32_t i) const; -+ bool GetIfIndexForDestination (Ipv4Address destination, -+ uint32_t& ifIndex) const; - uint16_t GetMtu (uint32_t i) const; - bool IsUp (uint32_t i) const; - void SetUp (uint32_t i); -diff -r a6fb891b59fd -r 2b63aafb050b src/internet-node/ipv4-static-routing.cc ---- a/src/internet-node/ipv4-static-routing.cc Mon Aug 13 14:58:06 2007 -0700 -+++ b/src/internet-node/ipv4-static-routing.cc Mon Aug 13 16:21:39 2007 -0700 -@@ -377,6 +377,55 @@ Ipv4StaticRouting::RequestRoute ( - } - } - -+bool -+Ipv4StaticRouting::RequestIfIndex (Ipv4Address destination, uint32_t& ifIndex) -+{ -+ NS_DEBUG ("Ipv4StaticRouting::RequestIfIndex (" << destination << ", " << -+ &ifIndex << ")"); -+// -+// First, see if this is a multicast packet we have a route for. If we -+// have a route, then send the packet down each of the specified interfaces. -+// -+ if (destination.IsMulticast ()) -+ { -+ NS_DEBUG ("Ipv4StaticRouting::RequestIfIndex (): Multicast destination"); -+ -+ Ipv4MulticastRoute *mRoute = LookupStatic(Ipv4Address::GetAny (), -+ destination, Ipv4RoutingProtocol::IF_INDEX_ANY); -+ -+ if (mRoute) -+ { -+ NS_DEBUG ("Ipv4StaticRouting::RequestIfIndex (): " -+ "Multicast route found"); -+ -+ if (mRoute->GetNOutputInterfaces () != 1) -+ { -+ NS_DEBUG ("Ipv4StaticRouting::RequestIfIndex (): " -+ "Route is to multiple interfaces. Ignoring."); -+ return false; -+ } -+ -+ ifIndex = mRoute->GetOutputInterface(0); -+ return true; -+ } -+ return false; // Let other routing protocols try to handle this -+ } -+// -+// See if this is a unicast packet we have a route for. -+// -+ NS_DEBUG ("Ipv4StaticRouting::RequestIfIndex (): Unicast destination"); -+ Ipv4Route *route = LookupStatic (destination); -+ if (route) -+ { -+ ifIndex = route->GetInterface (); -+ return true; -+ } -+ else -+ { -+ return false; -+ } -+} -+ - void - Ipv4StaticRouting::DoDispose (void) - { -diff -r a6fb891b59fd -r 2b63aafb050b src/internet-node/ipv4-static-routing.h ---- a/src/internet-node/ipv4-static-routing.h Mon Aug 13 14:58:06 2007 -0700 -+++ b/src/internet-node/ipv4-static-routing.h Mon Aug 13 16:21:39 2007 -0700 -@@ -56,6 +56,7 @@ public: - Packet packet, - RouteReplyCallback routeReply); - -+ virtual bool RequestIfIndex (Ipv4Address destination, uint32_t& ifIndex); - - void AddHostRouteTo (Ipv4Address dest, - Ipv4Address nextHop, -diff -r a6fb891b59fd -r 2b63aafb050b src/internet-node/udp-socket.cc ---- a/src/internet-node/udp-socket.cc Mon Aug 13 14:58:06 2007 -0700 -+++ b/src/internet-node/udp-socket.cc Mon Aug 13 16:21:39 2007 -0700 -@@ -26,6 +26,7 @@ - #include "udp-l4-protocol.h" - #include "ipv4-end-point.h" - #include "ipv4-l4-demux.h" -+#include "ns3/ipv4.h" - - NS_DEBUG_COMPONENT_DEFINE ("UdpSocket"); - -@@ -180,6 +181,10 @@ UdpSocket::Connect(const Address & addre - m_defaultPort = transport.GetPort (); - NotifyConnectionSucceeded (); - m_connected = true; -+ -+ Ptr ipv4; -+ ipv4 = m_node->QueryInterface (Ipv4::iid); -+ m_endPoint->SetLocalAddress (ipv4->GetSourceAddress(m_defaultAddress)); - return 0; - } - -diff -r a6fb891b59fd -r 2b63aafb050b src/node/ipv4.h ---- a/src/node/ipv4.h Mon Aug 13 14:58:06 2007 -0700 -+++ b/src/node/ipv4.h Mon Aug 13 16:21:39 2007 -0700 -@@ -104,6 +104,16 @@ public: - const Ipv4Header &ipHeader, - Packet packet, - RouteReplyCallback routeReply) = 0; -+ /** -+ * \brief Synchronously request the interface index that will be used to -+ * send a packet to a hypothetical destination. -+ * -+ * \param destination IP address of a hypothetical destination packet -+ * \param ifIndex Reference to interface index. -+ * \returns True if the protocol has a route, false otherwise. -+ */ -+ virtual bool RequestIfIndex (Ipv4Address destination, -+ uint32_t& ifIndex) = 0; - - static const uint32_t IF_INDEX_ANY = 0xffffffff; - }; -@@ -309,6 +319,12 @@ public: - */ - virtual Ipv4Address GetAddress (uint32_t i) const = 0; - /** -+ * \param destination The IP address of a hypothetical destination. -+ * \returns The IP address assigned to the interface that will be used -+ * if we were to send a packet to destination. -+ */ -+ virtual Ipv4Address GetSourceAddress (Ipv4Address destination) const = 0; -+ /** - * \param i index of ipv4 interface - * \returns the Maximum Transmission Unit (in bytes) associated - * to the underlying ipv4 interface - -changeset: 1287:a70de165a25a -user: Craig Dowell -date: Mon Aug 13 19:54:47 2007 -0700 -summary: set source IP address in udp-socket packets - -diff -r 2b63aafb050b -r a70de165a25a examples/csma-multicast.cc ---- a/examples/csma-multicast.cc Mon Aug 13 16:21:39 2007 -0700 -+++ b/examples/csma-multicast.cc Mon Aug 13 19:54:47 2007 -0700 -@@ -71,11 +71,11 @@ main (int argc, char *argv[]) - DebugComponentEnable("DropTailQueue"); - DebugComponentEnable("Channel"); - DebugComponentEnable("CsmaChannel"); -+ DebugComponentEnable("NetDevice"); - DebugComponentEnable("CsmaNetDevice"); - DebugComponentEnable("Ipv4L3Protocol"); -- DebugComponentEnable("NetDevice"); -+ DebugComponentEnable("OnOffApplication"); - DebugComponentEnable("PacketSocket"); -- DebugComponentEnable("OnOffApplication"); - DebugComponentEnable("UdpSocket"); - DebugComponentEnable("UdpL4Protocol"); - DebugComponentEnable("Ipv4L3Protocol"); -@@ -84,18 +84,6 @@ main (int argc, char *argv[]) - DebugComponentEnable("ArpIpv4Interface"); - DebugComponentEnable("Ipv4LoopbackInterface"); - #endif -- -- DebugComponentEnable("UdpSocket"); -- DebugComponentEnable("UdpL4Protocol"); -- DebugComponentEnable("Ipv4L3Protocol"); -- DebugComponentEnable("Ipv4StaticRouting"); -- DebugComponentEnable("Ipv4Interface"); -- DebugComponentEnable("ArpIpv4Interface"); -- DebugComponentEnable("Ipv4LoopbackInterface"); -- -- DebugComponentEnable("CsmaMulticast"); -- DebugComponentEnable("CsmaChannel"); -- DebugComponentEnable("CsmaNetDevice"); - // - // Set up default values for the simulation. Use the DefaultValue::Bind() - // technique to tell the system what subclass of Queue to use. The Bind -diff -r 2b63aafb050b -r a70de165a25a examples/csma-one-subnet.cc ---- a/examples/csma-one-subnet.cc Mon Aug 13 16:21:39 2007 -0700 -+++ b/examples/csma-one-subnet.cc Mon Aug 13 19:54:47 2007 -0700 -@@ -80,7 +80,6 @@ main (int argc, char *argv[]) - DebugComponentEnable("ArpIpv4Interface"); - DebugComponentEnable("Ipv4LoopbackInterface"); - #endif -- - // - // Set up default values for the simulation. Use the DefaultValue::Bind() - // technique to tell the system what subclass of Queue to use. The Bind -diff -r 2b63aafb050b -r a70de165a25a src/internet-node/ipv4-impl.cc ---- a/src/internet-node/ipv4-impl.cc Mon Aug 13 16:21:39 2007 -0700 -+++ b/src/internet-node/ipv4-impl.cc Mon Aug 13 19:54:47 2007 -0700 -@@ -184,8 +184,10 @@ Ipv4Address - Ipv4Address - Ipv4Impl::GetSourceAddress (Ipv4Address destination) const - { -- uint32_t ifIndex; -+ uint32_t ifIndex = 0xffffffff; -+ - bool result = m_ipv4->GetIfIndexForDestination (destination, ifIndex); -+ - if (result) - { - return m_ipv4->GetAddress (ifIndex); -diff -r 2b63aafb050b -r a70de165a25a src/internet-node/ipv4-l3-protocol.cc ---- a/src/internet-node/ipv4-l3-protocol.cc Mon Aug 13 16:21:39 2007 -0700 -+++ b/src/internet-node/ipv4-l3-protocol.cc Mon Aug 13 19:54:47 2007 -0700 -@@ -703,10 +703,13 @@ Ipv4L3Protocol::GetIfIndexForDestination - i++) - { - NS_DEBUG("Ipv4L3Protocol::Lookup (): Requesting Source Address"); -- uint32_t ifIndex; -- -- if ((*i).second->RequestIfIndex (destination, ifIndex)) -- { -+ uint32_t ifIndexTmp; -+ -+ if ((*i).second->RequestIfIndex (destination, ifIndexTmp)) -+ { -+ NS_DEBUG("Ipv4L3Protocol::GetIfIndexForDestination (): " -+ "Found ifIndex " << ifIndexTmp); -+ ifIndex = ifIndexTmp; - return true; - } - } -diff -r 2b63aafb050b -r a70de165a25a src/internet-node/ipv4-static-routing.cc ---- a/src/internet-node/ipv4-static-routing.cc Mon Aug 13 16:21:39 2007 -0700 -+++ b/src/internet-node/ipv4-static-routing.cc Mon Aug 13 19:54:47 2007 -0700 -@@ -406,6 +406,8 @@ Ipv4StaticRouting::RequestIfIndex (Ipv4A - } - - ifIndex = mRoute->GetOutputInterface(0); -+ NS_DEBUG ("Ipv4StaticRouting::RequestIfIndex (): " -+ "Found ifIndex " << ifIndex); - return true; - } - return false; // Let other routing protocols try to handle this -diff -r 2b63aafb050b -r a70de165a25a src/internet-node/udp-socket.cc ---- a/src/internet-node/udp-socket.cc Mon Aug 13 16:21:39 2007 -0700 -+++ b/src/internet-node/udp-socket.cc Mon Aug 13 19:54:47 2007 -0700 -@@ -174,7 +174,7 @@ int - int - UdpSocket::Connect(const Address & address) - { -- NS_DEBUG("UdpSocket::Connect (" << address << ")"); -+ NS_DEBUG ("UdpSocket::Connect (" << address << ")"); - - InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); - m_defaultAddress = transport.GetIpv4 (); -@@ -185,6 +185,8 @@ UdpSocket::Connect(const Address & addre - Ptr ipv4; - ipv4 = m_node->QueryInterface (Ipv4::iid); - m_endPoint->SetLocalAddress (ipv4->GetSourceAddress(m_defaultAddress)); -+ NS_DEBUG ("UdpSocket::Connect (): Local address is" << -+ m_endPoint->GetLocalAddress()); - return 0; - } - -@@ -270,4 +272,4 @@ UdpSocket::ForwardUp (const Packet &pack - NotifyDataReceived (p, address); - } - --}//namespace ns3 -+} //namespace ns3 - -changeset: 1288:9f9fe7919c89 -user: Craig Dowell -date: Mon Aug 13 20:14:36 2007 -0700 -summary: Silliness for optimized version - -diff -r a70de165a25a -r 9f9fe7919c89 examples/csma-multicast.cc ---- a/examples/csma-multicast.cc Mon Aug 13 19:54:47 2007 -0700 -+++ b/examples/csma-multicast.cc Mon Aug 13 20:14:36 2007 -0700 -@@ -193,6 +193,15 @@ main (int argc, char *argv[]) - NS_DEBUG ("ifIndexNd2Lan1 = " << ifIndexNd2Lan1); - NS_DEBUG ("ifIndexNd3 = " << ifIndexNd3); - NS_DEBUG ("ifIndexNd4 = " << ifIndexNd4); -+// -+// A little silliness to let optimized code work while still printing all -+// results in debug code (without attribute). -+// -+ nd3 = nd3; -+ ifIndexNd1 = ifIndexNd1; -+ ifIndexNd3 = ifIndexNd3; -+ ifIndexNd4 = ifIndexNd4; -+ - NS_DEBUG("Configure multicasting."); - // - // Now we can configure multicasting. As described above, the multicast - -changeset: 1289:1d32949ae397 -user: Craig Dowell -date: Mon Aug 13 23:40:51 2007 -0700 -summary: fix non-unique ethernet addresses - -diff -r 9f9fe7919c89 -r 1d32949ae397 examples/csma-multicast.cc ---- a/examples/csma-multicast.cc Mon Aug 13 20:14:36 2007 -0700 -+++ b/examples/csma-multicast.cc Mon Aug 13 23:40:51 2007 -0700 -@@ -135,11 +135,11 @@ main (int argc, char *argv[]) - Eui48Address("08:00:2e:00:00:02")); - - uint32_t nd2Lan1 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n2, lan1, -- Eui48Address("08:00:2e:00:00:00")); -+ Eui48Address("08:00:2e:00:00:03")); - uint32_t nd3 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n3, lan1, -- Eui48Address("08:00:2e:00:00:01")); -+ Eui48Address("08:00:2e:00:00:04")); - uint32_t nd4 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n4, lan1, -- Eui48Address("08:00:2e:00:00:02")); -+ Eui48Address("08:00:2e:00:00:05")); - - NS_DEBUG ("nd0 = " << nd0); - NS_DEBUG ("nd1 = " << nd1); - -changeset: 1299:2cc09d5a04c4 -parent: 1289:1d32949ae397 -parent: 1298:8bbad559c665 -user: Craig Dowell -date: Mon Aug 20 13:40:15 2007 -0700 -summary: branch merge - -diff -r 1d32949ae397 -r 2cc09d5a04c4 .hgtags ---- a/.hgtags Mon Aug 13 23:40:51 2007 -0700 -+++ b/.hgtags Mon Aug 20 13:40:15 2007 -0700 -@@ -3,3 +3,4 @@ 0dc81e76166c56aaae64da48b673b62155943aad - 0dc81e76166c56aaae64da48b673b62155943aad packet-history-working - 38099dd26e9467b8f49f8632f22789858149a6e7 release ns-3.0.3 - 5701e60bf01a8ac1308945e69001e0cc07948faf release ns-3.0.4 -+08046b6aef37932507696a2f2f427b42d693781e release ns-3.0.5 -diff -r 1d32949ae397 -r 2cc09d5a04c4 AUTHORS ---- a/AUTHORS Mon Aug 13 23:40:51 2007 -0700 -+++ b/AUTHORS Mon Aug 20 13:40:15 2007 -0700 -@@ -3,4 +3,5 @@ Craig Dowell (craigdo@ee.washington.edu) - Craig Dowell (craigdo@ee.washington.edu) - Tom Henderson (tomhend@u.washington.edu) - Mathieu Lacage (mathieu.lacage@sophia.inria.fr) -+Emmanuelle Laprise (emmmanuelle.laprise@bluekazoo.ca) - George F. Riley (riley@ece.gatech.edu) -diff -r 1d32949ae397 -r 2cc09d5a04c4 RELEASE_NOTES ---- a/RELEASE_NOTES Mon Aug 13 23:40:51 2007 -0700 -+++ b/RELEASE_NOTES Mon Aug 20 13:40:15 2007 -0700 -@@ -3,12 +3,16 @@ - - This file contains ns-3 release notes (most recent releases first). - --Release 3.0.5 (2007/08/XX) -+Release 3.0.5 (2007/08/15) - ======================== - -- - Add CSMA/CD model (Emmanuelle Laprise) -- - Modularize ipv4 routing support (Gustavo Carneiro) -- - Add mobility framework and basic mobility models -+ - Refactoring to support win32-based unix environments (Cygwin, mingw) -+ - "Packet socket" for allowing applications to access NetDevices directly -+ - Generalized, polymorphic Address class -+ - Add CSMA NetDevice model (from Emmanuelle Laprise) -+ - Modularize IPv4 routing support (from Gustavo Carneiro) -+ - Add mobility framework and basic mobility models -+ - Global unicast centralized routing - - Release 3.0.4 (2007/07/15) - ======================== -diff -r 1d32949ae397 -r 2cc09d5a04c4 VERSION ---- a/VERSION Mon Aug 13 23:40:51 2007 -0700 -+++ b/VERSION Mon Aug 20 13:40:15 2007 -0700 -@@ -1,1 +1,1 @@ 3.0.4 --3.0.4 -+3.0.5 -diff -r 1d32949ae397 -r 2cc09d5a04c4 doc/release_steps.txt ---- a/doc/release_steps.txt Mon Aug 13 23:40:51 2007 -0700 -+++ b/doc/release_steps.txt Mon Aug 20 13:40:15 2007 -0700 -@@ -5,23 +5,20 @@ 1. prepare the source files - - revise and check in RELEASE_NOTES - - update and check in VERSION to the latest release number - 2. make a new "architecture.pdf" document and place it in the doc/ directory --3. add current version of waf script from subversion: -- - svn checkout http://waf.googlecode.com/svn/tags/ns3/ waf -- - build waf script and put it into top of ns-3-dev --4. cd ns-3-dev; ./waf configure; ./waf dist --5. test tarball on release platforms (run-tests and simple-p2p) --6. tag ns-3-dev with "release ns-3.0.X" -+3. cd ns-3-dev; ./waf configure; ./waf dist -+4. test tarball on release platforms (waf check and maybe some other scripts) -+5. tag ns-3-dev with "release ns-3.0.X" - - hg tag "release ns-3.0.x" - - hg push --7. clone the tagged ns-3-dev and place it on the repository -+6. clone the tagged ns-3-dev and place it on the repository - - ssh code.nsnam.org; sudo; su code; - - cp -r /home/code/repos/ns-3-dev /home/code/repos/ns-3.0.x - - cd /home/code/repos/ns-3.0.x/.hg and edit the hgrc appropriately --8. upload "ns-3.0.x.tar.bz2" to the releases/ directory on the server --9. update web page -+7. upload "ns-3.0.x.tar.bz2" to the releases/ directory on the server -+8. update web page - - add link to news.html - - update download.html - - update roadmap.html - - build and update Doxygen directory on the server - - update and upload software architecture document (PDF, HTML) --10. announce to ns-developers, with summary of release notes -+9. announce to ns-developers, with summary of release notes -diff -r 1d32949ae397 -r 2cc09d5a04c4 src/devices/csma/csma-net-device.h ---- a/src/devices/csma/csma-net-device.h Mon Aug 13 23:40:51 2007 -0700 -+++ b/src/devices/csma/csma-net-device.h Mon Aug 20 13:40:15 2007 -0700 -@@ -99,8 +99,23 @@ enum CsmaEncapsulationMode { - * - * \param node the Node to which this device is connected. - * \param addr The source MAC address of the net device. -+ * \param pktType the type of encapsulation - */ - CsmaNetDevice (Ptr node, Eui48Address addr, CsmaEncapsulationMode pktType); -+ -+ /** -+ * Construct a CsmaNetDevice -+ * -+ * This is the constructor for the CsmaNetDevice. It takes as a -+ * parameter the Node to which this device is connected. Ownership of the -+ * Node pointer is not implied and the node must not be deleted. -+ * -+ * \param node the Node to which this device is connected. -+ * \param addr The source MAC address of the net device. -+ * \param pktType the type of encapsulation -+ * \param sendEnable whether this device is able to send -+ * \param receiveEnable whether this device is able to receive -+ */ - CsmaNetDevice (Ptr node, Eui48Address addr, - CsmaEncapsulationMode pktType, - bool sendEnable, bool receiveEnable); -diff -r 1d32949ae397 -r 2cc09d5a04c4 src/devices/point-to-point/point-to-point-net-device.h ---- a/src/devices/point-to-point/point-to-point-net-device.h Mon Aug 13 23:40:51 2007 -0700 -+++ b/src/devices/point-to-point/point-to-point-net-device.h Mon Aug 20 13:40:15 2007 -0700 -@@ -175,7 +175,6 @@ protected: - virtual Ptr DoGetChannel(void) const; - /** - * Set a new default data rate -- * @param Data rate to set for new default - */ - static void SetDefaultRate(const DataRate&); - -diff -r 1d32949ae397 -r 2cc09d5a04c4 src/internet-node/ascii-trace.cc ---- a/src/internet-node/ascii-trace.cc Mon Aug 13 23:40:51 2007 -0700 -+++ b/src/internet-node/ascii-trace.cc Mon Aug 20 13:40:15 2007 -0700 -@@ -25,6 +25,7 @@ - #include "ns3/simulator.h" - #include "ns3/node.h" - #include "ns3/packet.h" -+#include "ns3/queue.h" - - namespace ns3 { - -@@ -40,8 +41,12 @@ AsciiTrace::TraceAllQueues (void) - AsciiTrace::TraceAllQueues (void) - { - Packet::EnableMetadata (); -- TraceRoot::Connect ("/nodes/*/devices/*/queue/*", -- MakeCallback (&AsciiTrace::LogDevQueue, this)); -+ TraceRoot::Connect ("/nodes/*/devices/*/queue/enqueue", -+ MakeCallback (&AsciiTrace::LogDevQueueEnqueue, this)); -+ TraceRoot::Connect ("/nodes/*/devices/*/queue/dequeue", -+ MakeCallback (&AsciiTrace::LogDevQueueDequeue, this)); -+ TraceRoot::Connect ("/nodes/*/devices/*/queue/drop", -+ MakeCallback (&AsciiTrace::LogDevQueueDrop, this)); - } - void - AsciiTrace::TraceAllNetDeviceRx (void) -@@ -52,8 +57,34 @@ AsciiTrace::TraceAllNetDeviceRx (void) - } - - void --AsciiTrace::LogDevQueue (TraceContext const &context, Packet const &packet) -+AsciiTrace::LogDevQueueEnqueue (TraceContext const &context, -+ Packet const &packet) - { -+ m_os << "+ "; -+ m_os << Simulator::Now ().GetSeconds () << " "; -+ context.Print (m_os); -+ m_os << " pkt-uid=" << packet.GetUid () << " "; -+ packet.Print (m_os); -+ m_os << std::endl; -+} -+ -+void -+AsciiTrace::LogDevQueueDequeue (TraceContext const &context, -+ Packet const &packet) -+{ -+ m_os << "- "; -+ m_os << Simulator::Now ().GetSeconds () << " "; -+ context.Print (m_os); -+ m_os << " pkt-uid=" << packet.GetUid () << " "; -+ packet.Print (m_os); -+ m_os << std::endl; -+} -+ -+void -+AsciiTrace::LogDevQueueDrop (TraceContext const &context, -+ Packet const &packet) -+{ -+ m_os << "d "; - m_os << Simulator::Now ().GetSeconds () << " "; - context.Print (m_os); - m_os << " pkt-uid=" << packet.GetUid () << " "; -@@ -63,7 +94,7 @@ void - void - AsciiTrace::LogDevRx (TraceContext const &context, Packet &p) - { -- m_os << Simulator::Now ().GetSeconds () << " "; -+ m_os << "r " << Simulator::Now ().GetSeconds () << " "; - context.Print (m_os); - m_os << " pkt-uid=" << p.GetUid () << " "; - p.Print (m_os); -diff -r 1d32949ae397 -r 2cc09d5a04c4 src/internet-node/ascii-trace.h ---- a/src/internet-node/ascii-trace.h Mon Aug 13 23:40:51 2007 -0700 -+++ b/src/internet-node/ascii-trace.h Mon Aug 20 13:40:15 2007 -0700 -@@ -37,7 +37,9 @@ public: - void TraceAllQueues (void); - void TraceAllNetDeviceRx (void); - private: -- void LogDevQueue (TraceContext const &context, const Packet &p); -+ void LogDevQueueEnqueue (TraceContext const &context, const Packet &p); -+ void LogDevQueueDequeue (TraceContext const &context, const Packet &p); -+ void LogDevQueueDrop (TraceContext const &context, const Packet &p); - void LogDevRx (TraceContext const &context, Packet &p); - std::ofstream m_os; - }; -diff -r 1d32949ae397 -r 2cc09d5a04c4 src/node/socket.h ---- a/src/node/socket.h Mon Aug 13 23:40:51 2007 -0700 -+++ b/src/node/socket.h Mon Aug 20 13:40:15 2007 -0700 -@@ -170,7 +170,6 @@ public: - /** - * \brief Send data (or dummy data) to the remote host - * \param p packet to send -- * \param dataSent Data sent callback. - * \returns -1 in case of error or the number of bytes copied in the - * internal buffer and accepted for transmission. - */ -@@ -180,7 +179,6 @@ public: - * \brief Send data to a specified peer. - * \param address IP Address of remote host - * \param p packet to send -- * \param dataSent Data sent callback. - * \returns -1 in case of error or the number of bytes copied in the - * internal buffer and accepted for transmission. - */ -diff -r 1d32949ae397 -r 2cc09d5a04c4 src/routing/global-routing/global-route-manager-impl.cc ---- a/src/routing/global-routing/global-route-manager-impl.cc Mon Aug 13 23:40:51 2007 -0700 -+++ b/src/routing/global-routing/global-route-manager-impl.cc Mon Aug 20 13:40:15 2007 -0700 -@@ -1586,6 +1586,7 @@ GlobalRouteManagerImplTest::RunTests (vo - 1); - - GlobalRoutingLSA* lsa0 = new GlobalRoutingLSA (); -+ lsa0->SetLSType (GlobalRoutingLSA::RouterLSA); - lsa0->SetLinkStateId ("0.0.0.0"); - lsa0->SetAdvertisingRouter ("0.0.0.0"); - lsa0->AddLinkRecord (lr0); -@@ -1605,6 +1606,7 @@ GlobalRouteManagerImplTest::RunTests (vo - 1); - - GlobalRoutingLSA* lsa1 = new GlobalRoutingLSA (); -+ lsa1->SetLSType (GlobalRoutingLSA::RouterLSA); - lsa1->SetLinkStateId ("0.0.0.1"); - lsa1->SetAdvertisingRouter ("0.0.0.1"); - lsa1->AddLinkRecord (lr2); -@@ -1648,6 +1650,7 @@ GlobalRouteManagerImplTest::RunTests (vo - 1); - - GlobalRoutingLSA* lsa2 = new GlobalRoutingLSA (); -+ lsa2->SetLSType (GlobalRoutingLSA::RouterLSA); - lsa2->SetLinkStateId ("0.0.0.2"); - lsa2->SetAdvertisingRouter ("0.0.0.2"); - lsa2->AddLinkRecord (lr4); -@@ -1671,6 +1674,7 @@ GlobalRouteManagerImplTest::RunTests (vo - 1); - - GlobalRoutingLSA* lsa3 = new GlobalRoutingLSA (); -+ lsa3->SetLSType (GlobalRoutingLSA::RouterLSA); - lsa3->SetLinkStateId ("0.0.0.3"); - lsa3->SetAdvertisingRouter ("0.0.0.3"); - lsa3->AddLinkRecord (lr10); -diff -r 1d32949ae397 -r 2cc09d5a04c4 src/routing/global-routing/global-router-interface.h ---- a/src/routing/global-routing/global-router-interface.h Mon Aug 13 23:40:51 2007 -0700 -+++ b/src/routing/global-routing/global-router-interface.h Mon Aug 20 13:40:15 2007 -0700 -@@ -431,7 +431,7 @@ public: - /** - * @brief Add an attached router to the list in the NetworkLSA - * -- * @param address The Ipv4Address of the interface on the network link -+ * @param addr The Ipv4Address of the interface on the network link - * @returns The number of addresses in the list. - */ - uint32_t AddAttachedRouter (Ipv4Address addr); - -changeset: 1311:4743aef86605 -parent: 1299:2cc09d5a04c4 -parent: 1310:394c16278532 -user: Craig Dowell -date: Fri Aug 24 13:29:51 2007 -0700 -summary: merge with trunk - -diff -r 2cc09d5a04c4 -r 4743aef86605 SConstruct ---- a/SConstruct Mon Aug 20 13:40:15 2007 -0700 -+++ /dev/null Thu Jan 01 00:00:00 1970 +0000 -@@ -1,521 +0,0 @@ --## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- -- --import os.path --import build -- --version_file = open ('VERSION', 'r') --version = version_file.readline () --version_file.close () --version = version.strip () -- --ns3 = build.Ns3() --ns3.build_dir = 'build-dir' --ns3.version = version --ns3.name = 'ns3' --ns3.distname = 'ns' --ns3.doxygen_config = os.path.join('doc', 'doxygen.conf') --ns3.add_extra_dist(os.path.join('doc', 'main.txt')) --ns3.add_extra_dist ('doc/architecture.pdf') --ns3.add_extra_dist ('doc/contributing.txt') --ns3.add_extra_dist ('doc/build.txt') --ns3.add_extra_dist ('doc/codingstd.txt') --ns3.add_extra_dist ('doc/mercurial.txt') --ns3.add_extra_dist ('README') --ns3.add_extra_dist ('RELEASE_NOTES') --ns3.add_extra_dist ('AUTHORS') --ns3.add_extra_dist ('VERSION') -- --ns3.add_extra_dist('doc/build-waf.txt') --ns3.add_extra_dist('ns3/_placeholder_') --for wscript in [ -- "src/core/wscript", -- "src/node/wscript", -- "src/devices/p2p/wscript", -- "src/common/wscript", -- "src/applications/wscript", -- "src/simulator/wscript", -- "src/internet-node/wscript", -- "src/wscript", -- "utils/wscript", -- "samples/wscript", -- "examples/wscript", -- "wscript", -- ]: -- ns3.add_extra_dist(wscript) --ns3.add_extra_dist('waf') --ns3.add_extra_dist('waf.bat') -- --# --# The Core module --# --core = build.Ns3Module('core', 'src/core') --ns3.add(core) --core.add_sources([ -- 'callback-test.cc', -- 'debug.cc', -- 'assert.cc', -- 'ptr.cc', -- 'object.cc', -- 'test.cc', -- 'random-variable.cc', -- 'rng-stream.cc', -- 'uid-manager.cc', -- 'default-value.cc', -- 'command-line.cc', -- 'type-name.cc', -- 'component-manager.cc', -- ]) --env = Environment() --if env['PLATFORM'] == 'posix' or env['PLATFORM'] == 'darwin' or env['PLATFORM'] == 'cygwin': -- core.add_external_dep('pthread') -- core.add_sources([ -- 'unix-system-wall-clock-ms.cc', -- ]) --elif env['PLATFORM'] == 'win32': -- core.add_sources([ -- 'win32-system-wall-clock-ms.cc', -- ]) --core.add_headers ([ -- 'uid-manager.h', -- 'singleton.h', --]) --core.add_inst_headers([ -- 'system-wall-clock-ms.h', -- 'empty.h', -- 'callback.h', -- 'ptr.h', -- 'object.h', -- 'debug.h', -- 'assert.h', -- 'fatal-error.h', -- 'test.h', -- 'random-variable.h', -- 'rng-stream.h', -- 'default-value.h', -- 'command-line.h', -- 'type-name.h', -- 'component-manager.h', -- ]) -- --def config_core (env, config): -- retval = [] -- # XXX This check is primitive but it should be -- # good enough for now. -- if config.CheckCHeader ('stdlib.h') == 1: -- retval.append ('#define HAVE_STDLIB_H 1') -- retval.append ('#define HAVE_GETENV 1') -- else: -- retval.append ('#undef HAVE_STDLIB_H') -- retval.append ('#undef HAVE_GETENV') -- return retval --core.add_config (config_core) -- --# --# The Simulator module --# --simu = build.Ns3Module('simulator', 'src/simulator') --ns3.add(simu) --simu.add_dep('core') --simu.add_external_dep('m') --simu.add_sources([ -- 'high-precision.cc', -- 'time.cc', -- 'event-id.cc', -- 'scheduler.cc', -- 'scheduler-factory.cc', -- 'scheduler-list.cc', -- 'scheduler-heap.cc', -- 'scheduler-map.cc', -- 'event-impl.cc', -- 'simulator.cc', -- ]) --simu.add_headers([ -- 'scheduler-heap.h', -- 'scheduler-map.h', -- 'scheduler-list.h' -- ]) --simu.add_inst_headers([ -- 'high-precision.h', -- 'nstime.h', -- 'event-id.h', -- 'event-impl.h', -- 'simulator.h', -- 'scheduler.h', -- 'scheduler-factory.h', -- 'simulation-singleton.h', -- ]) --high_precision_as_double = ARGUMENTS.get('high-precision-as-double', 'n') --if high_precision_as_double == 'y': -- simu.add_inst_header ('high-precision-double.h') -- simu.add_source ('high-precision-double.cc') --else: -- simu.add_inst_headers ([ -- 'high-precision-128.h', -- 'cairo-wideint-private.h' -- ]) -- simu.add_sources ([ -- 'high-precision-128.cc', -- 'cairo-wideint.c', -- ]) -- --def config_simulator (env, config): -- retval = [] -- high_precision_as_double = ARGUMENTS.get('high-precision-as-double', 'n') -- if high_precision_as_double == 'y': -- retval.append ('#define USE_HIGH_PRECISION_DOUBLE 1') -- else: -- retval.append ('#undef USE_HIGH_PRECISION_DOUBLE') -- if config.CheckCHeader ('stdint.h') == 1: -- retval.append ('#define HAVE_STDINT_H 1') -- elif config.CheckCHeader ('inttypes.h') == 1: -- retval.append ('#define HAVE_INTTYPES_H 1') -- elif config.CheckCHeader ('sys/inttypes.h') == 1: -- retval.append ('#define HAVE_SYS_INT_TYPES_H 1') -- return retval --simu.add_config (config_simulator) -- --# --# The Common module --# --common = build.Ns3Module('common', 'src/common') --common.add_deps(['core', 'simulator']) --ns3.add(common) --common.add_sources([ -- 'buffer.cc', -- 'chunk.cc', -- 'header.cc', -- 'trailer.cc', -- 'packet-printer.cc', -- 'packet-metadata.cc', -- 'packet.cc', -- 'tags.cc', -- 'pcap-writer.cc', -- 'variable-tracer-test.cc', -- 'trace-context.cc', -- 'trace-resolver.cc', -- 'callback-trace-source.cc', -- 'empty-trace-resolver.cc', -- 'composite-trace-resolver.cc', -- 'trace-root.cc', -- 'data-rate.cc', -- ]) --common.add_headers ([ -- ]) --common.add_inst_headers([ -- 'buffer.h', -- 'chunk.h', -- 'header.h', -- 'trailer.h', -- 'tags.h', -- 'packet.h', -- 'packet-printer.h', -- 'packet-metadata.h', -- 'uv-trace-source.h', -- 'sv-trace-source.h', -- 'fv-trace-source.h', -- 'pcap-writer.h', -- 'callback-trace-source.h', -- 'trace-context.h', -- 'trace-resolver.h', -- 'empty-trace-resolver.h', -- 'composite-trace-resolver.h', -- 'array-trace-resolver.h', -- 'trace-root.h', -- 'terminal-trace-resolver.h', -- 'data-rate.h', -- ]) -- --# --# The Node module --# --node = build.Ns3Module ('node', 'src/node') --ns3.add (node) --node.add_deps (['core', 'common', 'simulator']) --node.add_sources ([ -- 'node.cc', -- 'ipv4-address.cc', -- 'net-device.cc', -- 'mac-address.cc', -- 'llc-snap-header.cc', -- 'ipv4-route.cc', -- 'queue.cc', -- 'drop-tail-queue.cc', -- 'channel.cc', -- 'node-list.cc', -- 'socket.cc', -- 'socket-factory.cc', -- 'udp.cc', -- 'ipv4.cc', -- 'application.cc', -- ]) --node.add_inst_headers ([ -- 'node.h', -- 'ipv4-address.h', -- 'net-device.h', -- 'mac-address.h', -- 'ipv4-route.h', -- 'queue.h', -- 'drop-tail-queue.h', -- 'llc-snap-header.h', -- 'channel.h', -- 'node-list.h', -- 'socket.h', -- 'socket-factory.h', -- 'udp.h', -- 'ipv4.h', -- 'application.h', -- ]) -- --# --# The Applications module --# --applications = build.Ns3Module ('applications', 'src/applications') --ns3.add (applications) --applications.add_deps (['node']) --applications.add_sources ([ -- 'onoff-application.cc', --]) --applications.add_inst_headers ([ -- 'onoff-application.h', --]) -- --# --# The Internet Node module --# --inode = build.Ns3Module ('internet-node', 'src/internet-node') --ns3.add (inode) --inode.add_deps (['node', 'routing']) --inode.add_sources ([ -- 'internet-node.cc', -- 'l3-demux.cc', -- 'l3-protocol.cc', -- 'ipv4-l4-demux.cc', -- 'ipv4-l4-protocol.cc', -- 'ipv4-header.cc', -- 'udp-header.cc', -- 'ipv4-checksum.cc', -- 'ipv4-interface.cc', -- 'ipv4-l3-protocol.cc', -- 'ipv4-end-point.cc', -- 'udp-l4-protocol.cc', -- 'arp-header.cc', -- 'arp-cache.cc', -- 'arp-ipv4-interface.cc', -- 'arp-l3-protocol.cc', -- 'ipv4-loopback-interface.cc', -- 'header-utils.cc', -- 'udp-socket.cc', -- 'ipv4-end-point-demux.cc', -- 'arp-private.cc', -- 'ipv4-impl.cc', -- 'ipv4-private.cc', -- 'ascii-trace.cc', -- 'pcap-trace.cc', -- 'udp-impl.cc', --]) --inode.add_headers ([ -- 'ipv4-checksum.h', -- 'arp-header.h', -- 'arp-cache.h', -- 'arp-l3-protocol.h', -- 'ipv4-loopback-interface.h', -- 'l3-demux.h', -- 'header-utils.h', -- 'arp-ipv4-interface.h', -- 'udp-socket.h', -- 'udp-l4-protocol.h', -- 'arp-private.h', -- 'ipv4-impl.h', -- 'ipv4-private.h', -- 'ipv4-l3-protocol.h', -- 'l3-protocol.h', -- 'ipv4-l4-protocol.h', -- 'ipv4-l4-demux.h', -- 'ipv4-end-point-demux.h', -- 'ipv4-end-point.h', -- 'ipv4-header.h', -- 'ipv4-interface.h', -- 'udp-header.h', -- 'sgi-hashmap.h', -- 'udp-impl.h', --]) --inode.add_inst_headers ([ -- 'internet-node.h', -- 'ascii-trace.h', -- 'pcap-trace.h', -- 'ipv4-header.h', -- 'udp-header.h', --]) -- --# --# The Point-to-point module --# --p2p = build.Ns3Module ('p2p', 'src/devices/p2p') --ns3.add (p2p) --p2p.add_deps (['node']) --p2p.add_sources ([ -- 'p2p-net-device.cc', -- 'p2p-channel.cc', -- 'p2p-topology.cc', -- ]) --p2p.add_inst_headers ([ -- 'p2p-net-device.h', -- 'p2p-channel.h', -- 'p2p-topology.h', -- ]) -- --# --# The Routing module --# --routing = build.Ns3Module('routing', 'src/routing') --routing.add_deps(['core', 'node']) --ns3.add(routing) --routing.add_sources([ -- 'routing-environment.cc', -- 'static-router.cc', -- 'static-route-manager.cc', -- 'static-route-manager-impl.cc', -- 'candidate-queue.cc', -- ]) --routing.add_headers ([ -- 'candidate-queue.h', -- 'static-route-manager-impl.h', -- ]) --routing.add_inst_headers([ -- 'routing-environment.h', -- 'static-router.h', -- 'static-route-manager.h', -- ]) -- --# utils --run_tests = build.Ns3Module('run-tests', 'utils') --ns3.add(run_tests) --run_tests.set_executable() --run_tests.add_deps(['core', 'simulator', 'common', 'routing']) --run_tests.add_source('run-tests.cc') -- --bench_object = build.Ns3Module('bench-object', 'utils') --ns3.add(bench_object) --bench_object.set_executable() --bench_object.add_deps(['core']) --bench_object.add_source('bench-object.cc') -- --bench_packets = build.Ns3Module('bench-packets', 'utils') --ns3.add(bench_packets) --bench_packets.set_executable() --bench_packets.add_deps (['core', 'common']) --bench_packets.add_source('bench-packets.cc') -- --bench_simu = build.Ns3Module('bench-simulator', 'utils') --ns3.add(bench_simu) --bench_simu.set_executable() --bench_simu.add_dep('simulator') --bench_simu.add_source('bench-simulator.cc') -- --replay_simu = build.Ns3Module('replay-simulation', 'utils') --ns3.add(replay_simu) --replay_simu.set_executable() --replay_simu.add_dep('simulator') --replay_simu.add_source('replay-simulation.cc') -- -- --# samples --sample_debug = build.Ns3Module('sample-debug', 'samples') --sample_debug.set_executable() --ns3.add(sample_debug) --sample_debug.add_dep('core') --sample_debug.add_source('main-debug.cc') --sample_debug.add_source('main-debug-other.cc') -- --sample_packet_printer = build.Ns3Module('sample-packet-printer', 'samples') --sample_packet_printer.set_executable() --ns3.add(sample_packet_printer) --sample_packet_printer.add_deps (['common', 'internet-node']) --sample_packet_printer.add_source('main-packet-printer.cc') -- --sample_callback = build.Ns3Module('sample-callback', 'samples') --sample_callback.set_executable() --ns3.add(sample_callback) --sample_callback.add_dep('core') --sample_callback.add_source('main-callback.cc') -- --sample_ptr = build.Ns3Module('sample-ptr', 'samples') --sample_ptr.set_executable() --ns3.add(sample_ptr) --sample_ptr.add_dep('core') --sample_ptr.add_source('main-ptr.cc') -- --sample_trace = build.Ns3Module('sample-trace', 'samples') --#ns3.add(sample_trace) --sample_trace.add_dep('common') --sample_trace.set_executable() --sample_trace.add_source('main-trace.cc') -- --sample_query_interface = build.Ns3Module('sample-query-interface', 'samples') --ns3.add(sample_query_interface) --sample_query_interface.add_dep('common') --sample_query_interface.set_executable() --sample_query_interface.add_source('main-query-interface.cc') -- --sample_simu = build.Ns3Module('sample-simulator', 'samples') --ns3.add(sample_simu) --sample_simu.set_executable() --sample_simu.add_dep('simulator') --sample_simu.add_source('main-simulator.cc') -- --sample_packet = build.Ns3Module('sample-packet', 'samples') --ns3.add(sample_packet) --sample_packet.set_executable() --sample_packet.add_dep('common') --sample_packet.add_source('main-packet.cc') -- --sample_test = build.Ns3Module('sample-test', 'samples') --sample_test.set_executable() --ns3.add(sample_test) --sample_test.add_dep('core') --sample_test.add_source('main-test.cc') -- --sample_simple = build.Ns3Module('sample-simple', 'samples') --sample_simple.set_executable() --ns3.add(sample_simple) --sample_simple.add_deps(['core', 'simulator', 'node', 'internet-node', 'routing']) --sample_simple.add_source('main-simple.cc') -- --sample_sp2p = build.Ns3Module('sample-simple-p2p', 'samples') --sample_sp2p.set_executable() --#n3.add(sample_sp2p) --sample_sp2p.add_deps(['core', 'simulator', 'node', 'internet-node', 'p2p']) --sample_sp2p.add_source('main-simple-p2p.cc') -- --sample_default_value = build.Ns3Module('sample-default-value', 'samples') --sample_default_value.set_executable() --ns3.add(sample_default_value) --sample_default_value.add_deps(['core', 'simulator', 'node', 'p2p']) --sample_default_value.add_source('main-default-value.cc') -- --sample_object = build.Ns3Module('sample-object', 'samples') --sample_object.set_executable() --ns3.add(sample_object) --sample_object.add_deps(['core']) --sample_object.add_source('main-object.cc') -- --sample_component_manager = build.Ns3Module('sample-component-manager', 'samples') --sample_component_manager.set_executable() --ns3.add(sample_component_manager) --sample_component_manager.add_deps(['core']) --sample_component_manager.add_source('main-component-manager.cc') -- --# examples --example_simple_p2p = build.Ns3Module('simple-p2p', 'examples') --example_simple_p2p.set_executable() --ns3.add(example_simple_p2p) --example_simple_p2p.add_deps(['core', 'simulator', 'node', 'p2p', 'internet-node', 'applications', 'routing']) --example_simple_p2p.add_source('simple-p2p.cc') -- --example_static_routing = build.Ns3Module('simple-static-routing', 'examples') --example_static_routing.set_executable() --ns3.add(example_static_routing) --example_static_routing.add_deps(['core', 'simulator', 'node', 'p2p', 'internet-node', 'applications', 'routing']) --example_static_routing.add_source('simple-static-routing.cc') -- --ns3.generate_dependencies() -diff -r 2cc09d5a04c4 -r 4743aef86605 examples/simple-point-to-point.cc ---- a/examples/simple-point-to-point.cc Mon Aug 20 13:40:15 2007 -0700 -+++ b/examples/simple-point-to-point.cc Fri Aug 24 13:29:51 2007 -0700 -@@ -71,6 +71,7 @@ main (int argc, char *argv[]) - - // Users may find it convenient to turn on explicit debugging - // for selected modules; the below lines suggest how to do this -+ // remember to add #include "ns3/debug.h" before enabling these - #if 0 - DebugComponentEnable("Me"); - DebugComponentEnable("Object"); -diff -r 2cc09d5a04c4 -r 4743aef86605 src/applications/onoff-application.h ---- a/src/applications/onoff-application.h Mon Aug 20 13:40:15 2007 -0700 -+++ b/src/applications/onoff-application.h Fri Aug 24 13:29:51 2007 -0700 -@@ -28,13 +28,13 @@ - #include "ns3/application.h" - #include "ns3/event-id.h" - #include "ns3/ptr.h" -+#include "ns3/data-rate.h" - - namespace ns3 { - - class Address; - class RandomVariable; - class Socket; --class DataRate; - - /** - * \brief Generate traffic to a single destination according to an -diff -r 2cc09d5a04c4 -r 4743aef86605 src/mobility/mobility-model.cc ---- a/src/mobility/mobility-model.cc Mon Aug 20 13:40:15 2007 -0700 -+++ b/src/mobility/mobility-model.cc Fri Aug 24 13:29:51 2007 -0700 -@@ -52,9 +52,9 @@ MobilityModel::Set (const Position &posi - } - - double --MobilityModel::GetDistanceFrom (const MobilityModel &other) const -+MobilityModel::GetDistanceFrom (Ptr other) const - { -- Position oPosition = other.DoGet (); -+ Position oPosition = other->DoGet (); - Position position = DoGet (); - return CalculateDistance (position, oPosition); - } -diff -r 2cc09d5a04c4 -r 4743aef86605 src/mobility/mobility-model.h ---- a/src/mobility/mobility-model.h Mon Aug 20 13:40:15 2007 -0700 -+++ b/src/mobility/mobility-model.h Fri Aug 24 13:29:51 2007 -0700 -@@ -57,7 +57,7 @@ public: - * \param position a reference to another mobility model - * \returns the distance between the two objects. Unit is meters. - */ -- double GetDistanceFrom (const MobilityModel &position) const; -+ double GetDistanceFrom (Ptr position) const; - protected: - /** - * Must be invoked by subclasses when the course of the -diff -r 2cc09d5a04c4 -r 4743aef86605 src/node/inet-socket-address.cc ---- a/src/node/inet-socket-address.cc Mon Aug 20 13:40:15 2007 -0700 -+++ b/src/node/inet-socket-address.cc Fri Aug 24 13:29:51 2007 -0700 -@@ -1,3 +1,24 @@ -+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ -+/* -+ * Copyright (c) 2005 INRIA -+ * All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation; -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * Author: Mathieu Lacage -+ */ -+ - #include "inet-socket-address.h" - #include "ns3/assert.h" - -diff -r 2cc09d5a04c4 -r 4743aef86605 src/node/inet-socket-address.h ---- a/src/node/inet-socket-address.h Mon Aug 20 13:40:15 2007 -0700 -+++ b/src/node/inet-socket-address.h Fri Aug 24 13:29:51 2007 -0700 -@@ -1,5 +1,26 @@ --#ifndef IPV4_TRANSPORT_ADDRESS_H --#define IPV4_TRANSPORT_ADDRESS_H -+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ -+/* -+ * Copyright (c) 2005 INRIA -+ * All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation; -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * Author: Mathieu Lacage -+ */ -+ -+#ifndef INET_SOCKET_ADDRESS_H -+#define INET_SOCKET_ADDRESS_H - - #include "address.h" - #include "ipv4-address.h" -@@ -93,4 +114,4 @@ private: - } // namespace ns3 - - --#endif /* IPV4_TRANSPORT_ADDRESS_H */ -+#endif /* INET_SOCKET_ADDRESS_H */ -diff -r 2cc09d5a04c4 -r 4743aef86605 src/node/net-device.cc ---- a/src/node/net-device.cc Mon Aug 20 13:40:15 2007 -0700 -+++ b/src/node/net-device.cc Fri Aug 24 13:29:51 2007 -0700 -@@ -197,7 +197,7 @@ NetDevice::GetChannel (void) const - - // Receive packets from below - bool --NetDevice::ForwardUp(const Packet& p, uint32_t param, const Address &from) -+NetDevice::ForwardUp(const Packet& p, uint16_t param, const Address &from) - { - bool retval = false; - -diff -r 2cc09d5a04c4 -r 4743aef86605 src/node/net-device.h ---- a/src/node/net-device.h Mon Aug 20 13:40:15 2007 -0700 -+++ b/src/node/net-device.h Fri Aug 24 13:29:51 2007 -0700 -@@ -251,7 +251,7 @@ public: - * forwards it to the higher layers by calling this method - * which is responsible for passing it up to the Rx callback. - */ -- bool ForwardUp (const Packet& p, uint32_t param, const Address &address); -+ bool ForwardUp (const Packet& p, uint16_t param, const Address &address); - - - /** -diff -r 2cc09d5a04c4 -r 4743aef86605 src/simulator/simulator.cc ---- a/src/simulator/simulator.cc Mon Aug 20 13:40:15 2007 -0700 -+++ b/src/simulator/simulator.cc Fri Aug 24 13:29:51 2007 -0700 -@@ -539,13 +539,14 @@ public: - public: - SimulatorTests (); - // only here for testing of Ptr<> -- void Ref (void); -- void Unref (void); -+ void Ref (void) const; -+ void Unref (void) const; - virtual ~SimulatorTests (); - virtual bool RunTests (void); - private: - uint64_t NowUs (); - bool RunOneTest (void); -+ void RunTestsConst (void) const; - void A (int a); - void B (int b); - void C (int c); -@@ -566,6 +567,24 @@ private: - void cbaz3 (const int &, const int &, const int &); - void cbaz4 (const int &, const int &, const int &, const int &); - void cbaz5 (const int &, const int &, const int &, const int &, const int &); -+ -+ void bar0c (void) const; -+ void bar1c (int) const; -+ void bar2c (int, int) const; -+ void bar3c (int, int, int) const; -+ void bar4c (int, int, int, int) const; -+ void bar5c (int, int, int, int, int) const; -+ void baz1c (int &) const; -+ void baz2c (int &, int &) const; -+ void baz3c (int &, int &, int &) const; -+ void baz4c (int &, int &, int &, int &) const; -+ void baz5c (int &, int &, int &, int &, int &) const; -+ void cbaz1c (const int &) const; -+ void cbaz2c (const int &, const int &) const; -+ void cbaz3c (const int &, const int &, const int &) const; -+ void cbaz4c (const int &, const int &, const int &, const int &) const; -+ void cbaz5c (const int &, const int &, const int &, const int &, const int &) const; -+ - void destroy (void); - - bool m_b; -@@ -583,10 +602,10 @@ SimulatorTests::~SimulatorTests () - SimulatorTests::~SimulatorTests () - {} - void --SimulatorTests::Ref (void) --{} --void --SimulatorTests::Unref (void) -+SimulatorTests::Ref (void) const -+{} -+void -+SimulatorTests::Unref (void) const - {} - uint64_t - SimulatorTests::NowUs (void) -@@ -687,6 +706,57 @@ SimulatorTests::cbaz4 (const int &, cons - {} - void - SimulatorTests::cbaz5 (const int &, const int &, const int &, const int &, const int &) -+{} -+ -+void -+SimulatorTests::bar0c (void) const -+{} -+void -+SimulatorTests::bar1c (int) const -+{} -+void -+SimulatorTests::bar2c (int, int) const -+{} -+void -+SimulatorTests::bar3c (int, int, int) const -+{} -+void -+SimulatorTests::bar4c (int, int, int, int) const -+{} -+void -+SimulatorTests::bar5c (int, int, int, int, int) const -+{} -+ -+void -+SimulatorTests::baz1c (int &) const -+{} -+void -+SimulatorTests::baz2c (int &, int &) const -+{} -+void -+SimulatorTests::baz3c (int &, int &, int &) const -+{} -+void -+SimulatorTests::baz4c (int &, int &, int &, int &) const -+{} -+void -+SimulatorTests::baz5c (int &, int &, int &, int &, int &) const -+{} -+ -+void -+SimulatorTests::cbaz1c (const int &) const -+{} -+void -+SimulatorTests::cbaz2c (const int &, const int &) const -+{} -+void -+SimulatorTests::cbaz3c (const int &, const int &, const int &) const -+{} -+void -+SimulatorTests::cbaz4c (const int &, const int &, const int &, const int &) const -+{} -+void -+SimulatorTests::cbaz5c (const int &, const int &, const int &, const int &, const int &) const - {} - - bool -@@ -723,6 +793,80 @@ SimulatorTests::RunOneTest (void) - } - return ok; - } -+void -+SimulatorTests::RunTestsConst (void) const -+{ -+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar0c, this); -+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar1c, this, 0); -+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar2c, this, 0, 0); -+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar3c, this, 0, 0, 0); -+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar4c, this, 0, 0, 0, 0); -+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar5c, this, 0, 0, 0, 0, 0); -+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar0c, Ptr (this)); -+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar1c, Ptr (this), 0); -+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar2c, Ptr (this), 0, 0); -+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar3c, Ptr (this), 0, 0, 0); -+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar4c, Ptr (this), 0, 0, 0, 0); -+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar5c, Ptr (this), 0, 0, 0, 0, 0); -+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::cbaz1c, this, 0); -+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::cbaz2c, this, 0, 0); -+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::cbaz3c, this, 0, 0, 0); -+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::cbaz4c, this, 0, 0, 0, 0); -+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::cbaz5c, this, 0, 0, 0, 0, 0); -+ Simulator::ScheduleNow (&SimulatorTests::bar0c, this); -+ Simulator::ScheduleNow (&SimulatorTests::bar1c, this, 0); -+ Simulator::ScheduleNow (&SimulatorTests::bar2c, this, 0, 0); -+ Simulator::ScheduleNow (&SimulatorTests::bar3c, this, 0, 0, 0); -+ Simulator::ScheduleNow (&SimulatorTests::bar4c, this, 0, 0, 0, 0); -+ Simulator::ScheduleNow (&SimulatorTests::bar5c, this, 0, 0, 0, 0, 0); -+ Simulator::ScheduleNow (&SimulatorTests::cbaz1c, this, 0); -+ Simulator::ScheduleNow (&SimulatorTests::cbaz2c, this, 0, 0); -+ Simulator::ScheduleNow (&SimulatorTests::cbaz3c, this, 0, 0, 0); -+ Simulator::ScheduleNow (&SimulatorTests::cbaz4c, this, 0, 0, 0, 0); -+ Simulator::ScheduleNow (&SimulatorTests::cbaz5c, this, 0, 0, 0, 0, 0); -+ Simulator::ScheduleNow (&SimulatorTests::bar0c, Ptr (this)); -+ Simulator::ScheduleNow (&SimulatorTests::bar1c, Ptr (this), 0); -+ Simulator::ScheduleNow (&SimulatorTests::bar2c, Ptr (this), 0, 0); -+ Simulator::ScheduleNow (&SimulatorTests::bar3c, Ptr (this), 0, 0, 0); -+ Simulator::ScheduleNow (&SimulatorTests::bar4c, Ptr (this), 0, 0, 0, 0); -+ Simulator::ScheduleNow (&SimulatorTests::bar5c, Ptr (this), 0, 0, 0, 0, 0); -+ Simulator::ScheduleDestroy (&SimulatorTests::bar0c, this); -+ Simulator::ScheduleDestroy (&SimulatorTests::bar1c, this, 0); -+ Simulator::ScheduleDestroy (&SimulatorTests::bar2c, this, 0, 0); -+ Simulator::ScheduleDestroy (&SimulatorTests::bar3c, this, 0, 0, 0); -+ Simulator::ScheduleDestroy (&SimulatorTests::bar4c, this, 0, 0, 0, 0); -+ Simulator::ScheduleDestroy (&SimulatorTests::bar5c, this, 0, 0, 0, 0, 0); -+ Simulator::ScheduleDestroy (&SimulatorTests::cbaz1c, this, 0); -+ Simulator::ScheduleDestroy (&SimulatorTests::cbaz2c, this, 0, 0); -+ Simulator::ScheduleDestroy (&SimulatorTests::cbaz3c, this, 0, 0, 0); -+ Simulator::ScheduleDestroy (&SimulatorTests::cbaz4c, this, 0, 0, 0, 0); -+ Simulator::ScheduleDestroy (&SimulatorTests::cbaz5c, this, 0, 0, 0, 0, 0); -+ Simulator::ScheduleDestroy (&SimulatorTests::bar0c, Ptr (this)); -+ Simulator::ScheduleDestroy (&SimulatorTests::bar1c, Ptr (this), 0); -+ Simulator::ScheduleDestroy (&SimulatorTests::bar2c, Ptr (this), 0, 0); -+ Simulator::ScheduleDestroy (&SimulatorTests::bar3c, Ptr (this), 0, 0, 0); -+ Simulator::ScheduleDestroy (&SimulatorTests::bar4c, Ptr (this), 0, 0, 0, 0); -+ Simulator::ScheduleDestroy (&SimulatorTests::bar5c, Ptr (this), 0, 0, 0, 0, 0); -+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::baz1c, this, 0); -+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::baz2c, this, 0, 0); -+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::baz3c, this, 0, 0, 0); -+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::baz4c, this, 0, 0, 0, 0); -+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::baz5c, this, 0, 0, 0, 0, 0); -+ Simulator::ScheduleNow (&SimulatorTests::baz1c, this, 0); -+ Simulator::ScheduleNow (&SimulatorTests::baz2c, this, 0, 0); -+ Simulator::ScheduleNow (&SimulatorTests::baz3c, this, 0, 0, 0); -+ Simulator::ScheduleNow (&SimulatorTests::baz4c, this, 0, 0, 0, 0); -+ Simulator::ScheduleNow (&SimulatorTests::baz5c, this, 0, 0, 0, 0, 0); -+ Simulator::ScheduleDestroy (&SimulatorTests::baz1c, this, 0); -+ Simulator::ScheduleDestroy (&SimulatorTests::baz2c, this, 0, 0); -+ Simulator::ScheduleDestroy (&SimulatorTests::baz3c, this, 0, 0, 0); -+ Simulator::ScheduleDestroy (&SimulatorTests::baz4c, this, 0, 0, 0, 0); -+ Simulator::ScheduleDestroy (&SimulatorTests::baz5c, this, 0, 0, 0, 0, 0); -+ -+ Simulator::Run (); -+ Simulator::Destroy (); -+} -+ - bool - SimulatorTests::RunTests (void) - { -@@ -870,6 +1014,8 @@ SimulatorTests::RunTests (void) - Simulator::ScheduleDestroy (&SimulatorTests::baz5, this, 0, 0, 0, 0, 0); - #endif - -+ RunTestsConst (); -+ - EventId nowId = Simulator::ScheduleNow (&foo0); - m_destroyId = Simulator::ScheduleDestroy (&SimulatorTests::destroy, this); - if (m_destroyId.IsExpired ()) -diff -r 2cc09d5a04c4 -r 4743aef86605 src/simulator/simulator.h ---- a/src/simulator/simulator.h Mon Aug 20 13:40:15 2007 -0700 -+++ b/src/simulator/simulator.h Fri Aug 24 13:29:51 2007 -0700 -@@ -163,8 +163,8 @@ public: - * @param obj the object on which to invoke the member method - * @returns an id for the scheduled event. - */ -- template -- static EventId Schedule (Time const &time, void (T::*mem_ptr) (void), OBJ obj); -+ template -+ static EventId Schedule (Time const &time, MEM mem_ptr, OBJ obj); - /** - * @param time the relative expiration time of the event. - * @param mem_ptr member method pointer to invoke -@@ -172,8 +172,8 @@ public: - * @param a1 the first argument to pass to the invoked method - * @returns an id for the scheduled event. - */ -- template -- static EventId Schedule (Time const &time, void (T::*mem_ptr) (U1), OBJ obj, T1 a1); -+ template -+ static EventId Schedule (Time const &time, MEM mem_ptr, OBJ obj, T1 a1); - /** - * @param time the relative expiration time of the event. - * @param mem_ptr member method pointer to invoke -@@ -182,8 +182,8 @@ public: - * @param a2 the second argument to pass to the invoked method - * @returns an id for the scheduled event. - */ -- template -- static EventId Schedule (Time const &time, void (T::*mem_ptr) (U1,U2), OBJ obj, T1 a1, T2 a2); -+ template -+ static EventId Schedule (Time const &time, MEM mem_ptr, OBJ obj, T1 a1, T2 a2); - /** - * @param time the relative expiration time of the event. - * @param mem_ptr member method pointer to invoke -@@ -193,10 +193,9 @@ public: - * @param a3 the third argument to pass to the invoked method - * @returns an id for the scheduled event. - */ -- template -- static EventId Schedule (Time const &time, void (T::*mem_ptr) (U1,U2,U3), OBJ obj, T1 a1, T2 a2, T3 a3); -+ static EventId Schedule (Time const &time, MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3); - /** - * @param time the relative expiration time of the event. - * @param mem_ptr member method pointer to invoke -@@ -207,10 +206,9 @@ public: - * @param a4 the fourth argument to pass to the invoked method - * @returns an id for the scheduled event. - */ -- template -- static EventId Schedule (Time const &time, void (T::*mem_ptr) (U1,U2,U3,U4), OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4); -+ static EventId Schedule (Time const &time, MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4); - /** - * @param time the relative expiration time of the event. - * @param mem_ptr member method pointer to invoke -@@ -222,10 +220,9 @@ public: - * @param a5 the fifth argument to pass to the invoked method - * @returns an id for the scheduled event. - */ -- template -- static EventId Schedule (Time const &time, void (T::*mem_ptr) (U1,U2,U3,U4,U5), OBJ obj, -+ static EventId Schedule (Time const &time, MEM mem_ptr, OBJ obj, - T1 a1, T2 a2, T3 a3, T4 a4, T5 a5); - /** - * @param time the relative expiration time of the event. -@@ -295,27 +292,25 @@ public: - * @param mem_ptr member method pointer to invoke - * @param obj the object on which to invoke the member method - */ -- template -- static EventId ScheduleNow (void (T::*mem_ptr) (void), OBJ obj); -- /** -- * @param mem_ptr member method pointer to invoke -- * @param obj the object on which to invoke the member method -- * @param a1 the first argument to pass to the invoked method -- */ -- template -+ static EventId ScheduleNow (MEM mem_ptr, OBJ obj); -+ /** -+ * @param mem_ptr member method pointer to invoke -+ * @param obj the object on which to invoke the member method -+ * @param a1 the first argument to pass to the invoked method -+ */ -+ template -- static EventId ScheduleNow (void (T::*mem_ptr) (U1), OBJ obj, T1 a1); -+ static EventId ScheduleNow (MEM mem_ptr, OBJ obj, T1 a1); - /** - * @param mem_ptr member method pointer to invoke - * @param obj the object on which to invoke the member method - * @param a1 the first argument to pass to the invoked method - * @param a2 the second argument to pass to the invoked method - */ -- template -- static EventId ScheduleNow (void (T::*mem_ptr) (U1,U2), OBJ obj, T1 a1, T2 a2); -+ static EventId ScheduleNow (MEM mem_ptr, OBJ obj, T1 a1, T2 a2); - /** - * @param mem_ptr member method pointer to invoke - * @param obj the object on which to invoke the member method -@@ -323,10 +318,9 @@ public: - * @param a2 the second argument to pass to the invoked method - * @param a3 the third argument to pass to the invoked method - */ -- template -- static EventId ScheduleNow (void (T::*mem_ptr) (U1,U2,U3), OBJ obj, T1 a1, T2 a2, T3 a3); -+ static EventId ScheduleNow (MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3); - /** - * @param mem_ptr member method pointer to invoke - * @param obj the object on which to invoke the member method -@@ -335,11 +329,10 @@ public: - * @param a3 the third argument to pass to the invoked method - * @param a4 the fourth argument to pass to the invoked method - */ -- template -- static EventId ScheduleNow (void (T::*mem_ptr) (U1,U2,U3,U4), OBJ obj, -- T1 a1, T2 a2, T3 a3, T4 a4); -+ static EventId ScheduleNow (MEM mem_ptr, OBJ obj, -+ T1 a1, T2 a2, T3 a3, T4 a4); - /** - * @param mem_ptr member method pointer to invoke - * @param obj the object on which to invoke the member method -@@ -349,11 +342,10 @@ public: - * @param a4 the fourth argument to pass to the invoked method - * @param a5 the fifth argument to pass to the invoked method - */ -- template -- static EventId ScheduleNow (void (T::*mem_ptr) (U1,U2,U3,U4,U5), OBJ obj, -- T1 a1, T2 a2, T3 a3, T4 a4, T5 a5); -+ static EventId ScheduleNow (MEM mem_ptr, OBJ obj, -+ T1 a1, T2 a2, T3 a3, T4 a4, T5 a5); - /** - * @param f the function to invoke - */ -@@ -414,27 +406,25 @@ public: - * @param mem_ptr member method pointer to invoke - * @param obj the object on which to invoke the member method - */ -- template -- static EventId ScheduleDestroy (void (T::*mem_ptr) (void), OBJ obj); -- /** -- * @param mem_ptr member method pointer to invoke -- * @param obj the object on which to invoke the member method -- * @param a1 the first argument to pass to the invoked method -- */ -- template -+ static EventId ScheduleDestroy (MEM mem_ptr, OBJ obj); -+ /** -+ * @param mem_ptr member method pointer to invoke -+ * @param obj the object on which to invoke the member method -+ * @param a1 the first argument to pass to the invoked method -+ */ -+ template -- static EventId ScheduleDestroy (void (T::*mem_ptr) (U1), OBJ obj, T1 a1); -+ static EventId ScheduleDestroy (MEM mem_ptr, OBJ obj, T1 a1); - /** - * @param mem_ptr member method pointer to invoke - * @param obj the object on which to invoke the member method - * @param a1 the first argument to pass to the invoked method - * @param a2 the second argument to pass to the invoked method - */ -- template -- static EventId ScheduleDestroy (void (T::*mem_ptr) (U1,U2), OBJ obj, T1 a1, T2 a2); -+ static EventId ScheduleDestroy (MEM mem_ptr, OBJ obj, T1 a1, T2 a2); - /** - * @param mem_ptr member method pointer to invoke - * @param obj the object on which to invoke the member method -@@ -442,10 +432,9 @@ public: - * @param a2 the second argument to pass to the invoked method - * @param a3 the third argument to pass to the invoked method - */ -- template -- static EventId ScheduleDestroy (void (T::*mem_ptr) (U1,U2,U3), OBJ obj, T1 a1, T2 a2, T3 a3); -+ static EventId ScheduleDestroy (MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3); - /** - * @param mem_ptr member method pointer to invoke - * @param obj the object on which to invoke the member method -@@ -454,11 +443,10 @@ public: - * @param a3 the third argument to pass to the invoked method - * @param a4 the fourth argument to pass to the invoked method - */ -- template -- static EventId ScheduleDestroy (void (T::*mem_ptr) (U1,U2,U3,U4), OBJ obj, -- T1 a1, T2 a2, T3 a3, T4 a4); -+ static EventId ScheduleDestroy (MEM mem_ptr, OBJ obj, -+ T1 a1, T2 a2, T3 a3, T4 a4); - /** - * @param mem_ptr member method pointer to invoke - * @param obj the object on which to invoke the member method -@@ -468,11 +456,10 @@ public: - * @param a4 the fourth argument to pass to the invoked method - * @param a5 the fifth argument to pass to the invoked method - */ -- template -- static EventId ScheduleDestroy (void (T::*mem_ptr) (U1,U2,U3,U4,U5), OBJ obj, -- T1 a1, T2 a2, T3 a3, T4 a4, T5 a5); -+ static EventId ScheduleDestroy (MEM mem_ptr, OBJ obj, -+ T1 a1, T2 a2, T3 a3, T4 a4, T5 a5); - /** - * @param f the function to invoke - */ -@@ -569,29 +556,24 @@ private: - Simulator (); - ~Simulator (); - -- template -- static Ptr MakeEvent (void (T::*mem_ptr) (void), OBJ obj); -- template -+ static Ptr MakeEvent (MEM mem_ptr, OBJ obj); -+ template -- static Ptr MakeEvent (void (T::*mem_ptr) (U1), OBJ obj, T1 a1); -- template MakeEvent (MEM mem_ptr, OBJ obj, T1 a1); -+ template -- static Ptr MakeEvent (void (T::*mem_ptr) (U1,U2), OBJ obj, T1 a1, T2 a2); -- template MakeEvent (MEM mem_ptr, OBJ obj, T1 a1, T2 a2); -+ template -- static Ptr MakeEvent (void (T::*mem_ptr) (U1,U2,U3), OBJ obj, T1 a1, T2 a2, T3 a3); -- template MakeEvent (MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3); -+ template -- static Ptr MakeEvent (void (T::*mem_ptr) (U1,U2,U3,U4), OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4); -- template MakeEvent (MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4); -+ template -- static Ptr MakeEvent (void (T::*mem_ptr) (U1,U2,U3,U4,U5), OBJ obj, -- T1 a1, T2 a2, T3 a3, T4 a4, T5 a5); -+ static Ptr MakeEvent (MEM mem_ptr, OBJ obj, -+ T1 a1, T2 a2, T3 a3, T4 a4, T5 a5); - static Ptr MakeEvent (void (*f) (void)); - template -@@ -649,14 +631,13 @@ struct EventMemberImplObjTraits - } - }; - --template --Ptr Simulator::MakeEvent (void (T::*mem_ptr) (void), OBJ obj) -+template -+Ptr Simulator::MakeEvent (MEM mem_ptr, OBJ obj) - { - // zero argument version - class EventMemberImpl0 : public EventImpl { - public: -- typedef void (T::*F)(void); -- EventMemberImpl0 (OBJ obj, F function) -+ EventMemberImpl0 (OBJ obj, MEM function) - : m_obj (obj), - m_function (function) - {} -@@ -666,22 +647,20 @@ Ptr Simulator::MakeEvent (voi - (EventMemberImplObjTraits::GetReference (m_obj).*m_function) (); - } - OBJ m_obj; -- F m_function; -+ MEM m_function; - } * ev = new EventMemberImpl0 (obj, mem_ptr); - return Ptr (ev, false); - } - - --template --Ptr Simulator::MakeEvent (void (T::*mem_ptr) (U1), OBJ obj, T1 a1) -+Ptr Simulator::MakeEvent (MEM mem_ptr, OBJ obj, T1 a1) - { - // one argument version - class EventMemberImpl1 : public EventImpl { - public: -- typedef void (T::*F)(U1); -- EventMemberImpl1 (OBJ obj, F function, T1 a1) -+ EventMemberImpl1 (OBJ obj, MEM function, T1 a1) - : m_obj (obj), - m_function (function), - m_a1 (a1) -@@ -693,23 +672,20 @@ Ptr Simulator::MakeEvent (voi - (EventMemberImplObjTraits::GetReference (m_obj).*m_function) (m_a1); - } - OBJ m_obj; -- F m_function; -+ MEM m_function; - typename TypeTraits::ReferencedType m_a1; - } *ev = new EventMemberImpl1 (obj, mem_ptr, a1); - return Ptr (ev, false); - } - --template --Ptr Simulator::MakeEvent (void (T::*mem_ptr) (U1,U2), OBJ obj, T1 a1, T2 a2) -+Ptr Simulator::MakeEvent (MEM mem_ptr, OBJ obj, T1 a1, T2 a2) - { - // two argument version - class EventMemberImpl2 : public EventImpl { - public: -- typedef void (T::*F)(U1, U2); -- -- EventMemberImpl2 (OBJ obj, F function, T1 a1, T2 a2) -+ EventMemberImpl2 (OBJ obj, MEM function, T1 a1, T2 a2) - : m_obj (obj), - m_function (function), - m_a1 (a1), -@@ -722,24 +698,21 @@ Ptr Simulator::MakeEvent (voi - (EventMemberImplObjTraits::GetReference (m_obj).*m_function) (m_a1, m_a2); - } - OBJ m_obj; -- F m_function; -+ MEM m_function; - typename TypeTraits::ReferencedType m_a1; - typename TypeTraits::ReferencedType m_a2; - } *ev = new EventMemberImpl2 (obj, mem_ptr, a1, a2); - return Ptr (ev, false); - } - --template --Ptr Simulator::MakeEvent (void (T::*mem_ptr) (U1,U2,U3), OBJ obj, T1 a1, T2 a2, T3 a3) -+Ptr Simulator::MakeEvent (MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3) - { - // three argument version - class EventMemberImpl3 : public EventImpl { - public: -- typedef void (T::*F)(U1,U2,U3); -- -- EventMemberImpl3 (OBJ obj, F function, T1 a1, T2 a2, T3 a3) -+ EventMemberImpl3 (OBJ obj, MEM function, T1 a1, T2 a2, T3 a3) - : m_obj (obj), - m_function (function), - m_a1 (a1), -@@ -753,7 +726,7 @@ Ptr Simulator::MakeEvent (voi - (EventMemberImplObjTraits::GetReference (m_obj).*m_function) (m_a1, m_a2, m_a3); - } - OBJ m_obj; -- F m_function; -+ MEM m_function; - typename TypeTraits::ReferencedType m_a1; - typename TypeTraits::ReferencedType m_a2; - typename TypeTraits::ReferencedType m_a3; -@@ -761,17 +734,14 @@ Ptr Simulator::MakeEvent (voi - return Ptr (ev, false); - } - --template --Ptr Simulator::MakeEvent (void (T::*mem_ptr) (U1,U2,U3,U4), OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4) -+Ptr Simulator::MakeEvent (MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4) - { - // four argument version - class EventMemberImpl4 : public EventImpl { - public: -- typedef void (T::*F)(U1, U2, U3, U4); -- -- EventMemberImpl4 (OBJ obj, F function, T1 a1, T2 a2, T3 a3, T4 a4) -+ EventMemberImpl4 (OBJ obj, MEM function, T1 a1, T2 a2, T3 a3, T4 a4) - : m_obj (obj), - m_function (function), - m_a1 (a1), -@@ -786,7 +756,7 @@ Ptr Simulator::MakeEvent (voi - (EventMemberImplObjTraits::GetReference (m_obj).*m_function) (m_a1, m_a2, m_a3, m_a4); - } - OBJ m_obj; -- F m_function; -+ MEM m_function; - typename TypeTraits::ReferencedType m_a1; - typename TypeTraits::ReferencedType m_a2; - typename TypeTraits::ReferencedType m_a3; -@@ -795,18 +765,15 @@ Ptr Simulator::MakeEvent (voi - return Ptr (ev, false); - } - --template --Ptr Simulator::MakeEvent (void (T::*mem_ptr) (U1,U2,U3,U4,U5), OBJ obj, -- T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) -+Ptr Simulator::MakeEvent (MEM mem_ptr, OBJ obj, -+ T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) - { - // five argument version - class EventMemberImpl5 : public EventImpl { - public: -- typedef void (T::*F)(U1, U2, U3, U4, U5); -- -- EventMemberImpl5 (OBJ obj, F function, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) -+ EventMemberImpl5 (OBJ obj, MEM function, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) - : m_obj (obj), - m_function (function), - m_a1 (a1), -@@ -822,7 +789,7 @@ Ptr Simulator::MakeEvent (voi - (EventMemberImplObjTraits::GetReference (m_obj).*m_function) (m_a1, m_a2, m_a3, m_a4, m_a5); - } - OBJ m_obj; -- F m_function; -+ MEM m_function; - typename TypeTraits::ReferencedType m_a1; - typename TypeTraits::ReferencedType m_a2; - typename TypeTraits::ReferencedType m_a3; -@@ -975,50 +942,45 @@ Ptr Simulator::MakeEvent (voi - return Ptr (ev, false); - } - --template --EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (void), OBJ obj) -+template -+EventId Simulator::Schedule (Time const &time, MEM mem_ptr, OBJ obj) - { - return Schedule (time, MakeEvent (mem_ptr, obj)); - } - - --template --EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (U1), OBJ obj, T1 a1) -+EventId Simulator::Schedule (Time const &time, MEM mem_ptr, OBJ obj, T1 a1) - { - return Schedule (time, MakeEvent (mem_ptr, obj, a1)); - } - --template --EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (U1,U2), OBJ obj, T1 a1, T2 a2) -+EventId Simulator::Schedule (Time const &time, MEM mem_ptr, OBJ obj, T1 a1, T2 a2) - { - return Schedule (time, MakeEvent (mem_ptr, obj, a1, a2)); - } - --template --EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (U1,U2,U3), OBJ obj, T1 a1, T2 a2, T3 a3) -+EventId Simulator::Schedule (Time const &time, MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3) - { - return Schedule (time, MakeEvent (mem_ptr, obj, a1, a2, a3)); - } - --template --EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (U1,U2,U3,U4), OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4) -+EventId Simulator::Schedule (Time const &time, MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4) - { - return Schedule (time, MakeEvent (mem_ptr, obj, a1, a2, a3, a4)); - } - --template --EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (U1,U2,U3,U4,U5), OBJ obj, -- T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) -+EventId Simulator::Schedule (Time const &time, MEM mem_ptr, OBJ obj, -+ T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) - { - return Schedule (time, MakeEvent (mem_ptr, obj, a1, a2, a3, a4, a5)); - } -@@ -1060,55 +1022,50 @@ EventId Simulator::Schedule (Time const - - - --template --EventId --Simulator::ScheduleNow (void (T::*mem_ptr) (void), OBJ obj) -+template -+EventId -+Simulator::ScheduleNow (MEM mem_ptr, OBJ obj) - { - return ScheduleNow (MakeEvent (mem_ptr, obj)); - } - - --template - EventId --Simulator::ScheduleNow (void (T::*mem_ptr) (U1), OBJ obj, T1 a1) -+Simulator::ScheduleNow (MEM mem_ptr, OBJ obj, T1 a1) - { - return ScheduleNow (MakeEvent (mem_ptr, obj, a1)); - } - --template - EventId --Simulator::ScheduleNow (void (T::*mem_ptr) (U1,U2), OBJ obj, T1 a1, T2 a2) -+Simulator::ScheduleNow (MEM mem_ptr, OBJ obj, T1 a1, T2 a2) - { - return ScheduleNow (MakeEvent (mem_ptr, obj, a1, a2)); - } - --template - EventId --Simulator::ScheduleNow (void (T::*mem_ptr) (U1,U2,U3), OBJ obj, T1 a1, T2 a2, T3 a3) -+Simulator::ScheduleNow (MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3) - { - return ScheduleNow (MakeEvent (mem_ptr, obj, a1, a2, a3)); - } - --template - EventId --Simulator::ScheduleNow (void (T::*mem_ptr) (U1,U2,U3,U4), OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4) -+Simulator::ScheduleNow (MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4) - { - return ScheduleNow (MakeEvent (mem_ptr, obj, a1, a2, a3, a4)); - } - --template - EventId --Simulator::ScheduleNow (void (T::*mem_ptr) (U1,U2,U3,U4,U5), OBJ obj, -+Simulator::ScheduleNow (MEM mem_ptr, OBJ obj, - T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) - { - return ScheduleNow (MakeEvent (mem_ptr, obj, a1, a2, a3, a4, a5)); -@@ -1156,55 +1113,50 @@ Simulator::ScheduleNow (void (*f) (U1,U2 - - - --template --EventId --Simulator::ScheduleDestroy (void (T::*mem_ptr) (void), OBJ obj) -+template -+EventId -+Simulator::ScheduleDestroy (MEM mem_ptr, OBJ obj) - { - return ScheduleDestroy (MakeEvent (mem_ptr, obj)); - } - - --template - EventId --Simulator::ScheduleDestroy (void (T::*mem_ptr) (U1), OBJ obj, T1 a1) -+Simulator::ScheduleDestroy (MEM mem_ptr, OBJ obj, T1 a1) - { - return ScheduleDestroy (MakeEvent (mem_ptr, obj, a1)); - } - --template - EventId --Simulator::ScheduleDestroy (void (T::*mem_ptr) (U1,U2), OBJ obj, T1 a1, T2 a2) -+Simulator::ScheduleDestroy (MEM mem_ptr, OBJ obj, T1 a1, T2 a2) - { - return ScheduleDestroy (MakeEvent (mem_ptr, obj, a1, a2)); - } - --template - EventId --Simulator::ScheduleDestroy (void (T::*mem_ptr) (U1,U2,U3), OBJ obj, T1 a1, T2 a2, T3 a3) -+Simulator::ScheduleDestroy (MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3) - { - return ScheduleDestroy (MakeEvent (mem_ptr, obj, a1, a2, a3)); - } - --template - EventId --Simulator::ScheduleDestroy (void (T::*mem_ptr) (U1,U2,U3,U4), OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4) -+Simulator::ScheduleDestroy (MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4) - { - return ScheduleDestroy (MakeEvent (mem_ptr, obj, a1, a2, a3, a4)); - } - --template - EventId --Simulator::ScheduleDestroy (void (T::*mem_ptr) (U1,U2,U3,U4,U5), OBJ obj, -+Simulator::ScheduleDestroy (MEM mem_ptr, OBJ obj, - T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) - { - return ScheduleDestroy (MakeEvent (mem_ptr, obj, a1, a2, a3, a4, a5)); -diff -r 2cc09d5a04c4 -r 4743aef86605 wscript ---- a/wscript Mon Aug 20 13:40:15 2007 -0700 -+++ b/wscript Fri Aug 24 13:29:51 2007 -0700 -@@ -37,7 +37,7 @@ def set_options(opt): - - opt.add_option('-d', '--debug-level', - action='callback', -- type=str, dest='debug_level', default='debug', -+ type="string", dest='debug_level', default='debug', - help=('Specify the debug level, does nothing if CFLAGS is set' - ' in the environment. [Allowed Values: debug, optimized].' - ' WARNING: this option only has effect ' - -changeset: 1312:c77745b2731c -user: Craig Dowell -date: Fri Aug 24 16:57:54 2007 -0700 -summary: add ipv4 methods, remove source multicast route requirement, fix udp socket source address prob - -diff -r 4743aef86605 -r c77745b2731c examples/csma-multicast.cc ---- a/examples/csma-multicast.cc Fri Aug 24 13:29:51 2007 -0700 -+++ b/examples/csma-multicast.cc Fri Aug 24 16:57:54 2007 -0700 -@@ -84,6 +84,21 @@ main (int argc, char *argv[]) - DebugComponentEnable("ArpIpv4Interface"); - DebugComponentEnable("Ipv4LoopbackInterface"); - #endif -+ -+ DebugComponentEnable("Channel"); -+ DebugComponentEnable("CsmaChannel"); -+ DebugComponentEnable("CsmaMulticast"); -+ DebugComponentEnable("CsmaNetDevice"); -+ DebugComponentEnable("OnOffApplication"); -+ DebugComponentEnable("PacketSocket"); -+ DebugComponentEnable("UdpSocket"); -+ DebugComponentEnable("UdpL4Protocol"); -+ DebugComponentEnable("Ipv4L3Protocol"); -+ DebugComponentEnable("Ipv4StaticRouting"); -+ DebugComponentEnable("Ipv4Interface"); -+ DebugComponentEnable("ArpIpv4Interface"); -+ DebugComponentEnable("Ipv4LoopbackInterface"); -+ - // - // Set up default values for the simulation. Use the DefaultValue::Bind() - // technique to tell the system what subclass of Queue to use. The Bind -@@ -151,56 +166,32 @@ main (int argc, char *argv[]) - // We've got the "hardware" in place. Now we need to add IP addresses. - // - NS_DEBUG("Assign IP Addresses."); --// --// XXX BUGBUG --// Need a better way to get the interface index. The point-to-point topology --// as implemented can't return the index since it creates interfaces on both --// sides (i.e., it does AddIpv4Addresses, not AddIpv4Address). We need a --// method on Ipv4 to find the interface index corresponding to a given ipv4 --// address. --// --// First, assign IP addresses to the net devices and associated interfaces --// on Lan0. The AddIpv4Address method returns an Ipv4 interface index. --// Interpret ifIndexNd0 as the interface index to use to reference the --// net device we created on node zero when coming in from the Ipv4 interface. --// Net device numbers and interface indices are distinct. Interpret --// ifIndexNd2Lan0 as the interface index to use to reference the --// net device we created that connects node two to lan zero. --// -- uint32_t ifIndexNd0 = CsmaIpv4Topology::AddIpv4Address (n0, nd0, -- Ipv4Address ("10.1.1.1"), Ipv4Mask ("255.255.255.0")); -- -- uint32_t ifIndexNd1 = CsmaIpv4Topology::AddIpv4Address (n1, nd1, -- Ipv4Address ("10.1.1.2"), Ipv4Mask ("255.255.255.0")); -- -- uint32_t ifIndexNd2Lan0 = CsmaIpv4Topology::AddIpv4Address (n2, nd2Lan0, -- Ipv4Address ("10.1.1.3"), Ipv4Mask ("255.255.255.0")); -+ -+ CsmaIpv4Topology::AddIpv4Address (n0, nd0, Ipv4Address ("10.1.1.1"), -+ Ipv4Mask ("255.255.255.0")); -+ -+ CsmaIpv4Topology::AddIpv4Address (n1, nd1, Ipv4Address ("10.1.1.2"), -+ Ipv4Mask ("255.255.255.0")); -+ -+// -+// We'll need these addresses later -+// -+ Ipv4Address n2Lan0Addr ("10.1.1.3"); -+ Ipv4Address n2Lan1Addr ("10.1.2.1"); -+ -+ CsmaIpv4Topology::AddIpv4Address (n2, nd2Lan0, n2Lan0Addr, -+ Ipv4Mask ("255.255.255.0")); - // - // Assign IP addresses to the net devices and associated interfaces on Lan1 - // -- uint32_t ifIndexNd2Lan1 = CsmaIpv4Topology::AddIpv4Address (n2, nd2Lan1, -- Ipv4Address ("10.1.2.1"), Ipv4Mask ("255.255.255.0")); -- -- uint32_t ifIndexNd3 = CsmaIpv4Topology::AddIpv4Address (n3, nd1, -- Ipv4Address ("10.1.2.2"), Ipv4Mask ("255.255.255.0")); -- -- uint32_t ifIndexNd4 = CsmaIpv4Topology::AddIpv4Address (n4, nd4, -- Ipv4Address ("10.1.2.3"), Ipv4Mask ("255.255.255.0")); -- -- NS_DEBUG ("ifIndexNd0 = " << ifIndexNd0); -- NS_DEBUG ("ifIndexNd1 = " << ifIndexNd1); -- NS_DEBUG ("ifIndexNd2Lan0 = " << ifIndexNd2Lan0); -- NS_DEBUG ("ifIndexNd2Lan1 = " << ifIndexNd2Lan1); -- NS_DEBUG ("ifIndexNd3 = " << ifIndexNd3); -- NS_DEBUG ("ifIndexNd4 = " << ifIndexNd4); --// --// A little silliness to let optimized code work while still printing all --// results in debug code (without attribute). --// -- nd3 = nd3; -- ifIndexNd1 = ifIndexNd1; -- ifIndexNd3 = ifIndexNd3; -- ifIndexNd4 = ifIndexNd4; -+ CsmaIpv4Topology::AddIpv4Address (n2, nd2Lan1, n2Lan1Addr, -+ Ipv4Mask ("255.255.255.0")); -+ -+ CsmaIpv4Topology::AddIpv4Address (n3, nd1, Ipv4Address ("10.1.2.2"), -+ Ipv4Mask ("255.255.255.0")); -+ -+ CsmaIpv4Topology::AddIpv4Address (n4, nd4, Ipv4Address ("10.1.2.3"), -+ Ipv4Mask ("255.255.255.0")); - - NS_DEBUG("Configure multicasting."); - // -@@ -216,34 +207,35 @@ main (int argc, char *argv[]) - // - // We are going to manually configure multicast routing. This means telling - // node two that it should expect multicast data coming from IP address --// 10.1.1.1 over its IP interface connected to Lan0. These are called --// multicastSource and ifIndexNd2Lan0 respectively. When node two receives --// these packets, they should be forwarded out the interface that connects it --// to Lan1 which is called ifIndexNd2Lan1. All we need to do is to call the --// AddMulticastRoute method on node two's Ipv4 interface and provide this --// information. (Note: the vector of output interfaces is in case there are --// multiple net devices on a node). -+// 10.1.1.1 originally. It should expect these data coming in over its IP -+// interface connected to Lan0. When node two receives these packets, they -+// should be forwarded out the interface that connects it to Lan1. -+// -+// We're going to need the interface indices on node two corresponding to -+// these interfaces, which we call ifIndexLan0 and ifIndexLan1. The most -+// general way to get these interfaces is to look them up by IP address. -+// Looking back to the topology creation calls above, we saved the addresses -+// assigned to the interface connecting node two to Lan0 and Lan1. Now is -+// a fine time to find the interface indices on node two. - // - Ptr ipv4; - ipv4 = n2->QueryInterface (Ipv4::iid); - -+ uint32_t ifIndexLan0 = ipv4->FindInterfaceForAddr(n2Lan0Addr); -+ uint32_t ifIndexLan1 = ipv4->FindInterfaceForAddr(n2Lan1Addr); -+// -+// Now, we need to do is to call the AddMulticastRoute () method on node -+// two's Ipv4 interface and tell it that whenever it receives a packet on -+// the interface from Lan0, with the packet from the multicast source, -+// destined for the multicast group, it should forward these packets down -+// the interface connecting it to Lan1. (Note: the vector of output -+// interfaces is in case there are multiple net devices on a node -- not -+// true in this case). -+// - std::vector outputInterfaces (1); -- outputInterfaces[0] = ifIndexNd2Lan1; -- -- ipv4->AddMulticastRoute (multicastSource, multicastGroup, ifIndexNd2Lan0, -- outputInterfaces); --// --// We also need to explain to the node zero forwarding code that when it sees --// a packet destined for the multicast group it needs to send it out its --// one and only interface. The 0xffffffff in the call means that the input --// interface qualification is not applicable in this case (the packet has --// not been received over an interface, it has been created locally). --// -- ipv4 = n0->QueryInterface (Ipv4::iid); -- -- outputInterfaces[0] = ifIndexNd0;; -- -- ipv4->AddMulticastRoute (multicastSource, multicastGroup, 0xffffffff, -+ outputInterfaces[0] = ifIndexLan1; -+ -+ ipv4->AddMulticastRoute (multicastSource, multicastGroup, ifIndexLan0, - outputInterfaces); - // - // As described above, node four will be the only node listening for the -diff -r 4743aef86605 -r c77745b2731c src/internet-node/ipv4-impl.cc ---- a/src/internet-node/ipv4-impl.cc Fri Aug 24 13:29:51 2007 -0700 -+++ b/src/internet-node/ipv4-impl.cc Fri Aug 24 16:57:54 2007 -0700 -@@ -136,11 +136,25 @@ Ipv4Impl::AddInterface (Ptr d - { - return m_ipv4->AddInterface (device); - } -+ - uint32_t - Ipv4Impl::GetNInterfaces (void) - { - return m_ipv4->GetNInterfaces (); - } -+ -+uint32_t -+Ipv4Impl::FindInterfaceForAddr (Ipv4Address addr) const -+{ -+ return m_ipv4->FindInterfaceForAddr (addr); -+} -+ -+uint32_t -+Ipv4Impl::FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const -+{ -+ return m_ipv4->FindInterfaceForAddr (addr, mask); -+} -+ - Ptr - Ipv4Impl::GetNetDevice (uint32_t i) - { -diff -r 4743aef86605 -r c77745b2731c src/internet-node/ipv4-impl.h ---- a/src/internet-node/ipv4-impl.h Fri Aug 24 13:29:51 2007 -0700 -+++ b/src/internet-node/ipv4-impl.h Fri Aug 24 16:57:54 2007 -0700 -@@ -72,6 +72,11 @@ public: - - virtual uint32_t AddInterface (Ptr device); - virtual uint32_t GetNInterfaces (void); -+ -+ virtual uint32_t FindInterfaceForAddr (Ipv4Address addr) const; -+ virtual uint32_t FindInterfaceForAddr (Ipv4Address addr, -+ Ipv4Mask mask) const; -+ - virtual Ptr GetNetDevice(uint32_t i); - - virtual void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group); -diff -r 4743aef86605 -r c77745b2731c src/internet-node/ipv4-l3-protocol.cc ---- a/src/internet-node/ipv4-l3-protocol.cc Fri Aug 24 13:29:51 2007 -0700 -+++ b/src/internet-node/ipv4-l3-protocol.cc Fri Aug 24 16:57:54 2007 -0700 -@@ -278,6 +278,33 @@ Ipv4L3Protocol::Lookup ( - return; - } - -+ if (ipHeader.GetDestination ().IsMulticast () && -+ ifIndex == Ipv4RoutingProtocol::IF_INDEX_ANY) -+ { -+ NS_DEBUG ("Ipv4L3Protocol::Lookup (): " -+ "Multicast destination with local source"); -+// -+// We have a multicast packet originating from the current node. We didn't -+// want to force users to construct a route in order to get packets out of a -+// node, so there will have been no route found and it is left to us to send -+// the packet. What we'll do is to send the multicast out all of the -+// interfaces on this node. -+// -+ NS_DEBUG ("Ipv4StaticRouting::Lookup (): " -+ "Local source. Flooding multicast packet"); -+ -+ for (uint32_t i = 0; i < GetNInterfaces (); ++i) -+ { -+ Packet p = packet; -+ Ipv4Header h = ipHeader; -+ Ipv4Route route = -+ Ipv4Route::CreateHostRouteTo(h.GetDestination (), i); -+ NS_DEBUG ("Ipv4StaticRouting::Lookup (): " -+ "Send via interface " << i); -+ routeReply (true, route, p, h); -+ } -+ return; -+ } - // No route found - routeReply (false, Ipv4Route (), packet, ipHeader); - } -@@ -397,6 +424,49 @@ Ipv4L3Protocol::GetNInterfaces (void) co - { - NS_DEBUG("Ipv4L3Protocol::GetNInterface ()"); - return m_nInterfaces; -+} -+ -+uint32_t -+Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr) const -+{ -+ NS_DEBUG("Ipv4L3Protocol::FindInterfaceForAddr (" << addr << ")"); -+ -+ uint32_t ifIndex = 0; -+ for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); -+ i != m_interfaces.end (); -+ i++, ifIndex++) -+ { -+ if ((*i)->GetAddress () == addr) -+ { -+ return ifIndex; -+ } -+ } -+ -+ NS_ASSERT_MSG(false, "Ipv4L3Protocol::FindInterfaceForAddr (): " -+ "Interface not found for IP address"); -+ return 0; -+} -+ -+uint32_t -+Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const -+{ -+ NS_DEBUG("Ipv4L3Protocol::FindInterfaceForAddr (" << addr << ", " << -+ mask << ")"); -+ -+ uint32_t ifIndex = 0; -+ for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); -+ i != m_interfaces.end (); -+ i++, ifIndex++) -+ { -+ if ((*i)->GetAddress ().CombineMask (mask) == addr.CombineMask (mask)) -+ { -+ return ifIndex; -+ } -+ } -+ -+ NS_ASSERT_MSG(false, "Ipv4L3Protocol::FindInterfaceForAddr (): " -+ "Interface not found for masked IP address"); -+ return 0; - } - - Ipv4Interface * -@@ -713,7 +783,40 @@ Ipv4L3Protocol::GetIfIndexForDestination - return true; - } - } -- return false; -+// -+// If there's no routing table entry telling us what single interface will be -+// used to send a packet to this destination, we'll have to just pick one. -+// If there's only one interface on this node, a good answer isn't very hard -+// to come up with. Before jumping to any conclusions, remember that the -+// zeroth interface is the loopback interface, so what we actually want is -+// a situation where there are exactly two interfaces on the node, in which -+// case interface one is the "single" interface. -+// -+ if (GetNInterfaces () == 2) -+ { -+ NS_DEBUG("Ipv4L3Protocol::GetIfIndexForDestination (): " -+ "One Interface. Using interface 1."); -+ ifIndex = 1; -+ return true; -+ } -+// -+// If we fall through to here, we have a node with multiple interfaces and -+// no routes to guide us in determining what interface to choose. The last -+// choice is to use the one set in the default route. -+// -+ NS_DEBUG("Ipv4L3Protocol::GetIfIndexForDestination (): " -+ "Using default route"); -+ Ipv4Route *route = m_staticRouting->GetDefaultRoute (); -+ -+ NS_ASSERT_MSG(route, -+ "Ipv4L3Protocol::GetIfIndexForDestination (): " -+ "Unable to determine outbound interface. No default route set"); -+ -+ ifIndex = route->GetInterface (); -+ -+ NS_DEBUG("Ipv4L3Protocol::GetIfIndexForDestination (): " -+ "Default route specifies interface " << ifIndex); -+ return true; - } - - uint16_t -diff -r 4743aef86605 -r c77745b2731c src/internet-node/ipv4-l3-protocol.h ---- a/src/internet-node/ipv4-l3-protocol.h Fri Aug 24 13:29:51 2007 -0700 -+++ b/src/internet-node/ipv4-l3-protocol.h Fri Aug 24 16:57:54 2007 -0700 -@@ -174,9 +174,12 @@ public: - uint32_t AddInterface (Ptr device); - Ipv4Interface * GetInterface (uint32_t i) const; - uint32_t GetNInterfaces (void) const; -+ -+ uint32_t FindInterfaceForAddr (Ipv4Address addr) const; -+ uint32_t FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const; - -- virtual void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group); -- virtual void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group); -+ void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group); -+ void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group); - - void SetAddress (uint32_t i, Ipv4Address address); - void SetNetworkMask (uint32_t i, Ipv4Mask mask); -diff -r 4743aef86605 -r c77745b2731c src/internet-node/ipv4-static-routing.cc ---- a/src/internet-node/ipv4-static-routing.cc Fri Aug 24 13:29:51 2007 -0700 -+++ b/src/internet-node/ipv4-static-routing.cc Fri Aug 24 16:57:54 2007 -0700 -@@ -230,6 +230,20 @@ Ipv4StaticRouting::GetNRoutes (void) - n += m_networkRoutes.size (); - return n; - } -+ -+Ipv4Route * -+Ipv4StaticRouting::GetDefaultRoute () -+{ -+ if (m_defaultRoute != 0) -+ { -+ return m_defaultRoute; -+ } -+ else -+ { -+ return 0; -+ } -+} -+ - Ipv4Route * - Ipv4StaticRouting::GetRoute (uint32_t index) - { -@@ -331,14 +345,37 @@ Ipv4StaticRouting::RequestRoute ( - - NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): destination = " << - ipHeader.GetDestination ()); --// --// First, see if this is a multicast packet we have a route for. If we --// have a route, then send the packet down each of the specified interfaces. --// -+ - if (ipHeader.GetDestination ().IsMulticast ()) - { - NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): Multicast destination"); -- -+// -+// We have a multicast packet we're going to send. There are two distinct -+// cases we need to support. The first is if the current node is the source -+// of the packet. In that case, we don't want to have to consult multicast -+// routing tables (nor build them) in order to send multicasts. The interface -+// index (ifIndex) is Ipv4RoutingProtocol::IF_INDEX_ANY if we're the source. -+// -+// The second case is if the current packet has gotten to us by being -+// received over one of our interfaces. In this case, ifIndex is set to the -+// index over which we received the packet. For these packets, we need to -+// consult the multicast routing table for a disposition. -+// -+// So, first let's see if we're the source. In this case, we don't consult -+// the routing tables, but just return false and let the caller (up in -+// ipv4-l3-protocol) flood the multicast packet out of all of its interfaces. -+// We can't really do it here even if we wanted to since we have no easy way -+// to get to the Ipv4 interface which we would need. -+// -+ if (ifIndex == Ipv4RoutingProtocol::IF_INDEX_ANY) -+ { -+ return false; -+ } -+// -+// If we fall through to this point, we have a multicast packet that has -+// not originated at this node. We need to deal with forwarding. Let's -+// see if we have a route, and if so go ahead and forward this puppy. -+// - Ipv4MulticastRoute *mRoute = LookupStatic(ipHeader.GetSource (), - ipHeader.GetDestination (), ifIndex); - -@@ -349,14 +386,15 @@ Ipv4StaticRouting::RequestRoute ( - for (uint32_t i = 0; i < mRoute->GetNOutputInterfaces (); ++i) - { - Packet p = packet; -+ Ipv4Header h = ipHeader; - Ipv4Route route = -- Ipv4Route::CreateHostRouteTo(ipHeader.GetDestination (), -+ Ipv4Route::CreateHostRouteTo(h.GetDestination (), - mRoute->GetOutputInterface(i)); - NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): " - "Send via interface " << mRoute->GetOutputInterface(i)); -- routeReply (true, route, p, ipHeader); -- return true; -- } -+ routeReply (true, route, p, h); -+ } -+ return true; - } - return false; // Let other routing protocols try to handle this - } -diff -r 4743aef86605 -r c77745b2731c src/internet-node/ipv4-static-routing.h ---- a/src/internet-node/ipv4-static-routing.h Fri Aug 24 13:29:51 2007 -0700 -+++ b/src/internet-node/ipv4-static-routing.h Fri Aug 24 16:57:54 2007 -0700 -@@ -74,6 +74,7 @@ public: - void SetDefaultRoute (Ipv4Address nextHop, - uint32_t interface); - uint32_t GetNRoutes (void); -+ Ipv4Route *GetDefaultRoute (void); - Ipv4Route *GetRoute (uint32_t i); - void RemoveRoute (uint32_t i); - -diff -r 4743aef86605 -r c77745b2731c src/internet-node/udp-socket.cc ---- a/src/internet-node/udp-socket.cc Fri Aug 24 13:29:51 2007 -0700 -+++ b/src/internet-node/udp-socket.cc Fri Aug 24 16:57:54 2007 -0700 -@@ -182,10 +182,11 @@ UdpSocket::Connect(const Address & addre - NotifyConnectionSucceeded (); - m_connected = true; - -+ NS_DEBUG ("UdpSocket::Connect (): Updating local address"); - Ptr ipv4; - ipv4 = m_node->QueryInterface (Ipv4::iid); - m_endPoint->SetLocalAddress (ipv4->GetSourceAddress(m_defaultAddress)); -- NS_DEBUG ("UdpSocket::Connect (): Local address is" << -+ NS_DEBUG ("UdpSocket::Connect (): Local address is " << - m_endPoint->GetLocalAddress()); - return 0; - } -@@ -214,9 +215,9 @@ UdpSocket::DoSendTo (const Packet &p, co - } - - int --UdpSocket::DoSendTo (const Packet &p, Ipv4Address ipv4, uint16_t port) --{ -- NS_DEBUG("UdpSocket::DoSendTo (" << &p << ", " << ipv4 << ", " << -+UdpSocket::DoSendTo (const Packet &p, Ipv4Address addr, uint16_t port) -+{ -+ NS_DEBUG("UdpSocket::DoSendTo (" << &p << ", " << addr << ", " << - port << ")"); - - if (m_endPoint == 0) -@@ -234,9 +235,16 @@ UdpSocket::DoSendTo (const Packet &p, Ip - return -1; - } - -+ NS_DEBUG ("UdpSocket::DoSendTo (): Finding source address"); -+ Ptr ipv4; -+ ipv4 = m_node->QueryInterface (Ipv4::iid); -+ -+ Ipv4Address source = ipv4->GetSourceAddress(m_defaultAddress); -+ NS_DEBUG ("UdpSocket::DoSendTo (): Source address is " << source); -+ - NS_DEBUG("UdpSocket::DoSendTo (): Send to UDP"); -- m_udp->Send (p, m_endPoint->GetLocalAddress (), ipv4, -- m_endPoint->GetLocalPort (), port); -+ m_udp->Send (p, source, addr, m_endPoint->GetLocalPort (), port); -+ - NotifyDataSent (p.GetSize ()); - return 0; - } -@@ -245,11 +253,13 @@ UdpSocket::SendTo(const Address &address - UdpSocket::SendTo(const Address &address, const Packet &p) - { - NS_DEBUG("UdpSocket::SendTo (" << address << ", " << &p << ")"); -+#if 0 - if (m_connected) - { - m_errno = ERROR_ISCONN; - return -1; - } -+#endif - InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); - Ipv4Address ipv4 = transport.GetIpv4 (); - uint16_t port = transport.GetPort (); -diff -r 4743aef86605 -r c77745b2731c src/node/ipv4.h ---- a/src/node/ipv4.h Fri Aug 24 13:29:51 2007 -0700 -+++ b/src/node/ipv4.h Fri Aug 24 16:57:54 2007 -0700 -@@ -275,6 +275,36 @@ public: - virtual uint32_t GetNInterfaces (void) = 0; - - /** -+ * \brief Find and return the interface ID of the interface that has been -+ * assigned the specified IP address. -+ * \param addr The IP address assigned to the interface of interest. -+ * \returns The index of the ipv4 interface with the given address. -+ * -+ * Each IP interface has an IP address associated with it. It is often -+ * useful to search the list of interfaces for one that corresponds to -+ * a known IP Address. This call takes an IP address as a parameter and -+ * returns the interface index of the first interface that has been assigned -+ * that address. If the address is not found, this function asserts. -+ */ -+ virtual uint32_t FindInterfaceForAddr (Ipv4Address addr) const = 0; -+ -+ /** -+ * \brief Find and return the interface ID of the interface that has been -+ * assigned the specified (masked) IP address. -+ * \param addr The IP address assigned to the interface of interest. -+ * \param mask The address mask to be used in address matching. -+ * \returns The index of the ipv4 interface with the given address. -+ * -+ * Each IP interface has an IP address associated with it. It is often -+ * useful to search the list of interfaces for one that corresponds to -+ * a known IP Address. This call takes an IP address and an IP address -+ * mask as parameters and returns the interface index of the first interface -+ * that matches the masked IP address. -+ */ -+ virtual uint32_t FindInterfaceForAddr (Ipv4Address addr, -+ Ipv4Mask mask) const = 0; -+ -+ /** - * \param i index of ipv4 interface - * \returns the NetDevice associated with the ipv4 interface index - */ - -changeset: 1313:d6f8a7546e7f -user: Craig Dowell -date: Fri Aug 24 17:38:49 2007 -0700 -summary: semi-real multicast hardware addresses - -diff -r c77745b2731c -r d6f8a7546e7f src/devices/csma/csma-net-device.cc ---- a/src/devices/csma/csma-net-device.cc Fri Aug 24 16:57:54 2007 -0700 -+++ b/src/devices/csma/csma-net-device.cc Fri Aug 24 17:38:49 2007 -0700 -@@ -132,7 +132,7 @@ CsmaNetDevice::Init(bool sendEnable, boo - m_queue = 0; - - EnableBroadcast (Eui48Address ("ff:ff:ff:ff:ff:ff")); -- EnableMulticast(); -+ EnableMulticast (Eui48Address ("01:00:5e:00:00:00")); - - SetSendEnable (sendEnable); - SetReceiveEnable (receiveEnable); -@@ -500,10 +500,11 @@ CsmaNetDevice::Receive (const Packet& pa - EthernetHeader header (false); - EthernetTrailer trailer; - Eui48Address broadcast; -+ Eui48Address multicast; - Eui48Address destination; - Packet p = packet; - -- NS_DEBUG ("CsmaNetDevice::Receive UID is (" << p.GetUid() << ")"); -+ NS_DEBUG ("CsmaNetDevice::Receive (): UID is " << p.GetUid()); - - // Only receive if send side of net device is enabled - if (!IsReceiveEnabled()) -@@ -522,12 +523,25 @@ CsmaNetDevice::Receive (const Packet& pa - trailer.CheckFcs(p); - p.RemoveHeader(header); - -+ NS_DEBUG ("CsmaNetDevice::Receive (): Pkt destination is " << -+ header.GetDestination ()); -+// -+// XXX BUGBUG -+// -+// An IP host group address is mapped to an Ethernet multicast address -+// by placing the low-order 23-bits of the IP address into the low-order -+// 23 bits of the Ethernet multicast address 01-00-5E-00-00-00 (hex). -+// -+// Need to mask off the appropriate multicast bits. -+// -+ multicast = Eui48Address::ConvertFrom (GetMulticast ()); - broadcast = Eui48Address::ConvertFrom (GetBroadcast ()); - destination = Eui48Address::ConvertFrom (GetAddress ()); - if ((header.GetDestination() != broadcast) && -+ (header.GetDestination() != multicast) && - (header.GetDestination() != destination)) - { -- // not for us. -+ NS_DEBUG ("CsmaNetDevice::Receive (): Dropping pkt "); - m_dropTrace (p); - return; - } -diff -r c77745b2731c -r d6f8a7546e7f src/devices/point-to-point/point-to-point-net-device.cc ---- a/src/devices/point-to-point/point-to-point-net-device.cc Fri Aug 24 16:57:54 2007 -0700 -+++ b/src/devices/point-to-point/point-to-point-net-device.cc Fri Aug 24 17:38:49 2007 -0700 -@@ -68,11 +68,14 @@ PointToPointNetDevice::PointToPointNetDe - { - NS_DEBUG ("PointToPointNetDevice::PointToPointNetDevice (" << node << ")"); - -- // BUGBUG FIXME -- // -- // You _must_ support broadcast to get any sort of packet from the ARP layer. -+// BUGBUG FIXME -+// -+// You _must_ support broadcast to get any sort of packet from the ARP layer. - EnableBroadcast (Eui48Address ("ff:ff:ff:ff:ff:ff")); -- EnableMulticast(); -+// -+// Randomly pick the ethernet multicast address base -+// -+ EnableMulticast (Eui48Address ("01:00:5e:00:00:00")); - EnablePointToPoint(); - } - -diff -r c77745b2731c -r d6f8a7546e7f src/internet-node/arp-ipv4-interface.cc ---- a/src/internet-node/arp-ipv4-interface.cc Fri Aug 24 16:57:54 2007 -0700 -+++ b/src/internet-node/arp-ipv4-interface.cc Fri Aug 24 17:38:49 2007 -0700 -@@ -84,9 +84,18 @@ ArpIpv4Interface::SendTo (Packet p, Ipv4 - else if (dest.IsMulticast ()) - { - NS_DEBUG ("ArpIpv4Interface::SendTo (): IsMulticast"); -- // XXX BUGBUG -- // Need real multicast addresses -- hardwareDestination = GetDevice ()->GetBroadcast (); -+ NS_ASSERT_MSG(GetDevice ()->IsMulticast (), -+ "ArpIpv4Interface::SendTo (): Sending multicast packet over " -+ "non-multicast device"); -+// XXX -+// -+// An IP host group address is mapped to an Ethernet multicast address -+// by placing the low-order 23-bits of the IP address into the low-order -+// 23 bits of the Ethernet multicast address 01-00-5E-00-00-00 (hex). -+// -+// Currently no easy way to or bit from Ipv4Address into Address -+// -+ hardwareDestination = GetDevice ()->GetMulticast (); - found = true; - } - else -diff -r c77745b2731c -r d6f8a7546e7f src/internet-node/ipv4-l3-protocol.cc ---- a/src/internet-node/ipv4-l3-protocol.cc Fri Aug 24 16:57:54 2007 -0700 -+++ b/src/internet-node/ipv4-l3-protocol.cc Fri Aug 24 17:38:49 2007 -0700 -@@ -288,12 +288,13 @@ Ipv4L3Protocol::Lookup ( - // want to force users to construct a route in order to get packets out of a - // node, so there will have been no route found and it is left to us to send - // the packet. What we'll do is to send the multicast out all of the --// interfaces on this node. -+// interfaces on this node. Note that we start with interface 1 since we -+// don't particularly want to send the packet out the loopback. - // - NS_DEBUG ("Ipv4StaticRouting::Lookup (): " - "Local source. Flooding multicast packet"); - -- for (uint32_t i = 0; i < GetNInterfaces (); ++i) -+ for (uint32_t i = 1; i < GetNInterfaces (); ++i) - { - Packet p = packet; - Ipv4Header h = ipHeader; -diff -r c77745b2731c -r d6f8a7546e7f src/node/net-device.cc ---- a/src/node/net-device.cc Fri Aug 24 16:57:54 2007 -0700 -+++ b/src/node/net-device.cc Fri Aug 24 17:38:49 2007 -0700 -@@ -113,6 +113,7 @@ NetDevice::IsBroadcast (void) const - { - return m_isBroadcast; - } -+ - Address const & - NetDevice::GetBroadcast (void) const - { -@@ -139,10 +140,18 @@ NetDevice::IsMulticast (void) const - return m_isMulticast; - } - --void --NetDevice::EnableMulticast (void) -+Address const & -+NetDevice::GetMulticast (void) const -+{ -+ NS_ASSERT (m_isMulticast); -+ return m_multicast; -+} -+ -+void -+NetDevice::EnableMulticast (Address multicast) - { - m_isMulticast = true; -+ m_multicast = multicast; - } - - void -diff -r c77745b2731c -r d6f8a7546e7f src/node/net-device.h ---- a/src/node/net-device.h Fri Aug 24 16:57:54 2007 -0700 -+++ b/src/node/net-device.h Fri Aug 24 17:38:49 2007 -0700 -@@ -138,10 +138,21 @@ public: - * not true. - */ - Address const &GetBroadcast (void) const; -+ - /** - * \return value of m_isMulticast flag - */ - bool IsMulticast (void) const; -+ -+ /** -+ * \return the multicast address supported by -+ * this netdevice. -+ * -+ * Calling this method is invalid if IsMulticast returns -+ * not true. -+ */ -+ Address const &GetMulticast (void) const; -+ - /** - * \return value of m_isPointToPoint flag - */ -@@ -212,9 +223,10 @@ public: - */ - void DisableBroadcast (void); - /** -- * Set m_isMulticast flag to true -- */ -- void EnableMulticast (void); -+ * Enable multicast support. This method should be -+ * called by subclasses from their constructor -+ */ -+ void EnableMulticast (Address multicast); - /** - * Set m_isMulticast flag to false - */ -@@ -303,6 +315,7 @@ public: - uint16_t m_ifIndex; - Address m_address; - Address m_broadcast; -+ Address m_multicast; - uint16_t m_mtu; - bool m_isUp; - bool m_isBroadcast; - -changeset: 1314:bb5cf98c0c64 -user: Craig Dowell -date: Mon Aug 27 23:46:14 2007 -0700 -summary: real multicast enet addr, more source routes, default multicast route - -diff -r d6f8a7546e7f -r bb5cf98c0c64 examples/csma-multicast.cc ---- a/examples/csma-multicast.cc Fri Aug 24 17:38:49 2007 -0700 -+++ b/examples/csma-multicast.cc Mon Aug 27 23:46:14 2007 -0700 -@@ -98,7 +98,6 @@ main (int argc, char *argv[]) - DebugComponentEnable("Ipv4Interface"); - DebugComponentEnable("ArpIpv4Interface"); - DebugComponentEnable("Ipv4LoopbackInterface"); -- - // - // Set up default values for the simulation. Use the DefaultValue::Bind() - // technique to tell the system what subclass of Queue to use. The Bind -@@ -200,10 +199,11 @@ main (int argc, char *argv[]) - // earlier. We need to define a multicast group to send packets to. This - // can be any multicast address from 224.0.0.0 through 239.255.255.255 - // (avoiding the reserved routing protocol addresses). We just pick a --// convenient number. -+// convenient number (225.0.0.0) and or in some bits to let us verify that -+// correct Ethernet multicast addresses are constructed down in the system. - // - Ipv4Address multicastSource ("10.1.1.1"); -- Ipv4Address multicastGroup ("225.0.0.0"); -+ Ipv4Address multicastGroup ("225.1.2.4"); - // - // We are going to manually configure multicast routing. This means telling - // node two that it should expect multicast data coming from IP address -diff -r d6f8a7546e7f -r bb5cf98c0c64 src/devices/csma/csma-channel.cc ---- a/src/devices/csma/csma-channel.cc Fri Aug 24 17:38:49 2007 -0700 -+++ b/src/devices/csma/csma-channel.cc Mon Aug 27 23:46:14 2007 -0700 -@@ -250,7 +250,7 @@ CsmaChannel::TransmitEnd() - } - - NS_DEBUG ("CsmaChannel::TransmitEnd (): Schedule event in " << -- m_delay.GetSeconds () << "sec"); -+ m_delay.GetSeconds () << " sec"); - - Simulator::Schedule (m_delay, - &CsmaChannel::PropagationCompleteEvent, -diff -r d6f8a7546e7f -r bb5cf98c0c64 src/devices/csma/csma-net-device.cc ---- a/src/devices/csma/csma-net-device.cc Fri Aug 24 17:38:49 2007 -0700 -+++ b/src/devices/csma/csma-net-device.cc Mon Aug 27 23:46:14 2007 -0700 -@@ -526,20 +526,29 @@ CsmaNetDevice::Receive (const Packet& pa - NS_DEBUG ("CsmaNetDevice::Receive (): Pkt destination is " << - header.GetDestination ()); - // --// XXX BUGBUG --// - // An IP host group address is mapped to an Ethernet multicast address - // by placing the low-order 23-bits of the IP address into the low-order - // 23 bits of the Ethernet multicast address 01-00-5E-00-00-00 (hex). - // --// Need to mask off the appropriate multicast bits. --// -+// We are going to receive all packets destined to any multicast address, -+// which means clearing the low-order 23 bits the header destination -+// -+ Eui48Address mcDest; -+ uint8_t mcBuf[6]; -+ -+ header.GetDestination ().CopyTo (mcBuf); -+ mcBuf[3] &= 0x80; -+ mcBuf[4] = 0; -+ mcBuf[5] = 0; -+ mcDest.CopyFrom (mcBuf); -+ - multicast = Eui48Address::ConvertFrom (GetMulticast ()); - broadcast = Eui48Address::ConvertFrom (GetBroadcast ()); - destination = Eui48Address::ConvertFrom (GetAddress ()); -- if ((header.GetDestination() != broadcast) && -- (header.GetDestination() != multicast) && -- (header.GetDestination() != destination)) -+ -+ if ((header.GetDestination () != broadcast) && -+ (mcDest != multicast) && -+ (header.GetDestination () != destination)) - { - NS_DEBUG ("CsmaNetDevice::Receive (): Dropping pkt "); - m_dropTrace (p); -diff -r d6f8a7546e7f -r bb5cf98c0c64 src/internet-node/arp-ipv4-interface.cc ---- a/src/internet-node/arp-ipv4-interface.cc Fri Aug 24 17:38:49 2007 -0700 -+++ b/src/internet-node/arp-ipv4-interface.cc Mon Aug 27 23:46:14 2007 -0700 -@@ -61,6 +61,74 @@ ArpIpv4Interface::DoCreateTraceResolver - return resolver; - } - -+// -+// RFC 1112 says that an IP host group address is mapped to an Ethernet -+// multicast address by placing the low-order 23-bits of the IP address into -+// the low-order 23 bits of the Ethernet multicast address 01-00-5E-00-00-00 -+// (hex). These are completely different animals and they're encapsulated -+// very nicely. Translation: This isn't going to be very pretty. -+// -+Address -+ArpIpv4Interface::MakeMulticastAddress(Ipv4Address multicastGroup) -+{ -+ NS_DEBUG ("ArpIpv4Interface::MakeMulticastAddress (" << multicastGroup << -+ ")"); -+// -+// First, get the generic multicast address from the device. Since it is -+// connected to this object, and this object is an IPV4 stack, we hope that -+// it is really an Eui48Address. If it's not, then we don't know what to do. -+// -+ Address hardwareDestination = GetDevice ()->GetMulticast (); -+ -+ NS_DEBUG ("ArpIpv4Interface::MakeMulticastAddress (): " -+ "Device multicast address: " << hardwareDestination); -+ -+ Eui48Address etherAddr = Eui48Address::ConvertFrom (hardwareDestination); -+// -+// We now have the multicast address in an abstract 48-bit container. We -+// need to pull it out so we can play with it. When we're done, we have the -+// high order bits in etherBuffer[0], etc. -+// -+ uint8_t etherBuffer[6]; -+ etherAddr.CopyTo (etherBuffer); -+// -+// If the device is playing the game correctly, the low order 23 bits of the -+// multicast base address will be zero. -+// -+ NS_ASSERT_MSG((etherBuffer[4] & 0x7f) == 0, -+ "ArpIpv4Interface::SendTo (): Expected low order bits zeroed"); -+ NS_ASSERT_MSG(etherBuffer[5] == 0, -+ "ArpIpv4Interface::SendTo (): Expected low order bits zeroed"); -+ NS_ASSERT_MSG(etherBuffer[6] == 0, -+ "ArpIpv4Interface::SendTo (): Expected low order bits zeroed"); -+// -+// Now we need to pull the raw bits out of the Ipv4 destination address. -+// -+ uint8_t ipBuffer[4]; -+ multicastGroup.Serialize (ipBuffer); -+// -+// We need to place the low order 23 bits of the IP address into the low order -+// 23 bits of the ethernet address. -+// -+ etherBuffer[3] |= ipBuffer[1] & 0x7f; -+ etherBuffer[4] = ipBuffer[2]; -+ etherBuffer[5] = ipBuffer[3]; -+// -+// Now, etherBuffer has the desired ethernet multicast address. We have to -+// suck these bits back into the Eui48Address; and then suck those bits back -+// into the abstract hardwareAddress. -+// -+ etherAddr.CopyFrom (etherBuffer); -+// -+// Implicit conversion (operator Address ()) is defined for Eui48Address, so -+// use it. -+// -+ NS_DEBUG ("ArpIpv4Interface::MakeMulticastAddress (): " -+ "multicast address is " << etherAddr); -+ -+ return etherAddr; -+} -+ - void - ArpIpv4Interface::SendTo (Packet p, Ipv4Address dest) - { -@@ -87,15 +155,8 @@ ArpIpv4Interface::SendTo (Packet p, Ipv4 - NS_ASSERT_MSG(GetDevice ()->IsMulticast (), - "ArpIpv4Interface::SendTo (): Sending multicast packet over " - "non-multicast device"); --// XXX --// --// An IP host group address is mapped to an Ethernet multicast address --// by placing the low-order 23-bits of the IP address into the low-order --// 23 bits of the Ethernet multicast address 01-00-5E-00-00-00 (hex). --// --// Currently no easy way to or bit from Ipv4Address into Address --// -- hardwareDestination = GetDevice ()->GetMulticast (); -+ -+ hardwareDestination = MakeMulticastAddress(dest); - found = true; - } - else -diff -r d6f8a7546e7f -r bb5cf98c0c64 src/internet-node/arp-ipv4-interface.h ---- a/src/internet-node/arp-ipv4-interface.h Fri Aug 24 17:38:49 2007 -0700 -+++ b/src/internet-node/arp-ipv4-interface.h Mon Aug 27 23:46:14 2007 -0700 -@@ -24,6 +24,7 @@ - - #include "ipv4-interface.h" - #include "ns3/ptr.h" -+#include "ns3/eui48-address.h" - - namespace ns3 { - -@@ -46,6 +47,7 @@ class ArpIpv4Interface : public Ipv4Inte - virtual void SendTo (Packet p, Ipv4Address dest); - virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context); - Ptr m_node; -+ Address MakeMulticastAddress (Ipv4Address multicastGroup); - }; - - }//namespace ns3 -diff -r d6f8a7546e7f -r bb5cf98c0c64 src/internet-node/ipv4-impl.cc ---- a/src/internet-node/ipv4-impl.cc Fri Aug 24 17:38:49 2007 -0700 -+++ b/src/internet-node/ipv4-impl.cc Mon Aug 27 23:46:14 2007 -0700 -@@ -105,6 +105,16 @@ Ipv4Impl::AddMulticastRoute (Ipv4Address - m_ipv4->AddMulticastRoute (origin, group, inputInterface, outputInterfaces); - } - -+void -+Ipv4Impl::SetDefaultMulticastRoute (Ipv4Address origin, -+ Ipv4Address group, -+ uint32_t inputInterface, -+ std::vector outputInterfaces) -+{ -+ m_ipv4->SetDefaultMulticastRoute (origin, group, inputInterface, -+ outputInterfaces); -+} -+ - uint32_t - Ipv4Impl::GetNMulticastRoutes (void) const - { -@@ -208,6 +218,9 @@ Ipv4Impl::GetSourceAddress (Ipv4Address - } - else - { -+// -+// If we can't find any address, just leave it 0.0.0.0 -+// - return Ipv4Address::GetAny (); - } - } -diff -r d6f8a7546e7f -r bb5cf98c0c64 src/internet-node/ipv4-impl.h ---- a/src/internet-node/ipv4-impl.h Fri Aug 24 17:38:49 2007 -0700 -+++ b/src/internet-node/ipv4-impl.h Mon Aug 27 23:46:14 2007 -0700 -@@ -62,6 +62,10 @@ public: - uint32_t inputInterface, - std::vector outputInterfaces); - -+ virtual void SetDefaultMulticastRoute (Ipv4Address origin, -+ Ipv4Address group, uint32_t inputInterface, -+ std::vector outputInterfaces); -+ - virtual uint32_t GetNMulticastRoutes (void) const; - virtual Ipv4MulticastRoute GetMulticastRoute (uint32_t i) const; - -diff -r d6f8a7546e7f -r bb5cf98c0c64 src/internet-node/ipv4-l3-protocol.cc ---- a/src/internet-node/ipv4-l3-protocol.cc Fri Aug 24 17:38:49 2007 -0700 -+++ b/src/internet-node/ipv4-l3-protocol.cc Mon Aug 27 23:46:14 2007 -0700 -@@ -352,6 +352,20 @@ Ipv4L3Protocol::AddMulticastRoute (Ipv4A - group << ", " << inputInterface << ", " << &outputInterfaces << ")"); - - m_staticRouting->AddMulticastRoute (origin, group, inputInterface, -+ outputInterfaces); -+} -+ -+void -+Ipv4L3Protocol::SetDefaultMulticastRoute ( -+ Ipv4Address origin, -+ Ipv4Address group, -+ uint32_t inputInterface, -+ std::vector outputInterfaces) -+{ -+ NS_DEBUG("Ipv4L3Protocol::SetDefaultMulticastRoute (" << origin << ", " << -+ group << ", " << inputInterface << ", " << &outputInterfaces << ")"); -+ -+ m_staticRouting->SetDefaultMulticastRoute (origin, group, inputInterface, - outputInterfaces); - } - -@@ -768,7 +782,11 @@ Ipv4L3Protocol::GetIfIndexForDestination - { - NS_DEBUG("Ipv4L3Protocol::GetIfIndexForDestination (" << destination << - ", " << &ifIndex << ")"); -- -+// -+// The first thing we do in trying to determine a source address is to -+// consult the routing protocols. These will also check for a default route -+// if one has been set. -+// - for (Ipv4RoutingProtocolList::const_iterator i = m_routingProtocols.begin (); - i != m_routingProtocols.end (); - i++) -@@ -785,13 +803,13 @@ Ipv4L3Protocol::GetIfIndexForDestination - } - } - // --// If there's no routing table entry telling us what single interface will be --// used to send a packet to this destination, we'll have to just pick one. -+// If there's no routing table entry telling us what *single* interface will -+// be used to send a packet to this destination, we'll have to just pick one. - // If there's only one interface on this node, a good answer isn't very hard - // to come up with. Before jumping to any conclusions, remember that the - // zeroth interface is the loopback interface, so what we actually want is - // a situation where there are exactly two interfaces on the node, in which --// case interface one is the "single" interface. -+// case interface one is the "single" interface connected to the outside world. - // - if (GetNInterfaces () == 2) - { -@@ -802,11 +820,21 @@ Ipv4L3Protocol::GetIfIndexForDestination - } - // - // If we fall through to here, we have a node with multiple interfaces and --// no routes to guide us in determining what interface to choose. The last --// choice is to use the one set in the default route. --// -+// no routes to guide us in determining what interface to choose. Either -+// no default route was found (for unicast or multicast), or in the case of a -+// multicast, the default route contained multiple outbound interfaces. -+// -+// The fallback position is to just get the unicast default route and use -+// the outgoing interface specified there. We don't want to leave the source -+// address unset, so we just assert here. -+// -+// N.B. that in the case of a multicast with a route containing multiple -+// outgoing interfaces, the source address of packets from that node will be -+// set to the IP address of the interface set in the default unicast route. -+// Also, in the case of a broadcast, the same will be true. -+// - NS_DEBUG("Ipv4L3Protocol::GetIfIndexForDestination (): " -- "Using default route"); -+ "Using default unicast route"); - Ipv4Route *route = m_staticRouting->GetDefaultRoute (); - - NS_ASSERT_MSG(route, -diff -r d6f8a7546e7f -r bb5cf98c0c64 src/internet-node/ipv4-l3-protocol.h ---- a/src/internet-node/ipv4-l3-protocol.h Fri Aug 24 17:38:49 2007 -0700 -+++ b/src/internet-node/ipv4-l3-protocol.h Mon Aug 27 23:46:14 2007 -0700 -@@ -163,6 +163,11 @@ public: - uint32_t inputInterface, - std::vector outputInterfaces); - -+ void SetDefaultMulticastRoute (Ipv4Address origin, -+ Ipv4Address group, -+ uint32_t inputInterface, -+ std::vector outputInterfaces); -+ - uint32_t GetNMulticastRoutes (void) const; - Ipv4MulticastRoute *GetMulticastRoute (uint32_t i) const; - -diff -r d6f8a7546e7f -r bb5cf98c0c64 src/internet-node/ipv4-static-routing.cc ---- a/src/internet-node/ipv4-static-routing.cc Fri Aug 24 17:38:49 2007 -0700 -+++ b/src/internet-node/ipv4-static-routing.cc Mon Aug 27 23:46:14 2007 -0700 -@@ -26,6 +26,11 @@ NS_DEBUG_COMPONENT_DEFINE ("Ipv4StaticRo - NS_DEBUG_COMPONENT_DEFINE ("Ipv4StaticRouting"); - - namespace ns3 { -+ -+Ipv4StaticRouting::Ipv4StaticRouting () -+: m_defaultRoute (0), m_defaultMulticastRoute (0) -+{ -+} - - void - Ipv4StaticRouting::AddHostRouteTo (Ipv4Address dest, -@@ -95,10 +100,24 @@ Ipv4StaticRouting::AddMulticastRoute(Ipv - m_multicastRoutes.push_back (route); - } - -+void -+Ipv4StaticRouting::SetDefaultMulticastRoute( -+ Ipv4Address origin, -+ Ipv4Address group, -+ uint32_t inputInterface, -+ std::vector outputInterfaces) -+{ -+ Ipv4MulticastRoute *route = new Ipv4MulticastRoute (); -+ *route = Ipv4MulticastRoute::CreateMulticastRoute (origin, group, -+ inputInterface, outputInterfaces); -+ delete m_defaultMulticastRoute; -+ m_defaultMulticastRoute = route; -+} -+ - uint32_t - Ipv4StaticRouting::GetNMulticastRoutes (void) const - { -- return m_multicastRoutes.size (); -+ return m_multicastRoutes.size () + m_defaultMulticastRoute ? 1 : 0; - } - - Ipv4MulticastRoute * -@@ -106,17 +125,54 @@ Ipv4StaticRouting::GetMulticastRoute (ui - { - NS_ASSERT_MSG(index < m_multicastRoutes.size (), - "Ipv4StaticRouting::GetMulticastRoute (): Index out of range"); -- -- uint32_t tmp = 0; -- for (MulticastRoutesCI i = m_multicastRoutes.begin (); -- i != m_multicastRoutes.end (); -- i++) -- { -- if (tmp == index) -- { -- return *i; -- } -- tmp++; -+// -+// From an external point of view the default route appears to be in slot 0 -+// of the routing table. The implementation, however, puts it in a separate -+// place. So, if a client asks for index 0 and we have a default multicast -+// route, we have to return it from that different place -+// (m_defaultMulticastRoute). -+// -+ if (index == 0 && m_defaultMulticastRoute != 0) -+ { -+ return m_defaultMulticastRoute; -+ } -+// -+// If there is a default multicast route present, a client will just assume -+// that it is in slot zero and there is one "extra" zeroth route in the table. -+// To return the correct indexed entry in our list, we have to decrement the -+// index to take into account the default route not being in the actual list. -+// Since we fell through to here, we've taken care of the case where the -+// index was zero. -+// -+ if (m_defaultMulticastRoute != 0) -+ { -+ NS_ASSERT(index > 0); -+ index--; -+ } -+ -+ if (index < m_multicastRoutes.size ()) -+ { -+ uint32_t tmp = 0; -+ for (MulticastRoutesCI i = m_multicastRoutes.begin (); -+ i != m_multicastRoutes.end (); -+ i++) -+ { -+ if (tmp == index) -+ { -+ return *i; -+ } -+ tmp++; -+ } -+ } -+ return 0; -+} -+ -+Ipv4MulticastRoute * -+Ipv4StaticRouting::GetDefaultMulticastRoute () const -+{ -+ if (m_defaultMulticastRoute != 0) -+ { -+ return m_defaultMulticastRoute; - } - return 0; - } -@@ -126,6 +182,9 @@ Ipv4StaticRouting::RemoveMulticastRoute( - Ipv4Address group, - uint32_t inputInterface) - { -+// -+// This method does not attempt to delete the multicast route. -+// - for (MulticastRoutesI i = m_multicastRoutes.begin (); - i != m_multicastRoutes.end (); - i++) -@@ -145,6 +204,32 @@ void - void - Ipv4StaticRouting::RemoveMulticastRoute(uint32_t index) - { -+// -+// From an external point of view the default route appears to be in slot 0 -+// of the routing table. The implementation, however, puts it in a separate -+// place. So, if a client asks to delete index 0 and we have a default -+// multicast route set, we have to delete it from that different place -+// (m_defaultMulticastRoute). -+// -+ if (index == 0 && m_defaultMulticastRoute != 0) -+ { -+ delete m_defaultMulticastRoute; -+ m_defaultMulticastRoute = 0; -+ } -+// -+// If there is a default multicast route present, a client will just assume -+// that it is in slot zero and there is one "extra" zeroth route in the table. -+// To return the correct indexed entry in our list, we have to decrement the -+// index to take into account the default route not being in the actual list. -+// Since we fell through to here, we've taken care of the case where the -+// index was zero. -+// -+ if (m_defaultMulticastRoute != 0) -+ { -+ NS_ASSERT(index > 0); -+ index--; -+ } -+ - uint32_t tmp = 0; - for (MulticastRoutesI i = m_multicastRoutes.begin (); - i != m_multicastRoutes.end (); -@@ -215,6 +300,12 @@ Ipv4StaticRouting::LookupStatic ( - } - } - } -+ -+ if (m_defaultMulticastRoute != 0) -+ { -+ return m_defaultMulticastRoute; -+ } -+ - return 0; - } - -@@ -492,6 +583,11 @@ Ipv4StaticRouting::DoDispose (void) - { - delete (*i); - } -+ if (m_defaultMulticastRoute != 0) -+ { -+ delete m_defaultMulticastRoute; -+ m_defaultMulticastRoute = 0; -+ } - Ipv4RoutingProtocol::DoDispose (); - } - -diff -r d6f8a7546e7f -r bb5cf98c0c64 src/internet-node/ipv4-static-routing.h ---- a/src/internet-node/ipv4-static-routing.h Fri Aug 24 17:38:49 2007 -0700 -+++ b/src/internet-node/ipv4-static-routing.h Mon Aug 27 23:46:14 2007 -0700 -@@ -49,7 +49,7 @@ class Ipv4StaticRouting : public Ipv4Rou - { - - public: -- Ipv4StaticRouting () : m_defaultRoute (0) {} -+ Ipv4StaticRouting (); - - virtual bool RequestRoute (uint32_t ifIndex, - Ipv4Header const &ipHeader, -@@ -83,8 +83,14 @@ public: - uint32_t inputInterface, - std::vector outputInterfaces); - -+ void SetDefaultMulticastRoute (Ipv4Address origin, -+ Ipv4Address group, -+ uint32_t inputInterface, -+ std::vector outputInterfaces); -+ - uint32_t GetNMulticastRoutes (void) const; - Ipv4MulticastRoute *GetMulticastRoute (uint32_t i) const; -+ Ipv4MulticastRoute *GetDefaultMulticastRoute (void) const; - - void RemoveMulticastRoute (Ipv4Address origin, - Ipv4Address group, -@@ -114,6 +120,7 @@ private: - HostRoutes m_hostRoutes; - NetworkRoutes m_networkRoutes; - Ipv4Route *m_defaultRoute; -+ Ipv4MulticastRoute *m_defaultMulticastRoute; - MulticastRoutes m_multicastRoutes; - }; - -diff -r d6f8a7546e7f -r bb5cf98c0c64 src/node/ipv4.h ---- a/src/node/ipv4.h Fri Aug 24 17:38:49 2007 -0700 -+++ b/src/node/ipv4.h Mon Aug 27 23:46:14 2007 -0700 -@@ -244,6 +244,19 @@ public: - uint32_t inputInterface) = 0; - - /** -+ * \brief Set the default static multicast route for a given multicast -+ * source and group. -+ * -+ * \param origin The Ipv4 address of the multicast source. -+ * \param group The multicast group address. -+ * \param inputInterface The interface index over which the packet arrived. -+ * \param outputInterfaces The list of output interface indices over which -+ * the packet should be sent (excluding the inputInterface). -+ */ -+ virtual void SetDefaultMulticastRoute (Ipv4Address origin, -+ Ipv4Address group, uint32_t inputInterface, -+ std::vector outputInterfaces) = 0; -+ /** - * \returns the number of entries in the multicast routing table. - */ - virtual uint32_t GetNMulticastRoutes (void) const = 0; - -changeset: 1315:580ed7a4dd1e -user: Craig Dowell -date: Wed Aug 29 12:11:11 2007 -0700 -summary: Move MakeMulticastAddress to NetDevice - -diff -r bb5cf98c0c64 -r 580ed7a4dd1e src/devices/csma/csma-net-device.cc ---- a/src/devices/csma/csma-net-device.cc Mon Aug 27 23:46:14 2007 -0700 -+++ b/src/devices/csma/csma-net-device.cc Wed Aug 29 12:11:11 2007 -0700 -@@ -19,8 +19,6 @@ - * Author: Emmanuelle Laprise - */ - --#include --#include - #include "ns3/debug.h" - #include "ns3/queue.h" - #include "ns3/simulator.h" -@@ -60,7 +58,6 @@ CsmaTraceType::GetUid (void) - return uid; - } - -- - CsmaNetDevice::CsmaNetDevice (Ptr node) - : NetDevice (node, Eui48Address::Allocate ()), - m_bps (DataRate (0xffffffff)) -@@ -71,7 +68,7 @@ CsmaNetDevice::CsmaNetDevice (Ptr - } - - CsmaNetDevice::CsmaNetDevice (Ptr node, Eui48Address addr, -- CsmaEncapsulationMode encapMode) -+ CsmaEncapsulationMode encapMode) - : NetDevice(node, addr), - m_bps (DataRate (0xffffffff)) - { -@@ -82,8 +79,8 @@ CsmaNetDevice::CsmaNetDevice (Ptr - } - - CsmaNetDevice::CsmaNetDevice (Ptr node, Eui48Address addr, -- CsmaEncapsulationMode encapMode, -- bool sendEnable, bool receiveEnable) -+ CsmaEncapsulationMode encapMode, -+ bool sendEnable, bool receiveEnable) - : NetDevice(node, addr), - m_bps (DataRate (0xffffffff)) - { -@@ -582,6 +579,61 @@ CsmaNetDevice::Receive (const Packet& pa - return; - } - -+Address -+CsmaNetDevice::MakeMulticastAddress(Ipv4Address multicastGroup) const -+{ -+ NS_DEBUG ("CsmaNetDevice::MakeMulticastAddress (" << multicastGroup << -+ ")"); -+// -+// First, get the generic multicast address. -+// -+ Address hardwareDestination = GetMulticast (); -+ -+ NS_DEBUG ("CsmaNetDevice::MakeMulticastAddress (): " -+ "Device multicast address: " << hardwareDestination); -+// -+// It's our address, and we know we're playing with an EUI-48 address here -+// primarily since we know that by construction, but also since the parameter -+// is an Ipv4Address. -+// -+ Eui48Address etherAddr = Eui48Address::ConvertFrom (hardwareDestination); -+// -+// We now have the multicast address in an abstract 48-bit container. We -+// need to pull it out so we can play with it. When we're done, we have the -+// high order bits in etherBuffer[0], etc. -+// -+ uint8_t etherBuffer[6]; -+ etherAddr.CopyTo (etherBuffer); -+// -+// Now we need to pull the raw bits out of the Ipv4 destination address. -+// -+ uint8_t ipBuffer[4]; -+ multicastGroup.Serialize (ipBuffer); -+// -+// RFC 1112 says that an Ipv4 host group address is mapped to an EUI-48 -+// multicast address by placing the low-order 23-bits of the IP address into -+// the low-order 23 bits of the Ethernet multicast address -+// 01-00-5E-00-00-00 (hex). -+// -+ etherBuffer[3] |= ipBuffer[1] & 0x7f; -+ etherBuffer[4] = ipBuffer[2]; -+ etherBuffer[5] = ipBuffer[3]; -+// -+// Now, etherBuffer has the desired ethernet multicast address. We have to -+// suck these bits back into the Eui48Address, -+// -+ etherAddr.CopyFrom (etherBuffer); -+// -+// Implicit conversion (operator Address ()) is defined for Eui48Address, so -+// use it by just returning the EUI-48 address which is automagically converted -+// to an Address. -+// -+ NS_DEBUG ("CsmaNetDevice::MakeMulticastAddress (): " -+ "multicast address is " << etherAddr); -+ -+ return etherAddr; -+} -+ - Ptr - CsmaNetDevice::GetQueue(void) const - { -diff -r bb5cf98c0c64 -r 580ed7a4dd1e src/devices/csma/csma-net-device.h ---- a/src/devices/csma/csma-net-device.h Mon Aug 27 23:46:14 2007 -0700 -+++ b/src/devices/csma/csma-net-device.h Wed Aug 29 12:11:11 2007 -0700 -@@ -197,6 +197,37 @@ enum CsmaEncapsulationMode { - */ - void Receive (const Packet& p); - -+ /** -+ * @brief Make and return a MAC multicast address using the provided -+ * multicast group -+ * -+ * RFC 1112 says that an Ipv4 host group address is mapped to an Ethernet -+ * multicast address by placing the low-order 23-bits of the IP address into -+ * the low-order 23 bits of the Ethernet multicast address -+ * 01-00-5E-00-00-00 (hex). -+ * -+ * This method performs the multicast address creation function appropriate -+ * to an EUI-48-based CSMA device. This MAC address is encapsulated in an -+ * abstract Address to avoid dependencies on the exact address format. -+ * -+ * A default imlementation of MakeMulticastAddress is provided, but this -+ * method simply NS_ASSERTS. In the case of net devices that do not support -+ * multicast, clients are expected to test NetDevice::IsMulticast and avoid -+ * attempting to map multicast packets. Subclasses of NetDevice that do -+ * support multicasting are expected to override this method and provide an -+ * implementation appropriate to the particular device. -+ * -+ * @param multicastGroup The IP address for the multicast group destination -+ * of the packet. -+ * @return The MAC multicast Address used to send packets to the provided -+ * multicast group. -+ * -+ * @see Ipv4Address -+ * @see Eui48Address -+ * @see Address -+ */ -+ Address MakeMulticastAddress (Ipv4Address multicastGroup) const; -+ - bool IsSendEnabled (void); - bool IsReceiveEnabled (void); - -diff -r bb5cf98c0c64 -r 580ed7a4dd1e src/devices/point-to-point/point-to-point-net-device.cc ---- a/src/devices/point-to-point/point-to-point-net-device.cc Mon Aug 27 23:46:14 2007 -0700 -+++ b/src/devices/point-to-point/point-to-point-net-device.cc Wed Aug 29 12:11:11 2007 -0700 -@@ -20,8 +20,6 @@ - * Revised: George Riley - */ - --#include --#include - #include "ns3/debug.h" - #include "ns3/queue.h" - #include "ns3/simulator.h" -@@ -73,7 +71,7 @@ PointToPointNetDevice::PointToPointNetDe - // You _must_ support broadcast to get any sort of packet from the ARP layer. - EnableBroadcast (Eui48Address ("ff:ff:ff:ff:ff:ff")); - // --// Randomly pick the ethernet multicast address base -+// We want to allow multicast packets to flow across this link - // - EnableMulticast (Eui48Address ("01:00:5e:00:00:00")); - EnablePointToPoint(); -@@ -214,6 +212,8 @@ bool PointToPointNetDevice::Attach (Ptr< - m_bps = m_channel->GetDataRate (); - // GFR Comment. Below is definitely wrong. Interframe gap - // is unrelated to channel delay. -+ // -- unlesss you want to introduce a default gap which is there to avoid -+ // parts of multiple packets flowing on the "wire" at the same time. - //m_tInterframeGap = m_channel->GetDelay (); - - /* -diff -r bb5cf98c0c64 -r 580ed7a4dd1e src/internet-node/arp-ipv4-interface.cc ---- a/src/internet-node/arp-ipv4-interface.cc Mon Aug 27 23:46:14 2007 -0700 -+++ b/src/internet-node/arp-ipv4-interface.cc Wed Aug 29 12:11:11 2007 -0700 -@@ -61,74 +61,6 @@ ArpIpv4Interface::DoCreateTraceResolver - return resolver; - } - --// --// RFC 1112 says that an IP host group address is mapped to an Ethernet --// multicast address by placing the low-order 23-bits of the IP address into --// the low-order 23 bits of the Ethernet multicast address 01-00-5E-00-00-00 --// (hex). These are completely different animals and they're encapsulated --// very nicely. Translation: This isn't going to be very pretty. --// --Address --ArpIpv4Interface::MakeMulticastAddress(Ipv4Address multicastGroup) --{ -- NS_DEBUG ("ArpIpv4Interface::MakeMulticastAddress (" << multicastGroup << -- ")"); --// --// First, get the generic multicast address from the device. Since it is --// connected to this object, and this object is an IPV4 stack, we hope that --// it is really an Eui48Address. If it's not, then we don't know what to do. --// -- Address hardwareDestination = GetDevice ()->GetMulticast (); -- -- NS_DEBUG ("ArpIpv4Interface::MakeMulticastAddress (): " -- "Device multicast address: " << hardwareDestination); -- -- Eui48Address etherAddr = Eui48Address::ConvertFrom (hardwareDestination); --// --// We now have the multicast address in an abstract 48-bit container. We --// need to pull it out so we can play with it. When we're done, we have the --// high order bits in etherBuffer[0], etc. --// -- uint8_t etherBuffer[6]; -- etherAddr.CopyTo (etherBuffer); --// --// If the device is playing the game correctly, the low order 23 bits of the --// multicast base address will be zero. --// -- NS_ASSERT_MSG((etherBuffer[4] & 0x7f) == 0, -- "ArpIpv4Interface::SendTo (): Expected low order bits zeroed"); -- NS_ASSERT_MSG(etherBuffer[5] == 0, -- "ArpIpv4Interface::SendTo (): Expected low order bits zeroed"); -- NS_ASSERT_MSG(etherBuffer[6] == 0, -- "ArpIpv4Interface::SendTo (): Expected low order bits zeroed"); --// --// Now we need to pull the raw bits out of the Ipv4 destination address. --// -- uint8_t ipBuffer[4]; -- multicastGroup.Serialize (ipBuffer); --// --// We need to place the low order 23 bits of the IP address into the low order --// 23 bits of the ethernet address. --// -- etherBuffer[3] |= ipBuffer[1] & 0x7f; -- etherBuffer[4] = ipBuffer[2]; -- etherBuffer[5] = ipBuffer[3]; --// --// Now, etherBuffer has the desired ethernet multicast address. We have to --// suck these bits back into the Eui48Address; and then suck those bits back --// into the abstract hardwareAddress. --// -- etherAddr.CopyFrom (etherBuffer); --// --// Implicit conversion (operator Address ()) is defined for Eui48Address, so --// use it. --// -- NS_DEBUG ("ArpIpv4Interface::MakeMulticastAddress (): " -- "multicast address is " << etherAddr); -- -- return etherAddr; --} -- - void - ArpIpv4Interface::SendTo (Packet p, Ipv4Address dest) - { -@@ -156,7 +88,7 @@ ArpIpv4Interface::SendTo (Packet p, Ipv4 - "ArpIpv4Interface::SendTo (): Sending multicast packet over " - "non-multicast device"); - -- hardwareDestination = MakeMulticastAddress(dest); -+ hardwareDestination = GetDevice ()->MakeMulticastAddress(dest); - found = true; - } - else -diff -r bb5cf98c0c64 -r 580ed7a4dd1e src/internet-node/arp-ipv4-interface.h ---- a/src/internet-node/arp-ipv4-interface.h Mon Aug 27 23:46:14 2007 -0700 -+++ b/src/internet-node/arp-ipv4-interface.h Wed Aug 29 12:11:11 2007 -0700 -@@ -47,7 +47,6 @@ class ArpIpv4Interface : public Ipv4Inte - virtual void SendTo (Packet p, Ipv4Address dest); - virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context); - Ptr m_node; -- Address MakeMulticastAddress (Ipv4Address multicastGroup); - }; - - }//namespace ns3 -diff -r bb5cf98c0c64 -r 580ed7a4dd1e src/internet-node/ipv4-l3-protocol.cc ---- a/src/internet-node/ipv4-l3-protocol.cc Mon Aug 27 23:46:14 2007 -0700 -+++ b/src/internet-node/ipv4-l3-protocol.cc Wed Aug 29 12:11:11 2007 -0700 -@@ -503,6 +503,8 @@ Ipv4L3Protocol::Receive( Ptr - { - NS_DEBUG("Ipv4L3Protocol::Receive (" << &device << ", " << &p << ", " << - protocol << ", " << from << ")"); -+ -+ NS_DEBUG("Ipv4L3Protocol::Receive (): Packet from " << from); - - uint32_t index = 0; - for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); -diff -r bb5cf98c0c64 -r 580ed7a4dd1e src/node/net-device.cc ---- a/src/node/net-device.cc Mon Aug 27 23:46:14 2007 -0700 -+++ b/src/node/net-device.cc Wed Aug 29 12:11:11 2007 -0700 -@@ -140,10 +140,19 @@ NetDevice::IsMulticast (void) const - return m_isMulticast; - } - --Address const & -+Address - NetDevice::GetMulticast (void) const - { -- NS_ASSERT (m_isMulticast); -+ NS_ASSERT_MSG (m_isMulticast, "NetDevice::GetMulticast (): " -+ "Invalid operation when not IsMulticast ()"); -+ return m_multicast; -+} -+ -+Address -+NetDevice::MakeMulticastAddress(Ipv4Address multicastGroup) const -+{ -+ NS_ASSERT_MSG (m_isMulticast, "NetDevice::GetMulticast (): " -+ "Invalid operation when not IsMulticast ()"); - return m_multicast; - } - -diff -r bb5cf98c0c64 -r 580ed7a4dd1e src/node/net-device.h ---- a/src/node/net-device.h Mon Aug 27 23:46:14 2007 -0700 -+++ b/src/node/net-device.h Wed Aug 29 12:11:11 2007 -0700 -@@ -29,6 +29,7 @@ - #include "ns3/object.h" - #include "ns3/ptr.h" - #include "address.h" -+#include "ipv4-address.h" - - namespace ns3 { - -@@ -145,13 +146,61 @@ public: - bool IsMulticast (void) const; - - /** -- * \return the multicast address supported by -- * this netdevice. -- * -- * Calling this method is invalid if IsMulticast returns -- * not true. -- */ -- Address const &GetMulticast (void) const; -+ * \brief Return the MAC multicast base address used when mapping multicast -+ * groups to MAC multicast addresses. -+ * -+ * Typically when one constructs a multicast MAC addresses, some bits from -+ * the IP multicast group are copied into a corresponding MAC multicast -+ * group. In EUI-48, for example, the low order 23 bits of the multicast -+ * group are copied to the MAC multicast group base address. -+ * -+ * This method allows access to the underlying MAC multicast group base -+ * address. It is expected that in most cases, a net device client will -+ * allow the net device to perform the actual construction of the multicast -+ * address. Use of this method is discouraged unless you have a good reason -+ * to perform a custom mapping. You should prefer -+ * NetDevice::MakeMulticastAddress which will do the RFC-specified mapping -+ * for the net device in question. -+ * -+ * \return The multicast address supported by this net device. -+ * -+ * \warning Calling this method is invalid if IsMulticast returns not true. -+ * The method NS_ASSERTs if the device is not a multicast device. -+ * \see NetDevice::MakeMulticastAddress -+ */ -+ Address GetMulticast (void) const; -+ -+ /** -+ * \brief Make and return a MAC multicast address using the provided -+ * multicast group -+ * -+ * RFC 1112 says that an Ipv4 host group address is mapped to an Ethernet -+ * multicast address by placing the low-order 23-bits of the IP address into -+ * the low-order 23 bits of the Ethernet multicast address -+ * 01-00-5E-00-00-00 (hex). Similar RFCs exist for Ipv6 and Eui64 mappings. -+ * This method performs the multicast address creation function appropriate -+ * to the underlying MAC address of the device. This MAC address is -+ * encapsulated in an abstract Address to avoid dependencies on the exact -+ * MAC address format. -+ * -+ * A default imlementation of MakeMulticastAddress is provided, but this -+ * method simply NS_ASSERTS. In the case of net devices that do not support -+ * multicast, clients are expected to test NetDevice::IsMulticast and avoid -+ * attempting to map multicast packets. Subclasses of NetDevice that do -+ * support multicasting are expected to override this method and provide an -+ * implementation appropriate to the particular device. -+ * -+ * \param multicastGroup The IP address for the multicast group destination -+ * of the packet. -+ * \return The MAC multicast Address used to send packets to the provided -+ * multicast group. -+ * -+ * \warning Calling this method is invalid if IsMulticast returns not true. -+ * \see Ipv4Address -+ * \see Address -+ * \see NetDevice::IsMulticast -+ */ -+ virtual Address MakeMulticastAddress (Ipv4Address multicastGroup) const; - - /** - * \return value of m_isPointToPoint flag - -changeset: 1316:7c81b4e2617d -user: Craig Dowell -date: Tue Sep 04 14:38:40 2007 -0700 -summary: piles of doxygen, changes to SetDefaultMulticastRoute plumbing - -diff -r 580ed7a4dd1e -r 7c81b4e2617d src/internet-node/ipv4-impl.cc ---- a/src/internet-node/ipv4-impl.cc Wed Aug 29 12:11:11 2007 -0700 -+++ b/src/internet-node/ipv4-impl.cc Tue Sep 04 14:38:40 2007 -0700 -@@ -106,13 +106,9 @@ Ipv4Impl::AddMulticastRoute (Ipv4Address - } - - void --Ipv4Impl::SetDefaultMulticastRoute (Ipv4Address origin, -- Ipv4Address group, -- uint32_t inputInterface, -- std::vector outputInterfaces) --{ -- m_ipv4->SetDefaultMulticastRoute (origin, group, inputInterface, -- outputInterfaces); -+Ipv4Impl::SetDefaultMulticastRoute (uint32_t outputInterface) -+{ -+ m_ipv4->SetDefaultMulticastRoute (outputInterface); - } - - uint32_t -diff -r 580ed7a4dd1e -r 7c81b4e2617d src/internet-node/ipv4-impl.h ---- a/src/internet-node/ipv4-impl.h Wed Aug 29 12:11:11 2007 -0700 -+++ b/src/internet-node/ipv4-impl.h Tue Sep 04 14:38:40 2007 -0700 -@@ -62,9 +62,7 @@ public: - uint32_t inputInterface, - std::vector outputInterfaces); - -- virtual void SetDefaultMulticastRoute (Ipv4Address origin, -- Ipv4Address group, uint32_t inputInterface, -- std::vector outputInterfaces); -+ virtual void SetDefaultMulticastRoute (uint32_t outputInterface); - - virtual uint32_t GetNMulticastRoutes (void) const; - virtual Ipv4MulticastRoute GetMulticastRoute (uint32_t i) const; -diff -r 580ed7a4dd1e -r 7c81b4e2617d src/internet-node/ipv4-l3-protocol.cc ---- a/src/internet-node/ipv4-l3-protocol.cc Wed Aug 29 12:11:11 2007 -0700 -+++ b/src/internet-node/ipv4-l3-protocol.cc Tue Sep 04 14:38:40 2007 -0700 -@@ -356,17 +356,12 @@ Ipv4L3Protocol::AddMulticastRoute (Ipv4A - } - - void --Ipv4L3Protocol::SetDefaultMulticastRoute ( -- Ipv4Address origin, -- Ipv4Address group, -- uint32_t inputInterface, -- std::vector outputInterfaces) --{ -- NS_DEBUG("Ipv4L3Protocol::SetDefaultMulticastRoute (" << origin << ", " << -- group << ", " << inputInterface << ", " << &outputInterfaces << ")"); -- -- m_staticRouting->SetDefaultMulticastRoute (origin, group, inputInterface, -- outputInterfaces); -+Ipv4L3Protocol::SetDefaultMulticastRoute (uint32_t outputInterface) -+{ -+ NS_DEBUG("Ipv4L3Protocol::SetDefaultMulticastRoute (" << outputInterface << -+ ")"); -+ -+ m_staticRouting->SetDefaultMulticastRoute (outputInterface); - } - - uint32_t -diff -r 580ed7a4dd1e -r 7c81b4e2617d src/internet-node/ipv4-l3-protocol.h ---- a/src/internet-node/ipv4-l3-protocol.h Wed Aug 29 12:11:11 2007 -0700 -+++ b/src/internet-node/ipv4-l3-protocol.h Tue Sep 04 14:38:40 2007 -0700 -@@ -163,10 +163,7 @@ public: - uint32_t inputInterface, - std::vector outputInterfaces); - -- void SetDefaultMulticastRoute (Ipv4Address origin, -- Ipv4Address group, -- uint32_t inputInterface, -- std::vector outputInterfaces); -+ void SetDefaultMulticastRoute (uint32_t onputInterface); - - uint32_t GetNMulticastRoutes (void) const; - Ipv4MulticastRoute *GetMulticastRoute (uint32_t i) const; -diff -r 580ed7a4dd1e -r 7c81b4e2617d src/internet-node/ipv4-static-routing.cc ---- a/src/internet-node/ipv4-static-routing.cc Wed Aug 29 12:11:11 2007 -0700 -+++ b/src/internet-node/ipv4-static-routing.cc Tue Sep 04 14:38:40 2007 -0700 -@@ -101,15 +101,19 @@ Ipv4StaticRouting::AddMulticastRoute(Ipv - } - - void --Ipv4StaticRouting::SetDefaultMulticastRoute( -- Ipv4Address origin, -- Ipv4Address group, -- uint32_t inputInterface, -- std::vector outputInterfaces) --{ -+Ipv4StaticRouting::SetDefaultMulticastRoute(uint32_t outputInterface) -+{ -+ Ipv4Address origin = Ipv4Address::GetAny (); -+ Ipv4Address group = Ipv4Address::GetAny (); -+ uint32_t inputInterface = Ipv4RoutingProtocol::IF_INDEX_ANY; -+ -+ std::vector outputInterfaces (1); -+ outputInterfaces[0] = outputInterface; -+ - Ipv4MulticastRoute *route = new Ipv4MulticastRoute (); - *route = Ipv4MulticastRoute::CreateMulticastRoute (origin, group, - inputInterface, outputInterfaces); -+ - delete m_defaultMulticastRoute; - m_defaultMulticastRoute = route; - } -@@ -177,7 +181,7 @@ Ipv4StaticRouting::GetDefaultMulticastRo - return 0; - } - --void -+bool - Ipv4StaticRouting::RemoveMulticastRoute(Ipv4Address origin, - Ipv4Address group, - uint32_t inputInterface) -@@ -196,9 +200,10 @@ Ipv4StaticRouting::RemoveMulticastRoute( - { - delete *i; - m_multicastRoutes.erase (i); -- return; -- } -- } -+ return true; -+ } -+ } -+ return false; - } - - void -diff -r 580ed7a4dd1e -r 7c81b4e2617d src/internet-node/ipv4-static-routing.h ---- a/src/internet-node/ipv4-static-routing.h Wed Aug 29 12:11:11 2007 -0700 -+++ b/src/internet-node/ipv4-static-routing.h Tue Sep 04 14:38:40 2007 -0700 -@@ -45,57 +45,418 @@ class TraceContext; - class TraceContext; - - -+/** -+ * @brief Static routing protocol for IP version 4 stacks. -+ * -+ * In ns-3 we have the concept of a pluggable routing protocol. Routing -+ * protocols are added to a list maintained by the Ipv4L3Protocol. Every -+ * stack gets one routing protocol for free -- the Ipv4StaticRouting routing -+ * protocol is added in the constructor of the Ipv4L3Protocol (this is the -+ * piece of code that implements the functionality of the IP layer). -+ * -+ * The Ipv4StaticRouting class inherits from the abstract base class -+ * Ipv4RoutingProtocol that defines the interface methods that a routing -+ * protocol must support. -+ * -+ * When a packet arrives in the Ipv4L3Protocol for transmission, it comes -+ * either from a local source via Ipv4L3Protocol::Send or from a remote -+ * source via Ipv4L3Protocol::Forwarding. In both cases, a function is called -+ * (Ipv4L3Protocol::Lookup) to look up the routing information for the packet. -+ * -+ * The lookup function iterates through the list of routing protocols asking -+ * each to see if it can find a route and send the packet. A callback is -+ * provided during each of these calls that should be considered a pre- -+ * packaged send call. This is done to allow asynchronous calls into -+ * routing subsystems in order to support on-demand routing, for example. The -+ * method for requesting this operation is Ipv4StaticRouting::RequestRoute for -+ * the static routing protocol. -+ * -+ * Each routing protocol is also free to implement its own methods for managing -+ * routes which you will find below. This class manages a set of "static" or -+ * manually configured routes for host, network and multicast routes. -+ * -+ * @see Ipv4RoutingProtocol -+ * @see Ipv4L3Protocol::AddRoutingProtocol -+ * @see Ipv4L3Protocol::Ipv4L3Protocol -+ */ - class Ipv4StaticRouting : public Ipv4RoutingProtocol - { -- - public: -+/** -+ * @brief Construct an empty Ipv4StaticRouting routing protocol, -+ * @internal -+ * -+ * The Ipv4StaticRouting class supports host, network and multicast routes. -+ * This method initializes the lists containing these routes to empty. -+ * -+ * @see Ipv4StaticRouting -+ */ - Ipv4StaticRouting (); - -+/** -+ * @brief Request that a check for a route bw performed and if a route is found -+ * that the packet be sent on its way using the pre-packaged send callback. -+ * -+ * The source and destination IP addresses for the packet in question are found -+ * in the provided Ipv4Header. There are two major processing forks depending -+ * on the type of destination address. -+ * -+ * If the destination address is unicast then the routing table is consulted -+ * for a route to the destination and if it is found, the routeReply callback -+ * is executed to send the packet (with the found route). -+ * -+ * If the destination address is a multicast, then the exact processing steps -+ * depend on whether or not the packet has been sourced locally. This is -+ * determined by the parameter ifIndex. This is the interface index over which -+ * this packet was received. If the packet has not been received over a -+ * network interface, this index will be set to -+ * Ipv4RoutingProtocol::IF_INDEX_ANY (a very large number). In that case, -+ * we want to avoid the requirement that an explicit route out of each node -+ * must be set, so we don't do anything here. -+ * -+ * If the packet is a multicast destination and has been received over a -+ * network interface, a call to this method implies that the packet is being -+ * forwarded. In that case, there must be an explicit route out of the node. -+ * A multicast route references the source address, the destination address -+ * (the multicast group) and the input interface in order to find a route. -+ * We consult the multicast routing table and, if a route is found, send the -+ * packet out of as many interfaces as required using the provided callback -+ * (think of it as a pre-packaged send call). -+ * -+ * @param ifIndex The network interface index over which the packed was -+ * received. If the packet is from a local source, ifIndex will be set to -+ * Ipv4RoutingProtocol::IF_INDEX_ANY. -+ * @param ipHeader the Ipv4Header containing the source and destination IP -+ * addresses for the packet. -+ * @param packet The packet to be sent if a route is found. -+ * @param routeReply A callback that packaged up the call to actually send the -+ * packet. -+ * @return Returns true if a route is found and the packet has been sent, -+ * otherwise returns false indicating that the next routing protocol should -+ * be consulted. In practice, the static routing protocol is the last chance -+ * protocol. -+ * -+ * @see Ipv4StaticRouting -+ * @see Ipv4RoutingProtocol -+ */ - virtual bool RequestRoute (uint32_t ifIndex, - Ipv4Header const &ipHeader, - Packet packet, - RouteReplyCallback routeReply); - -+/** -+ * @brief Check to see if we can determine the interface index that will be -+ * used if a packet is sent to this destination. -+ * -+ * This method addresses a problem in the IP stack where a destination address -+ * must be present and checksummed into the IP header before the actual -+ * interface over which the packet is sent can be determined. The answer is -+ * to implement a known and intentional cross-layer violation. This is the -+ * endpoint of a call chain that started up quite high in the stack (sockets) -+ * and has found its way down to the Ipv4L3Protocol which is consulting the -+ * routing protocols for what they would do if presented with a packet of the -+ * given destination. -+ * -+ * Note that the a single interface index is returned. This means that if -+ * the destination address is a multicast, and an explicit route is present -+ * that includeds multiple output interfaces, that route cannot be used. -+ * -+ * If there are multiple paths out of the node, the resolution is performed -+ * by Ipv4L3Protocol::GetIfIndexforDestination which has access to more -+ * contextual information that is useful for making a determination. -+ * -+ * @param destination The Ipv4Address if the destination of a hypothetical -+ * packet. This may be a multicast group address. -+ * @param ifIndex A reference to the interface index over which a packet -+ * sent to this destination would be sent. -+ * @return Returns true if a route is found to the destination that involves -+ * a single output interface index, otherwise returns false indicating that -+ * the next routing protocol should be consulted. In practice, the static -+ * routing protocol is the last chance protocol. -+ * -+ * @see Ipv4StaticRouting -+ * @see Ipv4RoutingProtocol -+ * @see Ipv4L3Protocol -+ */ - virtual bool RequestIfIndex (Ipv4Address destination, uint32_t& ifIndex); - -+/** -+ * @brief Add a host route to the static routing table. -+ * -+ * @param dest The Ipv4Address destination for this route. -+ * @param nextHop The Ipv4Address of the next hop in the route. -+ * @param interface The network interface index used to send packets to the -+ * destination. -+ * -+ * @see Ipv4Address -+ */ - void AddHostRouteTo (Ipv4Address dest, - Ipv4Address nextHop, - uint32_t interface); -+/** -+ * @brief Add a host route to the static routing table. -+ * -+ * @param dest The Ipv4Address destination for this route. -+ * @param interface The network interface index used to send packets to the -+ * destination. -+ * -+ * @see Ipv4Address -+ */ - void AddHostRouteTo (Ipv4Address dest, - uint32_t interface); - -+/** -+ * @brief Add a network route to the static routing table. -+ * -+ * @param network The Ipv4Address network for this route. -+ * @param networkmask The Ipv4Mask to extract the network. -+ * @param nextHop The next hop in the route to the destination network. -+ * @param interface The network interface index used to send packets to the -+ * destination. -+ * -+ * @see Ipv4Address -+ */ - void AddNetworkRouteTo (Ipv4Address network, - Ipv4Mask networkMask, - Ipv4Address nextHop, - uint32_t interface); -+ -+/** -+ * @brief Add a network route to the static routing table. -+ * -+ * @param network The Ipv4Address network for this route. -+ * @param networkmask The Ipv4Mask to extract the network. -+ * @param interface The network interface index used to send packets to the -+ * destination. -+ * -+ * @see Ipv4Address -+ */ - void AddNetworkRouteTo (Ipv4Address network, - Ipv4Mask networkMask, - uint32_t interface); -+ -+/** -+ * @brief Add a default route to the static routing table. -+ * -+ * This method tells the routing system what to do in the case where a specific -+ * route to a destination is not found. The system forwards packets to the -+ * specified node in the hope that it knows better how to route the packet. -+ * -+ * If the default route is set, it is returned as the selected route from -+ * LookupStatic irrespective of destination address if no specific route is -+ * found. -+ * -+ * @param nextHop The Ipv4Address to send packets to in the hope that they -+ * will be forwarded correctly. -+ * @param interface The network interface index used to send packets. -+ * -+ * @see Ipv4Address -+ * @see Ipv4StaticRouting::Lookup -+ */ - void SetDefaultRoute (Ipv4Address nextHop, - uint32_t interface); -+ -+/** -+ * @brief Get the number of individual unicast routes that have been added -+ * to the routing table. -+ * -+ * @warning The default route counts as one of the routes. -+ */ - uint32_t GetNRoutes (void); -+ -+/** -+ * @brief Get the default route from the static routing table. -+ * -+ * @return If the default route is set, a pointer to that Ipv4Route is -+ * returned, otherwise a zero pointer is returned. -+ * -+ * @see Ipv4Route -+ */ - Ipv4Route *GetDefaultRoute (void); -+ -+/** -+ * @brief Get a route from the static unicast routing table. -+ * -+ * Externally, the unicast static routing table appears simply as a table with -+ * n entries. The one sublety of note is that if a default route has been set -+ * it will appear as the zeroth entry in the table. This means that if you -+ * add only a default route, the table will have one entry that can be accessed -+ * either by explicity calling GetDefaultRoute () or by calling GetRoute (0). -+ * -+ * Similarly, if the default route has been set, calling RemoveRoute (0) will -+ * remove the default route. -+ * -+ * @param i The index (into the routing table) of the route to retrieve. If -+ * the default route has been set, it will occupy index zero. -+ * @return If route is set, a pointer to that Ipv4Route is returned, otherwise -+ * a zero pointer is returned. -+ * -+ * @see Ipv4Route -+ * @see Ipv4StaticRouting::RemoveRoute -+ */ - Ipv4Route *GetRoute (uint32_t i); -+ -+/** -+ * @brief Remove a route from the static unicast routing table. -+ * -+ * Externally, the unicast static routing table appears simply as a table with -+ * n entries. The one sublety of note is that if a default route has been set -+ * it will appear as the zeroth entry in the table. This means that if the -+ * default route has been set, calling RemoveRoute (0) will remove the -+ * default route. -+ * -+ * @param i The index (into the routing table) of the route to remove. If -+ * the default route has been set, it will occupy index zero. -+ * -+ * @see Ipv4Route -+ * @see Ipv4StaticRouting::GetRoute -+ * @see Ipv4StaticRouting::AddRoute -+ */ - void RemoveRoute (uint32_t i); - -+/** -+ * @brief Add a multicast route to the static routing table. -+ * -+ * A multicast route must specify an origin IP address -- the address of the -+ * node that originates packets destined for a given multicast group. This -+ * address may be Ipv4Address::GetAny (typically 0.0.0.0) if the multicast -+ * group is open, or it may specify a single IP address if the multicast -+ * group is closed. The route must also specify the multicast group address. -+ * -+ * For each route, the input nework interface must be specified. For -+ * forwarding operations, this is the interface index that you expect multicast -+ * packets to arrive over. If you want to specify routes off of a local node -+ * for given multicast groups, this index may be set to -+ * Ipv4RoutingProtocol::IF_INDEX_ANY. -+ * -+ * For each route, a vector of output network interfaces must also be -+ * specified. When the RequestRoute operation is performed, copies of a -+ * packet are sent out all of the specified interfaces. -+ * -+ * @param origin The Ipv4Address of the origin of packets for this route. May -+ * be Ipv4Address:GetAny for open groups. -+ * @param group The Ipv4Address of the multicast group or this route. -+ * @param inputInterface The input network interface index over which to -+ * expect packets destined for this route. May be -+ * Ipv4RoutingProtocol::IF_INDEX_ANY for packets of local origin. -+ * @param outputInterface A vector of network interface indices used to specify -+ * how to send packets to the destination(s). -+ * -+ * @see Ipv4Address -+ */ - void AddMulticastRoute (Ipv4Address origin, - Ipv4Address group, - uint32_t inputInterface, - std::vector outputInterfaces); - -- void SetDefaultMulticastRoute (Ipv4Address origin, -- Ipv4Address group, -- uint32_t inputInterface, -- std::vector outputInterfaces); -- -+/** -+ * @brief Add a default multicast route to the static routing table. -+ * -+ * This is the multicast equivalent of the unicast version SetDefaultRoute. -+ * We tell the routing system what to do in the case where a specific route -+ * to a destination multicast group is not found. The system forwards -+ * packets out the specified interface in the hope that "something out there" -+ * knows better how to route the packet. -+ * -+ * Since we're basically forwarding packets to some entity we think may know -+ * better what to do, we don't pay attention to subleties like origin address -+ * and input interface, nor do we worry about forwarding out multiple -+ * interfaces. If the default multicast route is set, it is returned as the -+ * selected route from LookupStatic irrespective of origin, multicast group or -+ * input interface if another specific route is not found. -+ * -+ * @param outputInterface The network interface index used to specify where -+ * to send packets in the case of unknown routes. -+ * -+ * @see Ipv4Address -+ */ -+ void SetDefaultMulticastRoute (uint32_t outputInterface); -+ -+/** -+ * @brief Get the number of individual multicast routes that have been added -+ * to the routing table. -+ * -+ * @warning The default multicast route counts as one of the routes. -+ */ - uint32_t GetNMulticastRoutes (void) const; -+ -+/** -+ * @brief Get a route from the static multicast routing table. -+ * -+ * Externally, the multicast static routing table appears simply as a table -+ * with n entries. The one sublety of note is that if a default route has -+ * been set it will appear as the zeroth entry in the table. This means that -+ * if you add only a default route, the table will have one entry that can be -+ * accessed either by explicity calling GetDefaultMulticastRoute () or by -+ * calling GetMulticastRoute (0). -+ * -+ * Similarly, if the default route has been set, calling -+ * RemoveMulticastRoute (0) will remove the default route. -+ * -+ * @param i The index (into the routing table) of the multicast route to -+ * retrieve. If the default route has been set, it will occupy index zero. -+ * @return If route is set, a pointer to that Ipv4MulticastRoute is -+ * returned, otherwise a zero pointer is returned. -+ * -+ * @see Ipv4MulticastRoute -+ * @see Ipv4StaticRouting::RemoveRoute -+ */ - Ipv4MulticastRoute *GetMulticastRoute (uint32_t i) const; -+ -+/** -+ * @brief Get the default multicast route from the static routing table. -+ * -+ * @return If the default route is set, a pointer to that Ipv4MulticastRoute is -+ * returned, otherwise a zero pointer is returned. -+ * -+ * @see Ipv4Route -+ */ - Ipv4MulticastRoute *GetDefaultMulticastRoute (void) const; - -- void RemoveMulticastRoute (Ipv4Address origin, -+/** -+ * @brief Remove a route from the static multicast routing table. -+ * -+ * Externally, the multicast static routing table appears simply as a table -+ * with n entries. The one sublety of note is that if a default multicast -+ * route has been set it will appear as the zeroth entry in the table. This -+ * means that the default route may be removed by calling this method with -+ * appropriate wildcard parameters. -+ * -+ * This method causes the multicast routing table to be searched for the first -+ * route that matches the parameters and removes it. -+ * -+ * @param origin The IP address specified as the origin of packets for the -+ * route. -+ * @param origin The IP address specified as the multicast group addres of -+ * the route. -+ * @param inputInterfade The network interface index specified as the expected -+ * input interface for the route. -+ * @returns True if a route was found and removed, false otherwise. -+ * -+ * @see Ipv4Route -+ * @see Ipv4StaticRouting::GetRoute -+ * @see Ipv4StaticRouting::AddRoute -+ */ -+ bool RemoveMulticastRoute (Ipv4Address origin, - Ipv4Address group, - uint32_t inputInterface); - -+/** -+ * @brief Remove a route from the static multicast routing table. -+ * -+ * Externally, the multicast static routing table appears simply as a table -+ * with n entries. The one sublety of note is that if a default multicast -+ * route has been set it will appear as the zeroth entry in the table. This -+ * means that if the default route has been set, calling -+ * RemoveMulticastRoute (0) will remove the default route. -+ * -+ * @param index The index (into the multicast routing table) of the route to -+ * remove. If the default route has been set, it will occupy index zero. -+ * -+ * @see Ipv4Route -+ * @see Ipv4StaticRouting::GetRoute -+ * @see Ipv4StaticRouting::AddRoute -+ */ - void RemoveMulticastRoute (uint32_t index); - - protected: -diff -r 580ed7a4dd1e -r 7c81b4e2617d src/node/ipv4.h ---- a/src/node/ipv4.h Wed Aug 29 12:11:11 2007 -0700 -+++ b/src/node/ipv4.h Tue Sep 04 14:38:40 2007 -0700 -@@ -104,14 +104,38 @@ public: - const Ipv4Header &ipHeader, - Packet packet, - RouteReplyCallback routeReply) = 0; -- /** -- * \brief Synchronously request the interface index that will be used to -- * send a packet to a hypothetical destination. -- * -- * \param destination IP address of a hypothetical destination packet -- * \param ifIndex Reference to interface index. -- * \returns True if the protocol has a route, false otherwise. -- */ -+/** -+ * \brief Synchronously check to see if we can determine the interface index -+ * that will be used if a packet is sent to this destination. -+ * -+ * This method addresses a problem in the IP stack where a destination address -+ * must be present and checksummed into the IP header before the actual -+ * interface over which the packet is sent can be determined. The answer is -+ * to implement a known and intentional cross-layer violation. This is the -+ * endpoint of a call chain that started up quite high in the stack (sockets) -+ * and has found its way down to the Ipv4L3Protocol which is consulting the -+ * routing protocols for what they would do if presented with a packet of the -+ * given destination. -+ * -+ * Note that the a single interface index is returned. This means that if -+ * the destination address is a multicast, and an explicit route is present -+ * that includeds multiple output interfaces, that route cannot be used. -+ * -+ * If there are multiple paths out of the node, the resolution is performed -+ * by Ipv4L3Protocol::GetIfIndexforDestination which has access to more -+ * contextual information that is useful for making a determination. -+ * -+ * \param destination The Ipv4Address if the destination of a hypothetical -+ * packet. This may be a multicast group address. -+ * \param ifIndex A reference to the interface index over which a packet -+ * sent to this destination would be sent. -+ * \return Returns true if a route is found to the destination that involves -+ * a single output interface index, otherwise false. -+ * -+ * \see Ipv4StaticRouting -+ * \see Ipv4RoutingProtocol -+ * \see Ipv4L3Protocol -+ */ - virtual bool RequestIfIndex (Ipv4Address destination, - uint32_t& ifIndex) = 0; - -@@ -207,11 +231,13 @@ public: - * \returns the number of entries in the routing table. - */ - virtual uint32_t GetNRoutes (void) = 0; -+ - /** - * \param i index of route to return - * \returns the route whose index is i - */ - virtual Ipv4Route GetRoute (uint32_t i) = 0; -+ - /** - * \param i index of route to remove from routing table. - */ -@@ -244,18 +270,13 @@ public: - uint32_t inputInterface) = 0; - - /** -- * \brief Set the default static multicast route for a given multicast -- * source and group. -- * -- * \param origin The Ipv4 address of the multicast source. -- * \param group The multicast group address. -- * \param inputInterface The interface index over which the packet arrived. -- * \param outputInterfaces The list of output interface indices over which -- * the packet should be sent (excluding the inputInterface). -- */ -- virtual void SetDefaultMulticastRoute (Ipv4Address origin, -- Ipv4Address group, uint32_t inputInterface, -- std::vector outputInterfaces) = 0; -+ * \brief Set the default static multicast route. -+ * -+ * \param outputInterface The network output interface index over which -+ * packets without specific routes should be sent. -+ */ -+ virtual void SetDefaultMulticastRoute (uint32_t outputInterface) = 0; -+ - /** - * \returns the number of entries in the multicast routing table. - */ -@@ -282,6 +303,7 @@ public: - * make sure that it is never used during packet forwarding. - */ - virtual uint32_t AddInterface (Ptr device) = 0; -+ - /** - * \returns the number of interfaces added by the user. - */ -@@ -346,39 +368,46 @@ public: - * \param address address to associate to the underlying ipv4 interface - */ - virtual void SetAddress (uint32_t i, Ipv4Address address) = 0; -+ - /** - * \param i index of ipv4 interface - * \param mask mask to associate to the underlying ipv4 interface - */ - virtual void SetNetworkMask (uint32_t i, Ipv4Mask mask) = 0; -+ - /** - * \param i index of ipv4 interface - * \returns the mask associated to the underlying ipv4 interface - */ - virtual Ipv4Mask GetNetworkMask (uint32_t i) const = 0; -+ - /** - * \param i index of ipv4 interface - * \returns the address associated to the underlying ipv4 interface - */ - virtual Ipv4Address GetAddress (uint32_t i) const = 0; -+ - /** - * \param destination The IP address of a hypothetical destination. - * \returns The IP address assigned to the interface that will be used - * if we were to send a packet to destination. - */ - virtual Ipv4Address GetSourceAddress (Ipv4Address destination) const = 0; -+ - /** - * \param i index of ipv4 interface - * \returns the Maximum Transmission Unit (in bytes) associated - * to the underlying ipv4 interface - */ - virtual uint16_t GetMtu (uint32_t i) const = 0; -+ - /** - * \param i index of ipv4 interface - * \returns true if the underlying interface is in the "up" state, - * false otherwise. - */ - virtual bool IsUp (uint32_t i) const = 0; -+ - /** - * \param i index of ipv4 interface - * -@@ -386,6 +415,7 @@ public: - * considered valid during ipv4 forwarding. - */ - virtual void SetUp (uint32_t i) = 0; -+ - /** - * \param i index of ipv4 interface - * -@@ -393,7 +423,6 @@ public: - * ignored during ipv4 forwarding. - */ - virtual void SetDown (uint32_t i) = 0; -- - }; - - } // namespace ns3 - -changeset: 1317:3fba36666488 -user: Craig Dowell -date: Tue Sep 04 15:10:47 2007 -0700 -summary: Don't flood multicasts if no route found - -diff -r 7c81b4e2617d -r 3fba36666488 src/internet-node/ipv4-l3-protocol.cc ---- a/src/internet-node/ipv4-l3-protocol.cc Tue Sep 04 14:38:40 2007 -0700 -+++ b/src/internet-node/ipv4-l3-protocol.cc Tue Sep 04 15:10:47 2007 -0700 -@@ -284,29 +284,29 @@ Ipv4L3Protocol::Lookup ( - NS_DEBUG ("Ipv4L3Protocol::Lookup (): " - "Multicast destination with local source"); - // --// We have a multicast packet originating from the current node. We didn't --// want to force users to construct a route in order to get packets out of a --// node, so there will have been no route found and it is left to us to send --// the packet. What we'll do is to send the multicast out all of the --// interfaces on this node. Note that we start with interface 1 since we --// don't particularly want to send the packet out the loopback. --// -- NS_DEBUG ("Ipv4StaticRouting::Lookup (): " -- "Local source. Flooding multicast packet"); -- -- for (uint32_t i = 1; i < GetNInterfaces (); ++i) -- { -- Packet p = packet; -- Ipv4Header h = ipHeader; -- Ipv4Route route = -- Ipv4Route::CreateHostRouteTo(h.GetDestination (), i); -+// We have a multicast packet originating from the current node and were not -+// able to send it using the usual RequestRoute process. Since the usual -+// process includes trying to use a default multicast route, this means that -+// there was no specific route out of the node found, and there was no default -+// multicast route set. -+// -+// The fallback position is to look for a default unicast route and use that -+// to get the packet off the node if we have one. -+// -+ Ipv4Route *route = m_staticRouting->GetDefaultRoute (); -+ -+ if (route) -+ { - NS_DEBUG ("Ipv4StaticRouting::Lookup (): " -- "Send via interface " << i); -- routeReply (true, route, p, h); -- } -- return; -- } -- // No route found -+ "Local source. Using unicast default route for multicast packet"); -+ -+ routeReply (true, *route, packet, ipHeader); -+ return; -+ } -+ } -+// -+// No route found -+// - routeReply (false, Ipv4Route (), packet, ipHeader); - } - -diff -r 7c81b4e2617d -r 3fba36666488 src/node/ipv4-route.cc ---- a/src/node/ipv4-route.cc Tue Sep 04 14:38:40 2007 -0700 -+++ b/src/node/ipv4-route.cc Tue Sep 04 15:10:47 2007 -0700 -@@ -30,11 +30,19 @@ namespace ns3 { - - Ipv4Route::Ipv4Route () - {} -+ - Ipv4Route::Ipv4Route (Ipv4Route const &route) - : m_dest (route.m_dest), - m_destNetworkMask (route.m_destNetworkMask), - m_gateway (route.m_gateway), - m_interface (route.m_interface) -+{} -+ -+Ipv4Route::Ipv4Route (Ipv4Route const *route) -+ : m_dest (route->m_dest), -+ m_destNetworkMask (route->m_destNetworkMask), -+ m_gateway (route->m_gateway), -+ m_interface (route->m_interface) - {} - - Ipv4Route::Ipv4Route (Ipv4Address dest, -@@ -236,6 +244,15 @@ Ipv4MulticastRoute::Ipv4MulticastRoute ( - { - } - -+Ipv4MulticastRoute::Ipv4MulticastRoute (Ipv4MulticastRoute const *route) -+: -+ m_origin (route->m_origin), -+ m_group (route->m_group), -+ m_inputInterface (route->m_inputInterface), -+ m_outputInterfaces (route->m_outputInterfaces) -+{ -+} -+ - Ipv4MulticastRoute::Ipv4MulticastRoute ( - Ipv4Address origin, - Ipv4Address group, -diff -r 7c81b4e2617d -r 3fba36666488 src/node/ipv4-route.h ---- a/src/node/ipv4-route.h Tue Sep 04 14:38:40 2007 -0700 -+++ b/src/node/ipv4-route.h Tue Sep 04 15:10:47 2007 -0700 -@@ -37,11 +37,18 @@ public: - * \brief This constructor does nothing - */ - Ipv4Route (); -+ - /** - * \brief Copy Constructor - * \param route The route to copy - */ - Ipv4Route (Ipv4Route const &route); -+ -+ /** -+ * \brief Copy Constructor -+ * \param route The route to copy -+ */ -+ Ipv4Route (Ipv4Route const *route); - - bool IsHost (void) const; - /** -@@ -108,11 +115,18 @@ public: - * \brief This constructor does nothing - */ - Ipv4MulticastRoute (); -+ - /** - * \brief Copy Constructor - * \param route The route to copy - */ - Ipv4MulticastRoute (Ipv4MulticastRoute const &route); -+ -+ /** -+ * \brief Copy Constructor -+ * \param route The route to copy -+ */ -+ Ipv4MulticastRoute (Ipv4MulticastRoute const *route); - - /** - * \return The IPv4 address of the source of this route - -changeset: 1318:f9bc98cbe5fe -user: Craig Dowell -date: Tue Sep 04 18:06:06 2007 -0700 -summary: clarify use of wildcards in multicast routes versus default mulicast routes. - -diff -r 3fba36666488 -r f9bc98cbe5fe examples/csma-multicast.cc ---- a/examples/csma-multicast.cc Tue Sep 04 15:10:47 2007 -0700 -+++ b/examples/csma-multicast.cc Tue Sep 04 18:06:06 2007 -0700 -@@ -221,8 +221,8 @@ main (int argc, char *argv[]) - Ptr ipv4; - ipv4 = n2->QueryInterface (Ipv4::iid); - -- uint32_t ifIndexLan0 = ipv4->FindInterfaceForAddr(n2Lan0Addr); -- uint32_t ifIndexLan1 = ipv4->FindInterfaceForAddr(n2Lan1Addr); -+ uint32_t ifIndexLan0 = ipv4->FindInterfaceForAddr (n2Lan0Addr); -+ uint32_t ifIndexLan1 = ipv4->FindInterfaceForAddr (n2Lan1Addr); - // - // Now, we need to do is to call the AddMulticastRoute () method on node - // two's Ipv4 interface and tell it that whenever it receives a packet on -@@ -237,6 +237,41 @@ main (int argc, char *argv[]) - - ipv4->AddMulticastRoute (multicastSource, multicastGroup, ifIndexLan0, - outputInterfaces); -+// -+// We need to specify how the source node handles multicasting. There are a -+// number of ways we can deal with this, we just need to pick one. The first -+// method is to add an explicit route out of the source node, just as we did -+// for the forwarding node. Use this method when you want to send packets out -+// multiple interfaces or send packets out different interfaces based on the -+// differing multicast groups. Since the source is local, there will be no -+// input interface over which packets are received, so use -+// Ipv4RoutingProtocol::IF_INDEX_ANY as a wildcard. -+// -+// A second way is to specify a multicast route using wildcards. If you -+// want to send multicasts out differing sets of interfaces based on the -+// multicast group, you can use AddMulticastRoute () but specify the origin -+// as a wildcard. If you want all multicasts to go out a single set of -+// interfaces, you can make both the origin and group a wildcard. -+// -+// If you have a simple system, where the source has a single interface, this -+// can be done via the SetDefaultMulticastRoute () method on the Ipv4 -+// interface. This tells the system to send all multicasts out a single -+// specified network interface index. -+// -+// A last way is to specify a (or use an existing) default unicast route. The -+// multicast routing code uses the unicast default route as a multicast "route -+// of last resort." this method for is also on Ipv4 and is called -+// SetDefaultRoute (). -+// -+// Since this is a simple multicast example, we use the -+// SetDefaultMulticastRoute () approach. We are going to first need the -+// Ipv4 interface for node 0 which is the multicast source. We use this -+// interface to find the output interface index, and tell node zero to send -+// its multicast traffic out that interface. -+// -+ ipv4 = n0->QueryInterface (Ipv4::iid); -+ uint32_t ifIndexSrc = ipv4->FindInterfaceForAddr (multicastSource); -+ ipv4->SetDefaultMulticastRoute (ifIndexSrc); - // - // As described above, node four will be the only node listening for the - // multicast data. To enable forwarding bits up the protocol stack, we need -diff -r 3fba36666488 -r f9bc98cbe5fe src/internet-node/ipv4-static-routing.cc ---- a/src/internet-node/ipv4-static-routing.cc Tue Sep 04 15:10:47 2007 -0700 -+++ b/src/internet-node/ipv4-static-routing.cc Tue Sep 04 18:06:06 2007 -0700 -@@ -289,14 +289,27 @@ Ipv4StaticRouting::LookupStatic ( - Ipv4Address group, - uint32_t ifIndex) - { -+// -+// We treat the "any" address (typically 0.0.0.0) as a wildcard in our matching -+// scheme. -+// -+ Ipv4Address wildcard = Ipv4Address::GetAny (); -+ - for (MulticastRoutesI i = m_multicastRoutes.begin (); - i != m_multicastRoutes.end (); - i++) - { - Ipv4MulticastRoute *route = *i; -- if ( (origin == route->GetOrigin () || -- origin == Ipv4Address::GetAny ()) && -- group == route->GetGroup ()) -+// -+// We've been passed an origin address, a multicast group address and an -+// interface index. We have to decide if the current route in the list is -+// a match. -+// -+// The first case is the restrictive case where the origin, group and index -+// matches. This picks up exact routes during forwarded and exact routes from -+// the local node (in which case the ifIndex is a wildcard). -+// -+ if (origin == route->GetOrigin () && group == route->GetGroup ()) - { - if (ifIndex == Ipv4RoutingProtocol::IF_INDEX_ANY || - ifIndex == route->GetInputInterface ()) -@@ -305,7 +318,67 @@ Ipv4StaticRouting::LookupStatic ( - } - } - } -- -+// -+// If the input interface index is not a wildcard (that means that the packet -+// did not originally come from this node), we're done. We don't -+// just happily forward packets we don't really know what to do with. -+// Multicast storms are not generally considered a good thing. -+// -+ if (ifIndex != Ipv4RoutingProtocol::IF_INDEX_ANY) -+ { -+ return 0; -+ } -+// -+// Now, we're going to get a litle less restricive. This only applies in the -+// case where the packet in question is coming from the local node. In order -+// to avoid dependencies on the order in which routes were added, we will -+// actually walk the list two more times, the first time looking for routes -+// with a single wildcard, and the last time looking for the first route -+// with two wildcards. -+// -+ for (MulticastRoutesI i = m_multicastRoutes.begin (); -+ i != m_multicastRoutes.end (); -+ i++) -+ { -+ Ipv4MulticastRoute *route = *i; -+// -+// Here we will ignore the origin. We know that a single source address must -+// be picked for a packet, but we may want to send multicast packets out -+// multiple interfaces. To support this case, a user would need to add -+// a Multicast route with the route's origin set to wildcard. N.B As a -+// result, packets sourced from a node with multiple interface may have a -+// source IP address different from that of the interface actually used to -+// send the packet. -+// -+ if (route->GetOrigin () == wildcard && group == route->GetGroup ()) -+ { -+ return *i; -+ } -+ } -+// -+// Finally we want to allow users to specify a default route that specifies -+// sending all multicast packets out multiple interfaces. The standard -+// default multicast route is patterned after other systems and limits the -+// number of outputs to one. If, however a client manually adds a multicast -+// route with the origin, the multicast group and the input interface index -+// all set to wildcard, she has created a default route with multiple output -+// interfaces. -+// -+ for (MulticastRoutesI i = m_multicastRoutes.begin (); -+ i != m_multicastRoutes.end (); -+ i++) -+ { -+ Ipv4MulticastRoute *route = *i; -+ -+ if (route->GetOrigin () == wildcard && route->GetGroup () == wildcard) -+ { -+ return *i; -+ } -+ } -+// -+// We also allow users to specify a typical default multicast route. This -+// default route is limited to specifying a single output interface. -+// - if (m_defaultMulticastRoute != 0) - { - return m_defaultMulticastRoute; -@@ -445,33 +518,7 @@ Ipv4StaticRouting::RequestRoute ( - if (ipHeader.GetDestination ().IsMulticast ()) - { - NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): Multicast destination"); --// --// We have a multicast packet we're going to send. There are two distinct --// cases we need to support. The first is if the current node is the source --// of the packet. In that case, we don't want to have to consult multicast --// routing tables (nor build them) in order to send multicasts. The interface --// index (ifIndex) is Ipv4RoutingProtocol::IF_INDEX_ANY if we're the source. --// --// The second case is if the current packet has gotten to us by being --// received over one of our interfaces. In this case, ifIndex is set to the --// index over which we received the packet. For these packets, we need to --// consult the multicast routing table for a disposition. --// --// So, first let's see if we're the source. In this case, we don't consult --// the routing tables, but just return false and let the caller (up in --// ipv4-l3-protocol) flood the multicast packet out of all of its interfaces. --// We can't really do it here even if we wanted to since we have no easy way --// to get to the Ipv4 interface which we would need. --// -- if (ifIndex == Ipv4RoutingProtocol::IF_INDEX_ANY) -- { -- return false; -- } --// --// If we fall through to this point, we have a multicast packet that has --// not originated at this node. We need to deal with forwarding. Let's --// see if we have a route, and if so go ahead and forward this puppy. --// -+ - Ipv4MulticastRoute *mRoute = LookupStatic(ipHeader.GetSource (), - ipHeader.GetDestination (), ifIndex); - -@@ -479,6 +526,7 @@ Ipv4StaticRouting::RequestRoute ( - { - NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): " - "Multicast route found"); -+ - for (uint32_t i = 0; i < mRoute->GetNOutputInterfaces (); ++i) - { - Packet p = packet; -@@ -495,7 +543,7 @@ Ipv4StaticRouting::RequestRoute ( - return false; // Let other routing protocols try to handle this - } - // --// See if this is a unicast packet we have a route for. -+// This is a unicast packet. Check to see if we have a route for it. - // - NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): Unicast destination"); - Ipv4Route *route = LookupStatic (ipHeader.GetDestination ()); -diff -r 3fba36666488 -r f9bc98cbe5fe src/internet-node/ipv4-static-routing.h ---- a/src/internet-node/ipv4-static-routing.h Tue Sep 04 15:10:47 2007 -0700 -+++ b/src/internet-node/ipv4-static-routing.h Tue Sep 04 18:06:06 2007 -0700 -@@ -317,21 +317,34 @@ public: - /** - * @brief Add a multicast route to the static routing table. - * -- * A multicast route must specify an origin IP address -- the address of the -- * node that originates packets destined for a given multicast group. This -- * address may be Ipv4Address::GetAny (typically 0.0.0.0) if the multicast -- * group is open, or it may specify a single IP address if the multicast -- * group is closed. The route must also specify the multicast group address. -- * -- * For each route, the input nework interface must be specified. For -- * forwarding operations, this is the interface index that you expect multicast -- * packets to arrive over. If you want to specify routes off of a local node -- * for given multicast groups, this index may be set to -- * Ipv4RoutingProtocol::IF_INDEX_ANY. -- * -- * For each route, a vector of output network interfaces must also be -- * specified. When the RequestRoute operation is performed, copies of a -- * packet are sent out all of the specified interfaces. -+ * A multicast route must specify an origin IP address, a multicast group and -+ * an input network interface index as conditions and provide a vector of -+ * output network interface indices over which packets matching the conditions -+ * are sent. -+ * -+ * Typically there are two main types of multicast routes: routes of the -+ * first kind are used during forwarding. All of the conditions must be -+ * exlicitly provided. The second kind of routes are used to get packets off -+ * of a local node. The difference is in the input interface. Routes for -+ * forwarding will always have an explicit input interface specified. Routes -+ * off of a node will always set the input interface to a wildcard specified -+ * by the index Ipv4RoutingProtocol::IF_INDEX_ANY. -+ * -+ * For routes off of a local node wildcards may be used in the origin and -+ * multicast group addresses. The wildcard used for Ipv4Adresses is that -+ * address returned by Ipv4Address::GetAny () -- typically "0.0.0.0". Usage -+ * of a wildcard allows one to specify default behavior to varying degrees. -+ * -+ * For example, making the origin address a wildcard, but leaving the -+ * multicast group specific allows one (in the case of a node with multiple -+ * interfaces) to create different routes using different output interfaces -+ * for each multicast group. -+ * -+ * If the origin and multicast addresses are made wildcards, you have created -+ * essentially a default multicast address that can forward to multiple -+ * interfaces. Compare this to the actual default multicast address that is -+ * limited to specifying a single output interface for compatibility with -+ * existing functionality in other systems. - * - * @param origin The Ipv4Address of the origin of packets for this route. May - * be Ipv4Address:GetAny for open groups. -@@ -425,6 +438,12 @@ public: - * This method causes the multicast routing table to be searched for the first - * route that matches the parameters and removes it. - * -+ * Wildcards may be provided to this function, but the wildcards are used to -+ * exacly match wildcards in the routes (see AddMulticastRoute). That is, -+ * calling RemoveMulticastRoute with the origin set to "0.0.0.0" will not -+ * remove routes with any address in the origin, but will only remove routes -+ * with "0.0.0.0" set as the the origin. -+ * - * @param origin The IP address specified as the origin of packets for the - * route. - * @param origin The IP address specified as the multicast group addres of -@@ -433,9 +452,8 @@ public: - * input interface for the route. - * @returns True if a route was found and removed, false otherwise. - * -- * @see Ipv4Route -- * @see Ipv4StaticRouting::GetRoute -- * @see Ipv4StaticRouting::AddRoute -+ * @see Ipv4MulticastRoute -+ * @see Ipv4StaticRouting::AddMulticastRoute - */ - bool RemoveMulticastRoute (Ipv4Address origin, - Ipv4Address group, - -changeset: 1319:f136fc719267 -tag: tip -user: Craig Dowell -date: Thu Sep 06 15:57:53 2007 -0700 -summary: readme file includes APIs - -diff -r f9bc98cbe5fe -r f136fc719267 README.multicast-routing ---- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/README.multicast-routing Thu Sep 06 15:57:53 2007 -0700 -@@ -0,0 +1,213 @@ -+Static multicast routing overview -+-------------------------------- -+ -+This is brief documentation of a proposal to add static multicast -+routing to ns-3. -+ -+This extension allows the simulation user to: -+ -+- manually add an Ipv4 multicast route to a router -+- specify a default outgoing interface for multicast sources (hosts) in -+ various ways -+- allow a multicast receiver (hosts) to join a multicast group, to enable -+ reception of that group's datagrams -+ -+1. Code location: -+ -+- http://code.nsnam.org/craigdo/ns-3-mc -+ -+- the main source code is found in src/internet-node/ipv4-static-routing.{cc,h} -+ -+also touched are: -+- src/internet-node/ipv4-l3-protocol.cc (forwarding methods for the -+ static routing API) -+- src/node/net-device.cc (provides virtual NetDevice::MakeMulticastAddress) -+- src/arp-ipv4-interface.cc (calls NetDevice::MakeMulticastAddress) -+- src/devices/csma/csma-net-device.cc (handles multicast addressing and -+ reception). -+- src/devices/point-to-point/point-to-point-net-device.cc (implements required -+ virtual methods. -+- src/internet-node/ (several files have added tracing) -+ -+- an example script is in examples/csma-multicast.cc -+ -+2. API: -+ -+The API for adding a multicast route is: -+ -+/** -+ * @brief Add a multicast route to the static routing table. -+ * -+ * A multicast route must specify an origin IP address, a multicast group and -+ * an input network interface index as conditions and provide a vector of -+ * output network interface indices over which packets matching the conditions -+ * are sent. -+ * -+ * Typically there are two main types of multicast routes: routes of the -+ * first kind are used during forwarding. All of the conditions must be -+ * exlicitly provided. The second kind of routes are used to get packets off -+ * of a local node. The difference is in the input interface. Routes for -+ * forwarding will always have an explicit input interface specified. Routes -+ * off of a node will always set the input interface to a wildcard specified -+ * by the index Ipv4RoutingProtocol::IF_INDEX_ANY. -+ * -+ * For routes off of a local node wildcards may be used in the origin and -+ * multicast group addresses. The wildcard used for Ipv4Adresses is that -+ * address returned by Ipv4Address::GetAny () -- typically "0.0.0.0". Usage -+ * of a wildcard allows one to specify default behavior to varying degrees. -+ * -+ * For example, making the origin address a wildcard, but leaving the -+ * multicast group specific allows one (in the case of a node with multiple -+ * interfaces) to create different routes using different output interfaces -+ * for each multicast group. -+ * -+ * If the origin and multicast addresses are made wildcards, you have created -+ * essentially a default multicast address that can forward to multiple -+ * interfaces. Compare this to the actual default multicast address that is -+ * limited to specifying a single output interface for compatibility with -+ * existing functionality in other systems. -+ * -+ * @param origin The Ipv4Address of the origin of packets for this route. May -+ * be Ipv4Address:GetAny for open groups. -+ * @param group The Ipv4Address of the multicast group or this route. -+ * @param inputInterface The input network interface index over which to -+ * expect packets destined for this route. May be -+ * Ipv4RoutingProtocol::IF_INDEX_ANY for packets of local origin. -+ * @param outputInterface A vector of network interface indices used to specify -+ * how to send packets to the destination(s). -+ * -+ * @see Ipv4Address -+ */ -+ Ipv4::AddMulticastRoute (Ipv4Address origin, -+ Ipv4Address group, -+ uint32_t inputInterface, -+ std::vector outputInterfaces) -+ -+To remove a route, one uses: -+ -+/** -+ * @brief Remove a route from the static multicast routing table. -+ * -+ * Externally, the multicast static routing table appears simply as a table -+ * with n entries. The one sublety of note is that if a default multicast -+ * route has been set it will appear as the zeroth entry in the table. This -+ * means that the default route may be removed by calling this method with -+ * appropriate wildcard parameters. -+ * -+ * This method causes the multicast routing table to be searched for the first -+ * route that matches the parameters and removes it. -+ * -+ * Wildcards may be provided to this function, but the wildcards are used to -+ * exacly match wildcards in the routes (see AddMulticastRoute). That is, -+ * calling RemoveMulticastRoute with the origin set to "0.0.0.0" will not -+ * remove routes with any address in the origin, but will only remove routes -+ * with "0.0.0.0" set as the the origin. -+ * -+ * @param origin The IP address specified as the origin of packets for the -+ * route. -+ * @param origin The IP address specified as the multicast group addres of -+ * the route. -+ * @param inputInterfade The network interface index specified as the expected -+ * input interface for the route. -+ * @returns True if a route was found and removed, false otherwise. -+ * -+ * @see Ipv4MulticastRoute -+ * @see Ipv4StaticRouting::AddMulticastRoute -+ */ -+ Ipv4::RemoveMulticastRoute (Ipv4Address origin, Ipv4Address group, -+ uint32_t inputInterface) -+ -+For compatibility, and to provide simplicity, one can set a default multicast -+route for a host originating data: -+ -+/** -+ * @brief Add a default multicast route to the static routing table. -+ * -+ * This is the multicast equivalent of the unicast version SetDefaultRoute. -+ * We tell the routing system what to do in the case where a specific route -+ * to a destination multicast group is not found. The system forwards -+ * packets out the specified interface in the hope that "something out there" -+ * knows better how to route the packet. This method is only used in -+ * initially sending packets off of a host. The default multicast route is -+ * not consulted during forwarding -- exact routes must be specified using -+ * AddMulticastRoute for that case. -+ * -+ * Since we're basically sending packets to some entity we think may know -+ * better what to do, we don't pay attention to "subtleties" like origin -+ * address, nor do we worry about forwarding out multiple interfaces. If the -+ * default multicast route is set, it is returned as the selected route from -+ * LookupStatic irrespective of origin or multicast group if another specific -+ * route is not found. -+ * -+ * @param outputInterface The network interface index used to specify where -+ * to send packets in the case of unknown routes. -+ * -+ * @see Ipv4Address -+ */ -+ Ipv4::SetDefaultMulticastRoute (uint32_t outputInterface) -+ -+For a host wanting to receive multicast data, the following function is used -+to join each multicast group. -+ -+ /** -+ * \brief Join a multicast group for a given multicast source and -+ * group. -+ * -+ * \param origin The Ipv4 address of the multicast source. -+ * \param group The multicast group address. -+ */ -+ Ipv4::JoinMulticastGroup (Ipv4Address origin, Ipv4Address group); -+ -+To stop receiving multicast data, the following function is used: -+ -+ /** -+ * \brief Leave a multicast group for a given multicast source and -+ * group. -+ * -+ * \param origin The Ipv4 address of the multicast source. -+ * \param group The multicast group address. -+ */ -+ LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group); -+ -+There are new lookup functions implemented in Ipv4: -+ -+ /** -+ * \brief Find and return the interface ID of the interface that has been -+ * assigned the specified IP address. -+ * \param addr The IP address assigned to the interface of interest. -+ * \returns The index of the ipv4 interface with the given address. -+ * -+ * Each IP interface has an IP address associated with it. It is often -+ * useful to search the list of interfaces for one that corresponds to -+ * a known IP Address. This call takes an IP address as a parameter and -+ * returns the interface index of the first interface that has been assigned -+ * that address. If the address is not found, this function asserts. -+ */ -+ Ipv4::FindInterfaceForAddr (Ipv4Address addr) const; -+ -+ /** -+ * \brief Find and return the interface ID of the interface that has been -+ * assigned the specified (masked) IP address. -+ * \param addr The IP address assigned to the interface of interest. -+ * \param mask The address mask to be used in address matching. -+ * \returns The index of the ipv4 interface with the given address. -+ * -+ * Each IP interface has an IP address associated with it. It is often -+ * useful to search the list of interfaces for one that corresponds to -+ * a known IP Address. This call takes an IP address and an IP address -+ * mask as parameters and returns the interface index of the first interface -+ * that matches the masked IP address. -+ */ -+ Ipv4::FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const; -+ -+Also, there are various methods to lookup and iterate the static multicast -+routes of a node, in the Ipv4StaticRouting class. -+ -+3. Dependencies: -+ -+- fix for bug 69 (source Ipv4 address is set correctly for UDP) -+- fix for OnOffApplication that receives data -+ -+4. Open issues or features not included -+ -+- choose source interface on a per-group basis when a host is multihomed -diff -r f9bc98cbe5fe -r f136fc719267 src/internet-node/ipv4-static-routing.h ---- a/src/internet-node/ipv4-static-routing.h Tue Sep 04 18:06:06 2007 -0700 -+++ b/src/internet-node/ipv4-static-routing.h Thu Sep 06 15:57:53 2007 -0700 -@@ -369,14 +369,17 @@ public: - * We tell the routing system what to do in the case where a specific route - * to a destination multicast group is not found. The system forwards - * packets out the specified interface in the hope that "something out there" -- * knows better how to route the packet. -- * -- * Since we're basically forwarding packets to some entity we think may know -- * better what to do, we don't pay attention to subleties like origin address -- * and input interface, nor do we worry about forwarding out multiple -- * interfaces. If the default multicast route is set, it is returned as the -- * selected route from LookupStatic irrespective of origin, multicast group or -- * input interface if another specific route is not found. -+ * knows better how to route the packet. This method is only used in -+ * initially sending packets off of a host. The default multicast route is -+ * not consulted during forwarding -- exact routes must be specified using -+ * AddMulticastRoute for that case. -+ * -+ * Since we're basically sending packets to some entity we think may know -+ * better what to do, we don't pay attention to "subtleties" like origin -+ * address, nor do we worry about forwarding out multiple interfaces. If the -+ * default multicast route is set, it is returned as the selected route from -+ * LookupStatic irrespective of origin or multicast group if another specific -+ * route is not found. - * - * @param outputInterface The network interface index used to specify where - * to send packets in the case of unknown routes. - diff --git a/doc/doxygen.conf b/doc/doxygen.conf index fc6fd25fa..ac0f72a0e 100644 --- a/doc/doxygen.conf +++ b/doc/doxygen.conf @@ -450,7 +450,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = src doc/main.txt +INPUT = src doc/main.txt doc/trace-source-list.h doc/tracing.h # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp @@ -514,7 +514,7 @@ EXAMPLE_RECURSIVE = NO # directories that contain image that are included in the documentation (see # the \image command). -IMAGE_PATH = +IMAGE_PATH = doc # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program diff --git a/doc/main.txt b/doc/main.txt index 3fc144687..37e1ed92d 100644 --- a/doc/main.txt +++ b/doc/main.txt @@ -23,6 +23,7 @@ * - \ref config * - a base class for objects which need to support reference counting * and QueryInterface: ns3::Object and ns3::InterfaceId + * - a set of low-level trace facilities integrated in the ns3::Object system: \ref tracing * - a ns3::ComponentManager which can be used to manage the creation * of any object which derives from ns3::Object through an ns3::ClassId * - a smart-pointer class ns3::Ptr designed to work together with ns3::Object @@ -33,11 +34,10 @@ * ns3::Scheduler and ns3::SchedulerFactory * - a simulator class used to create, schedule and cancel events: ns3::Simulator * - * The "common" module contains: + * The "core" module contains: * - a packet class to create and manipulate simulation packets: ns3::Packet, ns3::Header, * and ns3::Trailer. This packet class also supports per-packet ns3::Tag which are * globs of data which can be attached to any packet. - * - a set of low-level trace facilities: \ref lowleveltracing * * The "node" module contains: * - a ns3::Node base class which should be subclassed by any new type of diff --git a/doc/namespace-2.dia b/doc/namespace-2.dia new file mode 100644 index 000000000..5cd5ed59e --- /dev/null +++ b/doc/namespace-2.dia @@ -0,0 +1,1658 @@ + + + + + + + + + + + + + #A4# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/devices/[0-n]# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #NodeList# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #Node# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/queue# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/nodes/[0-n]# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/udp# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/rx# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/netdevice# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/ipv4# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/interfaces/[0-n]# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/rx# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/queue# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/rx# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/enqueue# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/dequeue# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/drop# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #InternetNode# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #PointToPointNetDevice# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #Queue# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #Ipv4L3Protocol# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #Ipv4Interface# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #CsmaNetDevice# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/enqueue# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/dequeue# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/drop# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #Queue# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/namespace-2.png b/doc/namespace-2.png new file mode 100644 index 000000000..7ea379c82 Binary files /dev/null and b/doc/namespace-2.png differ diff --git a/doc/trace-source-list.h b/doc/trace-source-list.h new file mode 100644 index 000000000..c23d06ece --- /dev/null +++ b/doc/trace-source-list.h @@ -0,0 +1,204 @@ +/// +/// \ingroup TraceSourceList +/// \brief send ipv4 packet to outgoing interface +/// \param arg1 the trace context associated to the connected trace source. +/// \param arg2 packet sent. +/// \param arg3 index of output ipv4 interface. +/// +/// +/// The path to this trace source is: /nodes/[0-n]/ipv4/tx. +/// +/// The following classes can be extracted from \p arg1 with +/// ns3::TraceContext::GetElement: +/// - ns3::NodeListIndex +/// - ns3::Ipv4L3ProtocolTraceContextElement +void TraceSinkCallback0 (const TraceContext & arg1, const Packet & arg2, uint32_t arg3); + +/// +/// \ingroup TraceSourceList +/// \brief receive ipv4 packet from incoming interface +/// \param arg1 the trace context associated to the connected trace source. +/// \param arg2 packet received. +/// \param arg3 index of input ipv4 interface. +/// +/// +/// The path to this trace source is: /nodes/[0-n]/ipv4/rx. +/// +/// The following classes can be extracted from \p arg1 with +/// ns3::TraceContext::GetElement: +/// - ns3::NodeListIndex +/// - ns3::Ipv4L3ProtocolTraceContextElement +void TraceSinkCallback1 (const TraceContext & arg1, const Packet & arg2, uint32_t arg3); + +/// +/// \ingroup TraceSourceList +/// \brief drop ipv4 packet +/// \param arg1 the trace context associated to the connected trace source. +/// \param arg2 packet dropped. +/// +/// +/// The path to this trace source is: /nodes/[0-n]/ipv4/drop. +/// +/// The following classes can be extracted from \p arg1 with +/// ns3::TraceContext::GetElement: +/// - ns3::NodeListIndex +/// - ns3::Ipv4L3ProtocolTraceContextElement +void TraceSinkCallback2 (const TraceContext & arg1, const Packet & arg2); + +/// +/// \ingroup TraceSourceList +/// \brief store packet in queue +/// \param arg1 the trace context associated to the connected trace source. +/// \param arg2 packet queued. +/// +/// +/// The path to this trace source is: /nodes/[0-n]/devices/[0-n]/queue/enqueue. +/// +/// The following classes can be extracted from \p arg1 with +/// ns3::TraceContext::GetElement: +/// - ns3::NodeListIndex +/// - ns3::NodeNetDeviceIndex +/// - ns3::QueueTraceType +void TraceSinkCallback3 (const TraceContext & arg1, const Packet & arg2); + +/// +/// \ingroup TraceSourceList +/// \brief remove packet from queue +/// \param arg1 the trace context associated to the connected trace source. +/// \param arg2 packet dequeued. +/// +/// +/// The path to this trace source is: /nodes/[0-n]/devices/[0-n]/queue/dequeue. +/// +/// The following classes can be extracted from \p arg1 with +/// ns3::TraceContext::GetElement: +/// - ns3::NodeListIndex +/// - ns3::NodeNetDeviceIndex +/// - ns3::QueueTraceType +void TraceSinkCallback4 (const TraceContext & arg1, const Packet & arg2); + +/// +/// \ingroup TraceSourceList +/// \brief drop packet from queue +/// \param arg1 the trace context associated to the connected trace source. +/// \param arg2 packet dropped. +/// +/// +/// The path to this trace source is: /nodes/[0-n]/devices/[0-n]/queue/drop. +/// +/// The following classes can be extracted from \p arg1 with +/// ns3::TraceContext::GetElement: +/// - ns3::NodeListIndex +/// - ns3::NodeNetDeviceIndex +/// - ns3::QueueTraceType +void TraceSinkCallback5 (const TraceContext & arg1, const Packet & arg2); + +/// +/// \ingroup TraceSourceList +/// \brief receive MAC packet +/// \param arg1 the trace context associated to the connected trace source. +/// \param arg2 packet received. +/// +/// +/// The path to this trace source is: /nodes/[0-n]/devices/[0-n]/rx. +/// +/// The following classes can be extracted from \p arg1 with +/// ns3::TraceContext::GetElement: +/// - ns3::NodeListIndex +/// - ns3::NodeNetDeviceIndex +/// - ns3::PointToPointTraceType +void TraceSinkCallback6 (const TraceContext & arg1, const Packet & arg2); + +/// +/// \ingroup TraceSourceList +/// \brief receive MAC packet +/// \param arg1 the trace context associated to the connected trace source. +/// \param arg2 packet received. +/// +/// +/// The path to this trace source is: /nodes/[0-n]/devices/[0-n]/rx. +/// +/// The following classes can be extracted from \p arg1 with +/// ns3::TraceContext::GetElement: +/// - ns3::NodeListIndex +/// - ns3::NodeNetDeviceIndex +/// - ns3::CsmaTraceType +void TraceSinkCallback7 (const TraceContext & arg1, const Packet & arg2); + +/// +/// \ingroup TraceSourceList +/// \brief drop MAC packet +/// \param arg1 the trace context associated to the connected trace source. +/// \param arg2 packet dropped. +/// +/// +/// The path to this trace source is: /nodes/[0-n]/devices/[0-n]/drop. +/// +/// The following classes can be extracted from \p arg1 with +/// ns3::TraceContext::GetElement: +/// - ns3::NodeListIndex +/// - ns3::NodeNetDeviceIndex +/// - ns3::CsmaTraceType +void TraceSinkCallback8 (const TraceContext & arg1, const Packet & arg2); + +/// +/// \ingroup TraceSourceList +/// \brief The value of the speed vector changed +/// \param arg1 the trace context associated to the connected trace source. +/// \param arg2 the mobility model whose course changed. +/// +/// +/// The path to this trace source is: /nodes/[0-n]/$MobilityModelNotifier/course-change. +/// +/// The following classes can be extracted from \p arg1 with +/// ns3::TraceContext::GetElement: +/// - ns3::NodeListIndex +void TraceSinkCallback9 (const TraceContext & arg1, Ptr arg2); + +/// +/// \ingroup TraceSourceList +/// \brief send ipv4 packet to outgoing interface +/// \param arg1 the trace context associated to the connected trace source. +/// \param arg2 packet sent. +/// \param arg3 index of output ipv4 interface. +/// +/// +/// The path to this trace source is: /nodes/[0-n]/$Ipv4L3Protocol/tx. +/// +/// The following classes can be extracted from \p arg1 with +/// ns3::TraceContext::GetElement: +/// - ns3::NodeListIndex +/// - ns3::Ipv4L3ProtocolTraceContextElement +void TraceSinkCallback10 (const TraceContext & arg1, const Packet & arg2, uint32_t arg3); + +/// +/// \ingroup TraceSourceList +/// \brief receive ipv4 packet from incoming interface +/// \param arg1 the trace context associated to the connected trace source. +/// \param arg2 packet received. +/// \param arg3 index of input ipv4 interface. +/// +/// +/// The path to this trace source is: /nodes/[0-n]/$Ipv4L3Protocol/rx. +/// +/// The following classes can be extracted from \p arg1 with +/// ns3::TraceContext::GetElement: +/// - ns3::NodeListIndex +/// - ns3::Ipv4L3ProtocolTraceContextElement +void TraceSinkCallback11 (const TraceContext & arg1, const Packet & arg2, uint32_t arg3); + +/// +/// \ingroup TraceSourceList +/// \brief drop ipv4 packet +/// \param arg1 the trace context associated to the connected trace source. +/// \param arg2 packet dropped. +/// +/// +/// The path to this trace source is: /nodes/[0-n]/$Ipv4L3Protocol/drop. +/// +/// The following classes can be extracted from \p arg1 with +/// ns3::TraceContext::GetElement: +/// - ns3::NodeListIndex +/// - ns3::Ipv4L3ProtocolTraceContextElement +void TraceSinkCallback12 (const TraceContext & arg1, const Packet & arg2); + diff --git a/doc/tracing.h b/doc/tracing.h new file mode 100644 index 000000000..45e7d9db5 --- /dev/null +++ b/doc/tracing.h @@ -0,0 +1,576 @@ +/** + * \defgroup TraceSourceList List of trace sources + */ + +/** + * \defgroup tracing Tracing + * + * The flexibility of the ns-3 tracing system comes at the cost of quite + * a bit of complexity so, before trying to use the low-level aspects + * of the tracing API, it is important to focus on some basic definitions: + * + * - A trace source is an object instance which can report trace events + * to a set of listening trace sinks. + * + * - A trace sink is a user-provided callback (a function) which can + * be connected to a set of trace sources to receive the events generated + * by each trace source. + * + * - A trace resolver is an object which allows users to establish + * connections between a set of trace sources and a set of trace sinks. + * + * \section TraceSource Generating Trace Events + * + * So, what does it look like in practice ? First, let's look at trace + * sources. We have two types of trace sources: numeric, and, normal + * trace sources. Numeric trace sources behave as normal c++ integers + * or c++ floating point numbers except that they report as trace events + * each change of their value. For example: + * \code + * class MyModel + * { + * public: + * void DoSomething (void) + * { + * // use the "int" trace source just + * // like any other "int" variable. + * m_cwnd *= 2; + * m_cwnd += 4; + * if (m_cwnd > 100) + * { + * // do something. + * } + * } + * private: + * // declare an instance of a "int" trace source + * SVTraceSource m_cwnd; + * }; + * \endcode + * Normal trace sources, on the other hand, allow you to trace the + * call of arbitrary functions and methods, as shown below. They are + * typically used to track "rx", "tx", or "drop" events but could + * also be used to track route change events, or position change + * events: + * \code + * class MyModel + * { + * public: + * void DoSomething (Packet packet) + * { + * // report this event on packet + * m_doSomething (packet); + * // do something + * } + * private: + * // report every "something" function call. + * CallbackTraceSource m_doSomething; + * }; + * \endcode + * Every type of trace source derives from the ns3::TraceSource base class. + * As of today, the set of concrete subclasses is relatively short: + * ns3::CallbackTraceSource, ns3::SvTraceSource, ns3::UvTraceSource, and, + * ns3::FvTraceSource. + * + * \section TraceSink Receiving Trace Events + * + * To receive these trace events, a user should specify a set of trace sinks. + * For example, to receive the "int" and the "something" events shown in the + * examples above, a user would declare the following functions: + * \code + * // oldValue and newValue contain the previous and new values of + * // the connected SVTraceSource trace source. + * void + * CwndTraceSink (const TraceContext &context, int64_t oldValue, int64_t newValue) + * { + * // for example, print the new value: + * std::cout << "cwnd=" << newValue << std::endl; + * } + * void + * DoSomethingTraceSink (const TraceContext &context, Packet packet) + * { + * // for example, print the arguments + * std::cout << "packet " << packet << std::endl; + * } + * \endcode + * Each of these sink function takes, as a first argument, a reference to a + * const TraceContext object. This context object contains information which + * describes the instance of the connected trace source: that information is + * setup during the connection process and does not change afterwards + * The type and the number of the other arguments to each trace sink depends + * on the type of the connected trace source: it conveys per-event information + * from the trace source to the trace sink. For example, UVTraceSource and + * SVTraceSource trace sources require two extra arguments. The former requires + * two unsigned 64 bit integers while the latter requires two signed 64 bit + * integers. More generally, users can consult the \ref TraceSourceList + * to figure out the arguments which a trace sink is required to receive + * for each trace source: a signature of the user trace sink must match + * _exactly_ the signature documented in the \ref TraceSourceList. + * + * + * \section TraceSourceSimpleExport A simple way to connect Trace Sources with Trace Sinks + * + * The crux of the complexity of the ns-3 tracing system comes from its + * flexible system used to connect trace sources to trace sinks but what is really + * nice about it is that it is not necessary to use it to setup simple traces. + * + * The simplest way to export a set of trace sources to a user, for example, + * during the early prototyping phases of a system, is to add a set of public methods + * to give to your users access to the trace source object instances you use to generate + * trace events: + * \code + * class MyModel + * { + * public: + * void DoSomething (Packet packet) + * { + * // report this event on packet + * m_doSomething (packet); + * // do something + * } + * CallbackTraceSource *PeekSomethingTraceSource (void) const + * { + * return &m_doSomething + * } + * private: + * // report every "something" function call. + * CallbackTraceSource m_doSomething; + * }; + * \endcode + * If your users hold a pointer to an instance of MyModel, and if they want to connect + * a MySomethingSink, they can simply do the following which invokes the + * TraceSource::AddCallback method and creates a Callback object from the user's + * sink with the MakeCallback function. + * \code + * void + * MySomethingSink (const TraceContext &context, Packet packet) + * { + * // do whatever you want. + * } + * MyModel *model = ...; + * CallbackTraceSource *source = model->PeekSomethingTraceSource (); + * source->AddCallback (MakeCallback (&MySomethingSink)); + * \endcode + * + * The full power of the tracing system comes however from its ns3::NodeList::Connect + * method which is described in the following sections. + * + * \section TraceConnection Connecting Trace Sources to Trace Sinks + * + * If a trace source is integrated in the ns-3 trace connection facility, a user + * should call the ns3::NodeList::Connect method to establish a connection between + * a trace sink and a set of matching trace sources. The second argument to that + * method is a callback to the user's trace sink. + * That callback is easy to construct: call ns3::MakeCallback and you are done. The + * first argument is a string whose format is similar to a unix path and which is + * used to uniquely identify the set of trace sources you want to connect to. + * The set of acceptable path strings is also documented in the \ref TraceSourceList. + * + * So, what does this look like from the perspective of a user ? If we wanted to + * connect to a trace source defined somewhere deep into the a set of NetDevice objects + * located in some nodes of the system, we could write the following: + * \code + * void + * DoSomethingTraceSink (const TraceContext &context, Packet packet) + * { + * // for example, print the arguments + * std::cout << "packet: " << packet << std::endl; + * } + * // connect the above sink to a matching trace source + * NodeList::Connect ("/nodes/* /devices/* /rx", MakeCallback &DoSomethingTraceSink); + * \endcode + * + * The connection path string "/nodes/* /devices/* /rx" matches the "rx" trace source + * located in every netdevice located in every node. The syntax of that path string + * is loosely based on regular expressions so, a user could conceivably connect + * to the trace sources present in only one node identified by node index: + * "/nodex/3/devices/* /rx". + * + * The matching algorithm used here is very useful since it allows you to connect + * at once a large set of trace sources to a single sink but it introduces another + * problem: it becomes impossible when you receive an event in your trace sink to + * know from _which_ trace source the event is coming from. In our example, the + * trace source might be coming from the NetDevice number 2 of Node 10 or Netdevice + * number 0 of Node 5. In both cases, you might need to know which of these NetDevice + * is generating this event, if only to generate some ascii trace dump. Another + * similar use-case is that you might have connected the same trace sink to + * multiple types of events which have the same signature: it is quite common + * to receive all tx, rx, and drop events in the same trace sink and that would be + * quite trivial to achieve with a string such as: "/nodes/* /devices/* /*" + * + * The source of a trace event can be retrieved from a trace sink using + * different means: the simplest + * way to get this information is to use the builtin printing facility of + * the TraceContext object: + * \code + * void + * DoSomethingTraceSink (const TraceContext &context, Packet packet) + * { + * // for example, print the arguments + * std::cout << "context=\"" << context << "\" packet: " << packet << std::endl; + * } + * \endcode + * The above code is going to generate output which looks like the following: + * \code + * context="nodeid=2 device=0 dev-rx" packet: IPV4(tos 0x0 ttl 64 id 0 offset ... + * context="nodeid=1 device=0 dev-rx" packet: IPV4(tos 0x0 ttl 64 id 0 offset ... + * ... + * \endcode + * + * Another more advanced way to get information out of a TraceContext is to call its + * ns3::TraceContext::GetElement method. This method takes as its first and only + * argument an instance of the object we want to read and the list of available + * object instances we can read from a TraceContext is documented, once again, + * in the \ref TraceSourceList. For example, we could write the following to + * generate adhoc trace output: + * \code + * void DeviceRxSink (const TraceContext &context, const Packet &packet) + * { + * NodeListIndex nodeIndex; + * NodeNetDeviceIndex deviceIndex; + * context.GetElement (nodeIndex); + * context.GetElement (deviceIndex); + * std::cout << "node-index=" << nodeIndex.Get (); + * std::cout << ", device-index=" << deviceIndex.Get (); + * std::cout << ", packet: " << packet; + * std::cout << std::endl; + * } + * \endcode + * + * \section ExportingTraceSources Exporting new Trace Sources + * + * Using existing trace sources to connect them to a set of adhoc trace sinks + * is not really complicated but, setting up new trace sources which can hook + * in this automatic connection system is a bit more complicated. + * + * So far, we know that a model author can generate trace events really easily: + * \code + * class MyModel + * { + * public: + * void DoSomething (Packet packet) + * { + * // report this event on packet with value + * m_doSomething (packet); + * // do something + * } + * private: + * // report every "something" function call. + * CallbackTraceSource m_doSomething; + * }; + * \endcode + * + * To make these new trace sources available to the rest of the connection system, + * the first step is to make sure that your model object derives from the ns3::Object + * base class either directly (as shown below) or indirectly through another base class: + * \code + * class MyModel : public Object {...}; + * // or: + * class SomeOtherObject : public Object {...}; + * class MyModel : public SomeOtherObject {...}; + * \endcode + * + * This is pretty trivial and lays the ground for the second step: overriding the + * ns3::Object::GetTraceResolver method: + * \code + * class MyModel : public MyParent + * { + * public: + * // declare overriden method + * virtual Ptr GetTraceResolver (void) const; + * private: + * // the new trace source to export. + * CallbackTraceSource m_rxSource; + * }; + * \endcode + * + * To implement this method, you could attempt to implement a new subclass of + * the ns3::TraceResolver base class and return an instance from this method but + * this would be very hard. Instead, you should use the helper class + * ns3::CompositeTraceResolver to register your trace sources and chain up to + * your parent: + * \code + * Ptr + * MyModel::GetTraceResolver (void) const + * { + * // create an empty trace resolver + * Ptr resolver = Create (); + * // register m_rxSource + * resolver->AddSource ("rx", // the name of the trace source in the path string + * TraceDoc ("some help text to explain the purpose of this trace source", + * "Packet", // the type of the first argument to the trace source + * "the purpose of the first argument", + * "type-of-second-argument", "purpose-of-second-argument"), + * m_rxSource // the trace source itself is registered + * ); + * // make sure we include the trace sources implemented in the parent. + * resolver->SetParentResolver (MyParent::GetTraceResolver ()); + * return resolver; + * } + * \endcode + * + * Once you have written that code, you must make sure that this new method GetTraceResolver + * is going to be called at some point by the tracing system. If your model is located somewhere + * deep in MAC or PHY layer, that is, it is part of a NetDevice implementation, all you + * have to do is to make sure that your model is registered as a "composite" of your NetDevice + * subclass: + * \code + * class MyNetDevice : public NetDevice + * { + * public: + * Ptr GetTraceResolver (void) const; + * private: + * Ptr m_model; + * }; + * + * Ptr + * MyNetDevice::GetTraceResolver (void) const + * { + * Ptr resolver = ...; + * // register other trace source + * ... + * // register now your model as a "composite" + * resolver->AddComposite ("my-model", m_model); + * // chain up to parent. + * resolver->SetParentResolver (NetDevice::GetTraceResolver ()); + * return resolver; + * } + * \endcode + * + * The code above will make your "rx" trace source appear under the + * /nodes/xx/devices/xx/my-model/rx namespace path. + * + * If you have implemented a new layer 3 or 4 protocol object, the process to + * export your trace sources is quite similar. You need to subclass from + * ns3::Object, override the ns3::Object::GetTraceResolver method, make + * sure you chain up to your parent's GetTraceResolver method, and, finally, + * make sure that someone calls your new GetTraceResolver method. How to accomplish + * the latter should be documented in the node's API documentation which describes + * how to implement a new layer 3 or 4 protocol object. + * + * \section AdvancedTraceContext Creating new Trace Context Elements + * + * The last important feature which model developers need to understand + * is how to provide extra context information to trace sinks. For example, + * if your model exports both rx and tx trace sources which share the same + * signature, it is quite natural for a user to connect to a single trace sink + * to both of them with a trace path string such as "/nodes/* /devices/* /(rx|tx)". + * In this case, it becomes necessary to be able, from the trace sink function, + * to tell which event triggered the call to the trace sink: a rx or a tx event. + * + * That example is detailed below with a TX, a RX, and a DROP source: + * \code + * class MyModel + * { + * private: + * CallbackTraceSource m_rxSource; + * CallbackTraceSource m_txSource; + * CallbackTraceSource m_dropSource; + * }; + * \endcode + * When a single sink is connected to all 3 sources here, one might want + * to write code like the following: + * \code + * void DeviceRxSink (const TraceContext &context, const Packet &packet) + * { + * switch (type) { + * case RX: + * std::cout << "rx" << std::endl; + * break; + * case TX: + * std::cout << "tx" << std::endl; + * break; + * case DROP: + * std::cout << "drop" << std::endl; + * break; + * } + * \endcode + * + * \subsection AdvancedTraceContextSimpleSolution The simple solution + * + * The simplest way to do achieve the result shown above is to include + * in the trace source an extra explicit argument which describes the source event: + * - define a small enum with 3 values + * - change the signature of m_rxSource, m_txSource, and m_dropSource to include + * the enum + * - pass the enum value in each event + * + * The resulting code is shown below: + * \code + * class MyModel + * { + * public: + * // define the trace type enum. + * enum TraceType { + * RX, + * TX, + * DROP + * }; + * private: + * // generate events + * void NotifyRxPacket (Packet p) { + * m_rxSource (p, MyModel::RX); + * } + * void NotifyTxPacket (Packet p) { + * m_rxSource (p, MyModel::TX); + * } + * void NotifyDropPacket (Packet p) { + * m_rxSource (p, MyModel::DROP); + * } + * CallbackTraceSource m_rxSource; + * CallbackTraceSource m_txSource; + * CallbackTraceSource m_dropSource; + * }; + * \endcode + * These 3 new sources can be connected easily to a new trace sink: + * \code + * void ASimpleTraceSink (const TraceContext &context, const Packet &packet, enum MyModel::TraceType type) + * { + * // here, read the "type" argument + * } + * \endcode + * + * This solution works but it makes it impossible to connect a single trace sink to a set + * of trace sources which represent "rx" events in different NetDevice objects since + * each of them will define a different enum type with different values: since the + * trace sink signature must match exactly the trace source signature, it is impossible + * to connect at the same time to all "rx" events of different NetDevice. + * + * \subsection AdvancedTraceContextFancySolution The more complex and generic solution + * + * There is, hopefully, a way to get the best of both worlds, that is, to allow a + * user to connect to a lot of trace source events of the same kind but coming from different + * implementations and to allow the user to differentiate between these different + * implementations. + * + * Rather than define an adhoc enum type with a list of trace sources, you can also + * define a new ns3::TraceContextElement for your source sources. For example, if you + * define a new MyModelTraceType class which contains the type of trace, your users can + * then write trace sink code which looks like this: + * \code + * void AFancyTraceSink (const TraceContext &context, const Packet &packet) + * { + * MyModelTraceType type; + * if (context.GetElement (type)) + * { + * switch (type.Get ()) + * { + * case MyModelTraceType::RX: + * std::cout << "rx" << std::endl; + * break; + * case MyModelTraceType::TX: + * std::cout << "tx" << std::endl; + * break; + * case MyModelTraceType::DROP: + * std::cout << "drop" << std::endl; + * break; + * } + * } + * } + * \endcode + * + * Of course, since the type of trace is stored in the TraceContext, your users can + * also take the shortcut which uses the printing functionality of the TraceContext: + * \code + * void ALessFancyTraceSink (const TraceContext &context, const Packet &packet) + * { + * std::cout << "context=\"" << context << "\" packet: " << packet << std::endl; + * } + * \endcode + * which will generate something like the following when the trace source comes + * from MyModel: + * \code + * context="my-model-rx" packet: ... + * \endcode + * + * The first step to achieve this is to define and implement a new + * subclass of the ns3::TraceContextElement base class. The exact list of + * public methods which must be implemented is described in the API + * documentation of the ns3::TraceContextElement class. + * \code + * class MyModelTraceType : public TraceContextElement + * { + * public: + * enum Type { + * RX, + * TX, + * DROP + * }; + * // called from MyModel::GetTraceResolver + * MyModelTraceType (enum Type type); + * // called from trace sink + * enum Type Get (void) const; + * // needed by the tracing subsystem + * static uint16_t GetUid (void); + * // needed by the tracing subsystem to + * // print the content of a TraceContext + * void Print (std::ostream &os) const; + * // needed by the tracing subsystem to + * // generate the doxygen documentation. + * std::string GetTypeName (void) const; + * private: + * enum Type m_type; + * }; + * \endcode + * The implementation does not require much thinking: + * \code + * MyModelTraceType::MyModelTraceType (enum Type type) + * : m_type (type) + * {} + * enum Type + * MyModelTraceType::Get (void) const + * { + * return m_type; + * } + * uint16_t + * MyModelTraceType::GetUid (void) + * { + * // use protected TraceContextElement::AllocateUid method + * // the input string is used to uniquely identify this new subclass + * static uint16_t uid = AllocateUid ("ns3::MyModelTraceType"); + * return uid; + * } + * void + * MyModelTraceType::Print (std::ostream &os) const + * ( + * // this method is invoked by the print function of a TraceContext + * // if it contains an instance of this TraceContextElement. + * switch (m_type) { + * case RX: os << "rx"; break; + * // ... + * } + * ) + * std::string + * MyModelTraceType::GetTypeName (void) const + * { + * // This method should return a fully-qualified c++ typename + * // This method is used only for documentation purposes to + * // generate the content of the Trace Source List. + * return "ns3::MyModelTraceType"; + * } + * \endcode + * + * Once this subclass is implemented, the work is almost completed: you + * just need to pass an instance of that class as the last argument of + * the ns3::CompositeTraceResolver::AddSource method as shown below: + * \code + * Ptr + * MyModel::GetTraceResolver (void) const + * { + * // create an empty trace resolver + * Ptr resolver = Create (); + * // register m_rxSource + * resolver->AddSource ("rx", // the name of the trace source in the path string + * TraceDoc ("some help text to explain the purpose of this trace source", + * "Packet", // the type of the first argument to the trace source + * "the purpose of the first argument", + * "type-of-second-argument", "purpose-of-second-argument"), + * m_rxSource, // the trace source itself is registered + * // the TraceContextElement associated to this trace source. + * MyModelTraceType (MyModelTraceType::RX) + * ); + * // make sure we include the trace sources implemented in the parent. + * resolver->SetParentResolver (MyParent::GetTraceResolver ()); + * return resolver; + * } + * \endcode + */ diff --git a/samples/main-random-topology.cc b/samples/main-random-topology.cc index 3fb52a0d9..3021ed3fb 100644 --- a/samples/main-random-topology.cc +++ b/samples/main-random-topology.cc @@ -15,7 +15,7 @@ using namespace ns3; static void -CourseChange (Ptr position) +CourseChange (const TraceContext &context, Ptr position) { Position pos = position->Get (); std::cout << Simulator::Now () << ", pos=" << position << ", x=" << pos.x << ", y=" << pos.y @@ -39,7 +39,7 @@ int main (int argc, char *argv[]) for (uint32_t i = 0; i < 10000; i++) { Ptr notifier = Create (); - notifier->RegisterListener (MakeCallback (&CourseChange)); + notifier->TraceConnect ("/course-change", MakeCallback (&CourseChange)); objects.push_back (notifier); } diff --git a/src/applications/packet-sink.cc b/src/applications/packet-sink.cc index 4ed54ab50..2f767303e 100644 --- a/src/applications/packet-sink.cc +++ b/src/applications/packet-sink.cc @@ -29,6 +29,8 @@ using namespace std; namespace ns3 { +NS_DEBUG_COMPONENT_DEFINE ("PacketSink"); + // Constructors PacketSink::PacketSink (Ptr n, @@ -106,7 +108,7 @@ void PacketSink::Receive(Ptr socket, const Packet &packet, if (InetSocketAddress::IsMatchingType (from)) { InetSocketAddress address = InetSocketAddress::ConvertFrom (from); - NS_DEBUG_UNCOND ( __PRETTY_FUNCTION__ << ": Received " << + NS_DEBUG ( __PRETTY_FUNCTION__ << ": Received " << packet.GetSize() << " bytes from " << address.GetIpv4() << " [" << address << "]---'" << packet.PeekData() << "'"); } diff --git a/src/common/array-trace-resolver.h b/src/common/array-trace-resolver.h deleted file mode 100644 index e4507d4af..000000000 --- a/src/common/array-trace-resolver.h +++ /dev/null @@ -1,95 +0,0 @@ -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2007 INRIA - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Mathieu Lacage - */ -#ifndef ARRAY_TRACE_RESOLVER_H -#define ARRAY_TRACE_RESOLVER_H - -#include -#include -#include "ns3/callback.h" -#include "trace-resolver.h" - -namespace ns3 { - -/** - * \brief a helper class to offer trace resolution for an array of objects. - * \ingroup lowleveltracing - */ -template -class ArrayTraceResolver : public TraceResolver -{ -public: - /** - * \param context trace context associated to this trace resolver - * \param getSize callback which returns dynamically the size of underlying array - * \param get callback which returns any element in the underlying array - * - * Construct a trace resolver which can match any input integer - * against an element in an array. The array is accessed using a - * pair of callbacks. It is the responsability of the user to - * provide two such callbacks whose job is to adapt the array - * API to the resolver needs. Each element of the array is expected - * to provide a method named CreateTraceResolver which takes as - * only argument a reference to a const TraceContext and returns - * a pointer to a TraceResolver. i.e. the signature is: - * TraceResolver * (*) (TraceContext const &) - */ - ArrayTraceResolver (TraceContext const &context, - Callback getSize, - Callback get); -private: - virtual TraceResolverList DoLookup (std::string id) const; - Callback m_getSize; - Callback m_get; -}; -}//namespace ns3 - -namespace ns3 { - -template -ArrayTraceResolver::ArrayTraceResolver (TraceContext const &context, - Callback getSize, - Callback get) - : TraceResolver (context), - m_getSize (getSize), - m_get (get) -{} -template -TraceResolver::TraceResolverList -ArrayTraceResolver::DoLookup (std::string id) const -{ - TraceResolverList list; - if (id == "*") - { - for (uint32_t i = 0; i < m_getSize (); i++) - { - TraceContext context = GetContext (); - INDEX index = i; - context.Add (index); - list.push_back (m_get (i)->CreateTraceResolver (context)); - } - } - return list; -} - - -}//namespace ns3 - -#endif /* ARRAY_TRACE_RESOLVER_H */ diff --git a/src/common/callback-trace-source.h b/src/common/callback-trace-source.h deleted file mode 100644 index a1e13df9d..000000000 --- a/src/common/callback-trace-source.h +++ /dev/null @@ -1,157 +0,0 @@ -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2005,2006,2007 INRIA - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Mathieu Lacage - */ - -#ifndef CALLBACK_TRACE_H -#define CALLBACK_TRACE_H - -#include -#include "ns3/callback.h" -#include "ns3/fatal-error.h" -#include "trace-context.h" - -namespace ns3 { - - -/** - * \brief log arbitrary number of parameters to a matching ns3::Callback - * \ingroup lowleveltracing - * - * Whenever operator () is invoked on this class, the call and its arguments - * are forwarded to the internal matching ns3::Callback. - */ -template -class CallbackTraceSource { -public: - CallbackTraceSource (); - void AddCallback (CallbackBase const & callback, TraceContext const & context); - void RemoveCallback (CallbackBase const & callback); - void operator() (void); - void operator() (T1 a1); - void operator() (T1 a1, T2 a2); - void operator() (T1 a1, T2 a2, T3 a3); - void operator() (T1 a1, T2 a2, T3 a3, T4 a4); - -private: - typedef std::list > CallbackList; - TraceContext m_context; - CallbackList m_callbackList; -}; - -}; // namespace ns3 - -// implementation below. - -namespace ns3 { - -template -CallbackTraceSource::CallbackTraceSource () - : m_callbackList () -{} -template -void -CallbackTraceSource::AddCallback (CallbackBase const & callback, - TraceContext const &context) -{ - Callback cb; - cb.Assign (callback); - m_context.Add (context); - m_callbackList.push_back (cb); -} -template -void -CallbackTraceSource::RemoveCallback (CallbackBase const & callback) -{ - for (typename CallbackList::iterator i = m_callbackList.begin (); - i != m_callbackList.end (); /* empty */) - { - if ((*i).IsEqual (callback)) - { - i = m_callbackList.erase (i); - } - else - { - i++; - } - } -} -template -void -CallbackTraceSource::operator() (void) -{ - for (typename CallbackList::iterator i = m_callbackList.begin (); - i != m_callbackList.end (); i++) - { - (*i) (m_context); - } -} -template -void -CallbackTraceSource::operator() (T1 a1) -{ - for (typename CallbackList::iterator i = m_callbackList.begin (); - i != m_callbackList.end (); i++) - { - (*i) (m_context, a1); - } -} -template -void -CallbackTraceSource::operator() (T1 a1, T2 a2) -{ - for (typename CallbackList::iterator i = m_callbackList.begin (); - i != m_callbackList.end (); i++) - { - (*i) (m_context, a1, a2); - } -} -template -void -CallbackTraceSource::operator() (T1 a1, T2 a2, T3 a3) -{ - for (typename CallbackList::iterator i = m_callbackList.begin (); - i != m_callbackList.end (); i++) - { - (*i) (m_context, a1, a2, a3); - } -} -template -void -CallbackTraceSource::operator() (T1 a1, T2 a2, T3 a3, T4 a4) -{ - for (typename CallbackList::iterator i = m_callbackList.begin (); - i != m_callbackList.end (); i++) - { - (*i) (m_context, a1, a2, a3, a4); - } -} - -}//namespace ns3 - -#endif /* CALLBACK_TRACE_H */ diff --git a/src/common/composite-trace-resolver.cc b/src/common/composite-trace-resolver.cc deleted file mode 100644 index bf60aa81e..000000000 --- a/src/common/composite-trace-resolver.cc +++ /dev/null @@ -1,375 +0,0 @@ -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2007 INRIA - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Mathieu Lacage - */ -#include "composite-trace-resolver.h" - -namespace ns3 { - -CompositeTraceResolver::CompositeTraceResolver (TraceContext const &context) - : TraceResolver (context) -{} - -CompositeTraceResolver::~CompositeTraceResolver () -{} - -void -CompositeTraceResolver::Add (std::string name, - Callback createResolver) -{ - TraceContext traceContext = GetContext (); - DoAdd (name, createResolver, traceContext); -} - -void -CompositeTraceResolver::DoAdd (std::string name, - Callback createResolver, - TraceContext const &context) -{ - struct CallbackTraceSourceItem item; - item.name = name; - item.createResolver = createResolver; - item.context = context; - m_items.push_back (item); -} - -TraceResolver::TraceResolverList -CompositeTraceResolver::DoLookup (std::string id) const -{ - if (id == "*") - { - TraceResolver::TraceResolverList list; - for (TraceItems::const_iterator i = m_items.begin (); i != m_items.end (); i++) - { - list.push_back (i->createResolver (i->context)); - } - return list; - } - std::string::size_type start, end; - start = id.find_first_of ("(", 0); - end = id.find_first_of (")", 0); - if (start != 0 || end != (id.size ()-1)) - { - for (TraceItems::const_iterator i = m_items.begin (); i != m_items.end (); i++) - { - if (i->name == id) - { - TraceResolver::TraceResolverList list; - list.push_back (i->createResolver (i->context)); - return list; - } - } - } - std::list names; - std::string alternatives = std::string (id, start+1, end-1); - std::string::size_type next, cur; - next = 0; - cur = 0; - while (true) - { - std::string element; - next = alternatives.find ("|", cur); - if (next == std::string::npos) - { - element = std::string (alternatives, cur, alternatives.size ()); - names.push_back (element); - break; - } - element = std::string (alternatives, cur, next); - names.push_back (element); - cur = next + 1; - } - TraceResolver::TraceResolverList list; - for (std::list::const_iterator i = names.begin (); i != names.end (); i++) - { - for (TraceItems::const_iterator j = m_items.begin (); j != m_items.end (); j++) - { - if (j->name == *i) - { - list.push_back (j->createResolver (j->context)); - break; - } - } - } - return list; -} - -}//namespace ns3 - -#ifdef RUN_SELF_TESTS - -#include "ns3/test.h" -#include "trace-context-element.h" - -namespace ns3 { - -class TraceSourceTest : public TraceContextElement -{ -public: - enum Sources { - DOUBLEA, - DOUBLEB, - SUBRESOLVER, - }; - static uint16_t GetUid (void) - {static uint16_t uid = AllocateUid ("TraceSourceTest"); return uid;} - void Print (std::ostream &os) - {os << "tracesource="; - if (m_sources == DOUBLEA) {os << "doubleA";} - else if (m_sources == DOUBLEB) {os << "doubleB";} - else if (m_sources == SUBRESOLVER) {os << "subresolver";} - } - TraceSourceTest () : m_sources (TraceSourceTest::DOUBLEA) {} - TraceSourceTest (enum Sources sources) :m_sources (sources) {} - bool IsDoubleA (void) {return m_sources == TraceSourceTest::DOUBLEA;} - bool IsDoubleB (void) {return m_sources == TraceSourceTest::DOUBLEB;} -private: - enum TraceSourceTest::Sources m_sources; -}; - -class SubTraceSourceTest : public TraceContextElement -{ -public: - enum Sources { - INT, - }; - static uint16_t GetUid (void) - {static uint16_t uid = AllocateUid ("SubTraceSourceTest"); return uid;} - void Print (std::ostream &os) - {os << "subtracesource=int";} - SubTraceSourceTest () : m_sources (SubTraceSourceTest::INT) {} - SubTraceSourceTest (enum Sources sources) : m_sources (sources) {} -private: - enum Sources m_sources; -}; - -class CompositeTraceResolverTest : public Test -{ -public: - CompositeTraceResolverTest (); - virtual ~CompositeTraceResolverTest (); - virtual bool RunTests (void); -private: - void TraceDouble (TraceContext const &context, double v); - void TraceInt (TraceContext const &context, int v); - TraceResolver *CreateSubResolver (TraceContext const &context); - - - bool m_gotDoubleA; - bool m_gotDoubleB; - CallbackTraceSource m_traceInt; - bool m_gotInt; -}; - -CompositeTraceResolverTest::CompositeTraceResolverTest () - : Test ("CompositeTraceResolver") -{} -CompositeTraceResolverTest::~CompositeTraceResolverTest () -{} -void -CompositeTraceResolverTest::TraceDouble (TraceContext const &context, double v) -{ - TraceSourceTest source; - context.Get (source); - if (source.IsDoubleA ()) - { - m_gotDoubleA = true; - } - else if (source.IsDoubleB ()) - { - m_gotDoubleB = true; - } - else - { - NS_FATAL_ERROR ("should not get any other trace source in this sink"); - } - -} - -void -CompositeTraceResolverTest::TraceInt (TraceContext const &context, int v) -{ - m_gotInt = true; -} - -TraceResolver * -CompositeTraceResolverTest::CreateSubResolver (TraceContext const &context) -{ - CompositeTraceResolver *subresolver = new CompositeTraceResolver (context); - subresolver->Add ("trace-int", m_traceInt, - SubTraceSourceTest (SubTraceSourceTest::INT)); - return subresolver; -} -bool -CompositeTraceResolverTest::RunTests (void) -{ - bool ok = true; - - CallbackTraceSource traceDoubleA; - CallbackTraceSource traceDoubleB; - TraceContext context; - - CompositeTraceResolver resolver (context) ; - - resolver.Add ("trace-double-a", traceDoubleA, - TraceSourceTest (TraceSourceTest::DOUBLEA)); - resolver.Add ("trace-double-b", traceDoubleB, - TraceSourceTest (TraceSourceTest::DOUBLEB)); - - resolver.Connect ("/*", MakeCallback (&CompositeTraceResolverTest::TraceDouble, this)); - - m_gotDoubleA = false; - m_gotDoubleB = false; - traceDoubleA (0); - if (!m_gotDoubleA || m_gotDoubleB) - { - ok = false; - } - m_gotDoubleA = false; - traceDoubleA (0); - traceDoubleB (0); - if (!m_gotDoubleA || !m_gotDoubleB) - { - ok = false; - } - m_gotDoubleA = false; - m_gotDoubleB = false; - - resolver.Disconnect ("/*", MakeCallback (&CompositeTraceResolverTest::TraceDouble, this)); - - m_gotDoubleA = false; - m_gotDoubleB = false; - traceDoubleA (0); - traceDoubleB (0); - if (m_gotDoubleA || m_gotDoubleB) - { - ok = false; - } - - resolver.Connect ("/trace-double-a", - MakeCallback (&CompositeTraceResolverTest::TraceDouble, this)); - m_gotDoubleA = false; - m_gotDoubleB = false; - traceDoubleA (0); - traceDoubleB (0); - if (!m_gotDoubleA || m_gotDoubleB) - { - ok = false; - } - resolver.Disconnect ("/trace-double-a", - MakeCallback (&CompositeTraceResolverTest::TraceDouble, this)); - - resolver.Connect ("/(trace-double-a)", - MakeCallback (&CompositeTraceResolverTest::TraceDouble, this)); - m_gotDoubleA = false; - m_gotDoubleB = false; - traceDoubleA (0); - traceDoubleB (0); - if (!m_gotDoubleA || m_gotDoubleB) - { - ok = false; - } - resolver.Disconnect ("/trace-double-a", - MakeCallback (&CompositeTraceResolverTest::TraceDouble, this)); - - resolver.Connect ("/(trace-double-a|trace-double-b)", - MakeCallback (&CompositeTraceResolverTest::TraceDouble, this)); - m_gotDoubleA = false; - m_gotDoubleB = false; - traceDoubleA (0); - traceDoubleB (0); - if (!m_gotDoubleA || !m_gotDoubleB) - { - ok = false; - } - resolver.Disconnect ("/trace-double-a", - MakeCallback (&CompositeTraceResolverTest::TraceDouble, this)); - m_gotDoubleA = false; - m_gotDoubleB = false; - traceDoubleA (0); - traceDoubleB (0); - if (m_gotDoubleA || !m_gotDoubleB) - { - ok = false; - } - - - resolver.Disconnect ("/(trace-double-a|trace-double-b)", - MakeCallback (&CompositeTraceResolverTest::TraceDouble, this)); - m_gotDoubleA = false; - m_gotDoubleB = false; - traceDoubleA (0); - traceDoubleB (0); - if (m_gotDoubleA || m_gotDoubleB) - { - ok = false; - } - - resolver.Add ("subresolver", - MakeCallback (&CompositeTraceResolverTest::CreateSubResolver, this), - TraceSourceTest (TraceSourceTest::SUBRESOLVER)); - - resolver.Connect ("/subresolver/trace-int", - MakeCallback (&CompositeTraceResolverTest::TraceInt, this)); - m_gotInt = false; - m_traceInt (1); - if (!m_gotInt) - { - ok = false; - } - - resolver.Disconnect ("/subresolver/trace-int", - MakeCallback (&CompositeTraceResolverTest::TraceInt, this)); - m_gotInt = false; - m_traceInt (1); - if (m_gotInt) - { - ok = false; - } - - resolver.Connect ("/*/trace-int", - MakeCallback (&CompositeTraceResolverTest::TraceInt, this)); - m_gotInt = false; - m_traceInt (1); - if (!m_gotInt) - { - ok = false; - } - - resolver.Disconnect ("/subresolver/trace-int", - MakeCallback (&CompositeTraceResolverTest::TraceInt, this)); - m_gotInt = false; - m_traceInt (1); - if (m_gotInt) - { - ok = false; - } - - - - - return ok; -} - -static CompositeTraceResolverTest g_compositeTraceResolverTest; - -}//namespace ns3 - - -#endif /* RUN_SELF_TESTS */ diff --git a/src/common/composite-trace-resolver.h b/src/common/composite-trace-resolver.h deleted file mode 100644 index cadf9da2d..000000000 --- a/src/common/composite-trace-resolver.h +++ /dev/null @@ -1,222 +0,0 @@ -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2007 INRIA - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Mathieu Lacage - */ -#ifndef COMPOSITE_TRACE_RESOLVER_H -#define COMPOSITE_TRACE_RESOLVER_H - -#include "ns3/callback.h" -#include "trace-resolver.h" -#include "callback-trace-source.h" -#include "uv-trace-source.h" -#include "sv-trace-source.h" -#include "fv-trace-source.h" -#include "terminal-trace-resolver.h" - -namespace ns3 { - -/** - * \brief a helper class to aggregate contained TraceResolver and other trace sources. - * \ingroup lowleveltracing - */ -class CompositeTraceResolver : public TraceResolver -{ -public: - CompositeTraceResolver (TraceContext const &context); - virtual ~CompositeTraceResolver (); - /** - * \param name name of trace source - * \param trace a callback trace source - * \param context the context associated to this trace source - * - * Add a callback trace source in this resolver. This trace - * source will match the name specified during namespace - * resolution. The TraceContext of this trace source will also - * be automatically extended to contain the input context. - */ - template - void Add (std::string name, - CallbackTraceSource &trace, T const &context); - /** - * \param name name of trace source - * \param trace a signed variable trace source - * \param context the context associated to this trace source - * - * Add a signed variable trace source in this resolver. - * This trace source will match the name specified during namespace - * resolution. The TraceContext of this trace source will also - * be automatically extended to contain the input context. - */ - template - void Add (std::string name, - SVTraceSource &trace, T const &context); - /** - * \param name name of trace source - * \param trace an unsigned variable trace source - * \param context the context associated to this trace source - * - * Add an unsigned variable trace source in this resolver. - * This trace source will match the name specified during namespace - * resolution. The TraceContext of this trace source will also - * be automatically extended to contain the input context. - */ - template - void Add (std::string name, - UVTraceSource &trace, T const &context); - /** - * \param name name of trace source - * \param trace a floating-point variable trace source - * \param context the context associated to this trace source - * - * Add a floating-point variable trace source in this resolver. - * This trace source will match the name specified during namespace - * resolution. The TraceContext of this trace source will also - * be automatically extended to contain the input context. - */ - template - void Add (std::string name, - FVTraceSource &trace, T const &context); - - /** - * \param name name of child trace resolver - * \param createResolver a trace resolver constructor - * \param context the context associated to this entry - * - * Add a child trace resolver to this resolver. This child - * trace resolver will match the name specified during - * namespace resolution. When this happens, the constructor - * will be invoked to create the child trace resolver and - * the associated TraceContext will be automatically extended - * to contain the input context. - */ - template - void Add (std::string name, - Callback createResolver, - T const &context); - - /** - * \param name name of child trace resolver - * \param createResolver a trace resolver constructor - * - * Add a child trace resolver to this resolver. This child - * trace resolver will match the name specified during - * namespace resolution. When this happens, the constructor - * will be invoked to create the child trace resolver. - */ - void Add (std::string name, - Callback createResolver); -private: - template - void DoAddTraceSource (std::string name, - SOURCE &traceSource, CONTEXT const &context); - template - static TraceResolver *CreateTerminalTraceResolver (SOURCE *trace, - TraceContext const &context); - void DoAdd (std::string name, - Callback createResolver, - TraceContext const &context); - virtual TraceResolverList DoLookup (std::string id) const; - - struct CallbackTraceSourceItem - { - std::string name; - Callback createResolver; - TraceContext context; - }; - - typedef std::list TraceItems; - TraceItems m_items; -}; - -}//namespace ns3 - -namespace ns3 { - -template -void -CompositeTraceResolver::DoAddTraceSource (std::string name, - SOURCE &traceSource, CONTEXT const &context) -{ - TraceContext traceContext = GetContext (); - traceContext.Add (context); - TraceResolver *(*create) (SOURCE *trace, TraceContext const &context); - create = &CompositeTraceResolver::CreateTerminalTraceResolver; - Callback createResolver = - MakeBoundCallback (create, &traceSource); - DoAdd (name, createResolver, traceContext); -} - -template -TraceResolver * -CompositeTraceResolver::CreateTerminalTraceResolver (SOURCE *traceSource, - TraceContext const &context) -{ - return new TerminalTraceResolver (*traceSource, context); -} - - - - -template -void -CompositeTraceResolver::Add (std::string name, - CallbackTraceSource &trace, - T const &context) -{ - DoAddTraceSource (name, trace, context); -} -template -void -CompositeTraceResolver::Add (std::string name, - SVTraceSource &trace, T const &context) -{ - DoAddTraceSource (name, trace, context); -} -template -void -CompositeTraceResolver::Add (std::string name, - UVTraceSource &trace, T const &context) -{ - DoAddTraceSource (name, trace, context); -} -template -void -CompositeTraceResolver::Add (std::string name, - FVTraceSource &trace, T const &context) -{ - DoAddTraceSource (name, trace, context); -} -template -void -CompositeTraceResolver::Add (std::string name, - Callback createResolver, - T const &context) -{ - TraceContext traceContext = GetContext (); - traceContext.Add (context); - DoAdd (name, createResolver, traceContext); -} - -}//namespace ns3 - -#endif /* COMPOSITE_TRACE_RESOLVER_H */ diff --git a/src/common/empty-trace-resolver.h b/src/common/empty-trace-resolver.h deleted file mode 100644 index 04f1c1bc4..000000000 --- a/src/common/empty-trace-resolver.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2007 INRIA - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Mathieu Lacage - */ -#ifndef EMPTY_TRACE_RESOLVER_H -#define EMPTY_TRACE_RESOLVER_H - -#include "trace-resolver.h" - -namespace ns3 { - -class TraceContext; - -/** - * \brief a TraceResolver instance which does not resolve anything. - * \ingroup tracing - * - * Trying to resolve against this class will yield no matches and no - * connections. Returning an instance of this class from a - * CreateTraceResolver method is a hand way of not implementing - * any Tracing code. - */ -class EmptyTraceResolver : public TraceResolver -{ -public: - /** - * \param o necessary context for this class. - * - * The only constructor exported by this class. - */ - EmptyTraceResolver (TraceContext const &o); -}; - -}//namespace ns3 - -#endif /* EMPTY_TRACE_RESOLVER_H */ diff --git a/src/common/packet.cc b/src/common/packet.cc index 5159f3e2c..0de766dba 100644 --- a/src/common/packet.cc +++ b/src/common/packet.cc @@ -199,6 +199,12 @@ Packet::Deserialize (Buffer buffer) buffer.RemoveAtStart (metadataDeserialized); } +std::ostream& operator<< (std::ostream& os, const Packet &packet) +{ + packet.Print (os); + return os; +} + } // namespace ns3 diff --git a/src/common/packet.h b/src/common/packet.h index 00c540600..f1e14cf02 100644 --- a/src/common/packet.h +++ b/src/common/packet.h @@ -328,6 +328,8 @@ private: static uint32_t m_globalUid; }; +std::ostream& operator<< (std::ostream& os, const Packet &packet); + /** * \defgroup packetperf Packet Performance * The current implementation of the byte buffers and tag list is based diff --git a/src/common/terminal-trace-resolver.h b/src/common/terminal-trace-resolver.h deleted file mode 100644 index e026d07cb..000000000 --- a/src/common/terminal-trace-resolver.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2007 INRIA - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Mathieu Lacage - */ -#ifndef TERMINAL_TRACE_RESOLVER_H -#define TERMINAL_TRACE_RESOLVER_H - -#include "trace-resolver.h" - -namespace ns3 { - -class TraceContext; - -template -class TerminalTraceResolver : public TraceResolver -{ - public: - TerminalTraceResolver (T &traceSource, TraceContext const &context); - private: - virtual void DoConnect (CallbackBase const &cb); - virtual void DoDisconnect (CallbackBase const &cb); - T &m_traceSource; -}; - -}//namespace ns3 - -namespace ns3 { - -template -TerminalTraceResolver::TerminalTraceResolver (T &traceSource, - TraceContext const &context) - : TraceResolver (context), - m_traceSource (traceSource) -{} -template -void -TerminalTraceResolver::DoConnect (CallbackBase const &cb) -{ - m_traceSource.AddCallback (cb, GetContext ()); -} -template -void -TerminalTraceResolver::DoDisconnect (CallbackBase const &cb) -{ - m_traceSource.RemoveCallback (cb); -} - -}//namespace ns3 - -#endif /* TERMINAL_TRACE_RESOLVER_H */ diff --git a/src/common/trace-resolver.cc b/src/common/trace-resolver.cc deleted file mode 100644 index 251e7cc87..000000000 --- a/src/common/trace-resolver.cc +++ /dev/null @@ -1,104 +0,0 @@ -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2007 INRIA - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Mathieu Lacage - */ -#include "trace-resolver.h" - -namespace ns3 { - -TraceResolver::TraceResolver (TraceContext const &context) - : m_context (context) -{} - -TraceResolver::~TraceResolver () -{} - -TraceContext const & -TraceResolver::GetContext (void) const -{ - return m_context; -} - -void -TraceResolver::Connect (std::string path, CallbackBase const &cb) -{ - std::string::size_type cur = 1; - // check that first char is "/" - std::string::size_type next = path.find ("/", cur); - std::string element = std::string (path, cur, next-1); - TraceResolverList resolverList = DoLookup (element); - for (TraceResolverList::iterator i = resolverList.begin (); i != resolverList.end (); i++) - { - TraceResolver *resolver = *i; - if (next == std::string::npos) - { - // we really break the recursion here. - resolver->DoConnect (cb); - } - else - { - std::string subpath = std::string (path, next, std::string::npos); - resolver->Connect (subpath, cb); - } - delete resolver; - } - resolverList.erase (resolverList.begin (), resolverList.end ()); -} - -void -TraceResolver::Disconnect (std::string path, CallbackBase const &cb) -{ - std::string::size_type cur = 1; - // check that first char is "/" - std::string::size_type next = path.find ("/", cur); - std::string element = std::string (path, cur, next-1); - TraceResolverList resolverList = DoLookup (element); - for (TraceResolverList::iterator i = resolverList.begin (); i != resolverList.end (); i++) - { - TraceResolver *resolver = *i; - if (next == std::string::npos) - { - // we really break the recursion here. - resolver->DoDisconnect (cb); - } - else - { - std::string subpath = std::string (path, next, std::string::npos); - resolver->Disconnect (subpath, cb); - } - delete resolver; - } - resolverList.erase (resolverList.begin (), resolverList.end ()); -} - -TraceResolver::TraceResolverList -TraceResolver::DoLookup (std::string id) const -{ - return TraceResolverList (); -} -void -TraceResolver::DoConnect (CallbackBase const &cb) -{} - -void -TraceResolver::DoDisconnect (CallbackBase const &cb) -{} - - -}//namespace ns3 diff --git a/src/common/trace-resolver.h b/src/common/trace-resolver.h deleted file mode 100644 index 93bf43095..000000000 --- a/src/common/trace-resolver.h +++ /dev/null @@ -1,119 +0,0 @@ -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2007 INRIA - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Mathieu Lacage - */ -#ifndef TRACE_RESOLVER_H -#define TRACE_RESOLVER_H - -#include -#include -#include "trace-context.h" - -namespace ns3 { - -class CallbackBase; - -/** - * \brief the base class which is used to incremental perform trace - * namespace resolution. - * \ingroup lowleveltracing - * - * This class provides a public API to the ns3::TraceRoot object: - * - ns3::TraceResolver::Connect - * - ns3::TraceResolver::Disconnect - * - * It also provides an API for its subclasses. Each subclass should - * implement one of: - * - ns3::TraceResolver::DoLookup - * - ns3::TraceResolver::DoConnect and ns3::TraceResolver::DoDisconnect - * Each subclass must also provide an ns3::TraceContext to the TraceResolver - * constructor. Finally, each subclass can access the ns3::TraceContext - * associated to this ns3::TraceResolver through the - * ns3::TraceResolver::GetContext method. - */ -class TraceResolver -{ -public: - virtual ~TraceResolver (); - /** - * \param path the namespace path to resolver - * \param cb the callback to connect to the matching namespace - * - * This method is typically invoked by ns3::TraceRoot but advanced - * users could also conceivably call it directly if they want to - * skip the ns3::TraceRoot. - */ - void Connect (std::string path, CallbackBase const &cb); - /** - * \param path the namespace path to resolver - * \param cb the callback to disconnect in the matching namespace - * - * This method is typically invoked by ns3::TraceRoot but advanced - * users could also conceivably call it directly if they want to - * skip the ns3::TraceRoot. - */ - void Disconnect (std::string path, CallbackBase const &cb); -protected: - /** - * \param context the context used to initialize this TraceResolver. - * - * Every subclass must call this constructor - */ - TraceResolver (TraceContext const &context); - /** - * \returns the ns3::TraceContext stored in this ns3::TraceResolver. - * - * Subclasses usually invoke this method to get access to the - * TraceContext stored here to pass it down to the TraceResolver - * constructors invoked from within the DoLookup method. - */ - TraceContext const &GetContext (void) const; - typedef std::list TraceResolverList; -private: - TraceResolver (); - /** - * \param id the id to resolve. This is supposed to be - * one element of the global tracing namespace. - * \returns a list of reslvers which match the input namespace element - * - * A subclass which overrides this method should return a potentially - * empty list of pointers to ns3::TraceResolver instances which match - * the input namespace element. Each of these TraceResolver should be - * instanciated with a TraceContext which holds enough context - * information to identify the type of the TraceResolver. - */ - virtual TraceResolverList DoLookup (std::string id) const; - /** - * \param cb callback to connect - * - * This method is invoked on leaf trace resolvers. - */ - virtual void DoConnect (CallbackBase const &cb); - /** - * \param cb callback to disconnect - * - * This method is invoked on leaf trace resolvers. - */ - virtual void DoDisconnect (CallbackBase const &cb); - TraceContext m_context; -}; - -}//namespace ns3 - -#endif /* TRACE_RESOLVER_H */ diff --git a/src/common/trace-root.cc b/src/common/trace-root.cc deleted file mode 100644 index 5bb270b8c..000000000 --- a/src/common/trace-root.cc +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2007 INRIA - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Mathieu Lacage - */ -#include "trace-root.h" -#include "ns3/composite-trace-resolver.h" -#include "ns3/trace-context.h" - -namespace ns3 { - -void -TraceRoot::Connect (std::string path, CallbackBase const &cb) -{ - TraceResolver *resolver = GetComposite (); - resolver->Connect (path, cb); -} -void -TraceRoot::Disconnect (std::string path, CallbackBase const &cb) -{ - TraceResolver *resolver = GetComposite (); - resolver->Disconnect (path, cb); -} -void -TraceRoot::Register (std::string name, - Callback createResolver) -{ - CompositeTraceResolver *resolver = GetComposite (); - resolver->Add (name, createResolver); -} - -CompositeTraceResolver * -TraceRoot::GetComposite (void) -{ - static CompositeTraceResolver resolver = CompositeTraceResolver (TraceContext ()); - return &resolver; -} - -} // namespace ns3 diff --git a/src/common/trace-root.h b/src/common/trace-root.h deleted file mode 100644 index a07f923cd..000000000 --- a/src/common/trace-root.h +++ /dev/null @@ -1,335 +0,0 @@ -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2007 INRIA - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Mathieu Lacage - */ -#ifndef TRACE_ROOT_H -#define TRACE_ROOT_H - -#include -#include "ns3/callback.h" - -/** - * \defgroup lowleveltracing Low-level tracing - * - * This low-level API is built around a few concepts: - * - There can be any number of trace source objects. Each trace source - * object can generate any number of trace events. The current - * trace source objects are: ns3::CallbackTraceSourceSource, ns3::UVTraceSource, - * ns3::SVTraceSource, and, ns3::FVTraceSource. - * - Each trace source can be connected to any number of trace sinks. - * A trace sink is a ns3::Callback with a very special signature. Its - * first argument is always a ns3::TraceContext. - * - Every trace source is uniquely identified by a ns3::TraceContext. Every - * trace sink can query a ns3::TraceContext for information. This allows - * a trace sink which is connected to multiple trace sources to identify - * from which source each event is coming from. - * - * To define new trace sources, a model author needs to instante one trace source - * object for each kind of tracing event he wants to export. The trace source objects - * currently defined are: - * - ns3::CallbackTraceSourceSource: this trace source can be used to convey any kind of - * trace event to the user. It is a functor, that is, it is a variable - * which behaves like a function which will forward every event to every - * connected trace sink (i.e., ns3::Callback). This trace source takes - * up to four arguments and forwards these 4 arguments together with the - * ns3::TraceContext which identifies this trace source to the connected - * trace sinks. - * - ns3::UVTraceSource: this trace source is used to convey key state variable - * changes to the user. It behaves like a normal integer unsigned variable: - * you can apply every normal arithmetic operator to it. It will forward - * every change in the value of the variable back to every connected trace - * sink by providing a TraceContext, the old value and the new value. - * - ns3::SVTraceSource: this is the signed integer equivalent of - * ns3::UVTraceSource. - * - ns3::FVTraceSource: this is the floating point equivalent of - * ns3::UVTraceSource and ns3::SVTraceSource. - * - * For example, to define a trace source which notifies you of a new packet - * being transmitted, you would have to: - * \code - * class MyModel - * { - * public: - * void Tx (Packet const &p); - * private: - * CallbackTraceSource m_txTrace; - * }; - * - * void - * MyModel::Tx (Packet const &p) - * { - * // trace packet tx event. - * m_txTrace (p); - * // ... send the packet for real. - * } - * \endcode - * - * Once the model author has instantiated these objects and has wired them - * in his simulation code (that is, he calls them wherever he wants to trigger - * a trace event), he needs to make these trace sources available to users - * to allow them to connect any number of trace sources to any number - * of user trace sinks. While it would be possible to make each model - * export directly each of his trace source instances and request users to - * invoke a source->Connect (callback) method to perform the connection - * explicitely, it was felt that this was a bit cumbersome to do. - * - * As such, the ``connection'' between a set of sources and a sink is - * performed through a third-party class, the TraceResolver, which - * can be used to automate the connection of multiple matching trace sources - * to a single sink. This TraceResolver works by defining a hierarchical - * tracing namespace: the root of this namespace is accessed through the - * ns3::TraceRoot class. The namespace is represented as a string made of - * multiple elements, each of which is separated from the other elements - * by the '/' character. A namespace string always starts with a '/'. - * - * By default, the current simulation models provide a '/nodes' tracing root. - * This '/nodes' namespace is structured as follows: - * \code - * /nodes/n/arp - * /nodes/n/udp - * /nodes/n/ipv4 - * /tx - * /rx - * /drop - * /interfaces/n/netdevice - * /queue/ - * /enque - * /deque - * /drop - * \endcode - * - * The 'n' element which follows the /nodes and /interfaces namespace elements - * identify a specific node and interface through their index within the - * ns3::NodeList and ns3::Ipv4 objects respectively. - * - * To connect a trace sink to a trace source identified by a namespace string, - * a user can call the ns3::TraceRoot::Connect method (the ns3::TraceRoot::Disconnect - * method does the symmetric operation). This connection method can accept - * fully-detailed namespace strings but it can also perform pattern matching - * on the user-provided namespace strings to connect multiple trace sources - * to a single trace sink in a single connection operation. - * - * The syntax of the pattern matching rules are loosely based on regular - * expressions: - * - the '*' character matches every element - * - the (a|b) construct matches element 'a' or 'b' - * - the [ss-ee] construct matches all numerical values which belong - * to the interval which includes ss and ee - * - * For example, the user could use the following to connect a single sink - * to the ipv4 tx, rx, and drop trace events: - * - * \code - * void MyTraceSink (TraceContext const &context, Packet &packet); - * TraceRoot::Connect ("/nodes/ * /ipv4/ *", MakeCallback (&MyTraceSink)); - * \endcode - * - * Of course, this code would work only if the signature of the trace sink - * is exactly equal to the signature of all the trace sources which match - * the namespace string (if one of the matching trace source does not match - * exactly, a fatal error will be triggered at runtime during the connection - * process). The ns3::TraceContext extra argument contains - * information on where the trace source is located in the namespace tree. - * In that example, if there are multiple nodes in this scenario, each - * call to the MyTraceSink function would receive a different TraceContext, - * each of which would contain a different NodeList::NodeIndex object. - * - * It is important to understand exactly what an ns3::TraceContext - * is. It is a container for a number of type instances. Each instance of - * a ns3::TraceContext contains one and only one instance of a given type. - * ns3::TraceContext::Add can be called to add a type instance into a - * TraceContext instance and ns3::TraceContext::Get can be called to get - * a copy of a type instance stored into the ns3::TraceContext. If ::Get - * cannot retrieve the requested type, a fatal error is triggered at - * runtime. The values stored into an ns3::TraceContext attached to a - * trace source are automatically determined during the namespace - * resolution process. To retrieve a value from a ns3::TraceContext, the - * code can be as simple as this: - * \code - * void MyTraceSink (TraceContext const &context, Packet &packet) - * { - * NodeList::NodeIndex index; - * context.Get (index); - * std::cout << "node id=" << NodeList::GetNode (index)->GetId () << std::endl; - * } - * \endcode - * - * The hierarchical global namespace described here is not implemented - * in a single central location: it was felt that doing this would make - * it too hard to introduce user-specific models which could hook - * automatically into the overal tracing system. If the tracing - * namespace was implemented in a single central location, every model - * author would have had to modify this central component to make - * his own model available to trace users. - * - * Instead, the handling of the namespace is distributed across every relevant - * model: every model implements only the part of the namespace it is - * really responsible for. To do this, every model is expected - * to provide an instance of a TraceResolver whose - * responsability is to recursively provide access to the trace sources - * defined in its model. Each TraceResolver instance should be a subclass - * of the TraceResolver base class which implements either the DoLookup - * or the DoConnect and DoDisconnect methods. Because implementing these - * methods can be a bit tedious, our tracing framework provides a number - * of helper template classes which should save the model author from - * having to implement his own in most cases: - * - ns3::CompositeTraceResolver: this subclass of ns3::TraceResolver can - * be used to aggregate together multiple trace sources and multiple other - * ns3::TraceResolver instances. - * - ns3::ArrayTraceResolver: this subclass of ns3::TraceResolver can be - * used to match any number of elements within an array where every element - * is identified by its index. - * - * Once you can instantiate your own ns3::TraceResolver object instance, you - * have to hook it up into the global namespace. There are two ways to do this: - * - you can hook your ns3::TraceResolver creation method as a new trace - * root by using the ns3::TraceRoot::Register method - * - you can hook your new ns3::TraceResolver creation method into the - * container of your model. This step will obvsiouly depend on which model - * contains your own model but, if you wrote a new l3 protocol, all you - * would have to do to hook into your container L3Demux class is to implement - * the pure virtual method inherited from the L3Protocol class whose name is - * ns3::L3protocol::CreateTraceResolver. - * - * So, in most cases, exporting a model's trace sources is a matter of - * implementing a method CreateTraceResolver as shown below: - * \code - * class MyModel - * { - * public: - * enum TraceType { - * TX, - * RX, - * ... - * }; - * TraceResolver *CreateTraceResolver (TraceContext const &context); - * void Tx (Packet const &p); - * private: - * CallbackTraceSource m_txTrace; - * }; - * - * TraceResolver * - * MyModel::CreateTraceResolver (TraceContext const &context) - * { - * CompositeTraceResolver *resolver = new CompositeTraceResolver (context); - * resolver->Add ("tx", m_txTrace, MyModel::TX); - * return resolver; - * } - * void - * MyModel::Tx (Packet const &p) - * { - * m_txTrace (p); - * } - * \endcode - * - * If you really want to have fun and implement your own ns3::TraceResolver - * subclass, you need to understand the basic Connection and Disconnection - * algorithm. The code of that algorithm is wholy contained in the - * ns3::TraceResolver::Connect and ns3::TraceResolver::Disconnect methods. - * The idea is that we recursively parse the input namespace string by removing - * the first namespace element. This element is 'resolved' is calling - * the ns3::TraceResolver::DoLookup method which returns a list of - * TraceResolver instances. Each of the returned TraceResolver instance is - * then given what is left of the namespace by calling ns3::TraceResolver::Connect - * until the last namespace element is processed. At this point, we invoke - * the ns3::TraceResolver::DoConnect or ns3::TraceResolver::DoDisconnect - * methods to break the recursion. A good way to understand this algorithm - * is to trace its behavior. Let's say that you want to connect to - * '/nodes/ * /ipv4/interfaces/ * /netdevice/queue/ *'. It would generate - * the following call traces: - * - * \code - * TraceRoot::Connect ("/nodes/ * /ipv4/interfaces/ * /netdevice/queue/ *", callback); - * traceContext = TraceContext (); - * rootResolver = CompositeTraceResolver (traceContext); - * rootResolver->Connect ("/nodes/ * /ipv4/interfaces/ * /netdevice/queue/ *", callback); - * resolver = CompositeTraceResolver::DoLookup ("nodes"); - * return NodeList::CreateTraceResolver (GetContext ()); - * return ArrayTraceResolver (context); - * resolver->Connect ("/ * /ipv4/interfaces/ * /netdevice/queue/ *", callback); - * ArrayTraceResolver::DoLookup ("*"); - * for (i = 0; i < n_nodes; i++) - * resolver = nodes[i]->CreateTraceResolver (GetContext ()); - * return CompositeTraceResolver (context); - * resolvers.add (resolver); - * return resolvers; - * for resolver in (resolvers) - * resolver->Connect ("/ipv4/interfaces/ * /netdevice/queue/ *", callback); - * CompositeTraceResolver::DoLookup ("ipv4"); - * resolver = ipv4->CreateTraceResolver (GetContext ()); - * return CompositeTraceResolver (context); - * return resolver; - * resolver->Connect ("/interfaces/ * /netdevice/queue/ *", callback); - * CompositeTraceResolver::DoLookup ("interfaces"); - * resolver = ArrayTraceResolver (GetContext ()); - * resolver->Connect ("/ * /netdevice/queue/ *", callback); - * ArrayTraceResolver::DoLookup ("*"); - * for (i = 0; i < n_interfaces; i++) - * resolver = interfaces[i]->CreateTraceResolver (GetContext ()); - * return CompositeTraceResolver () - * resolvers.add (resolver); - * return resolvers; - * resolver->Connect ("/netdevice/queue/ *", callback); - * CompositeTraceResolver::DoLookup ("netdevice"); - * resolver = NetDevice::CreateTraceResolver (GetContext ()); - * return CompositeTraceResolver (); - * return resolver; - * resolver->Connect ("/queue/ *", callback); - * CompositeTraceResolver::DoLookup ("queue"); - * resolver = Queue::CreateTraceResolver (GetContext ()); - * return CompositeTraceResolver (); - * return resolver - * resolver->Connect ("*", callback); - * CompositeTraceResolver::DoLookup ("*"); - * for match in (matches) - * resolver = TerminalTraceResolver ("match"); - * resolvers.add (resolver) - * return resolvers; - * for resolver in (resolvers) - * TerminalTraceResolver->DoConnect (callback); - * \endcode - */ - -namespace ns3 { - -class CompositeTraceResolver; -class TraceResolver; -class TraceContext; -class CallbackBase; - -/** - * \brief The main class used to access tracing functionality for - * a user. - * - * \ingroup lowleveltracing - */ -class TraceRoot -{ -public: - static void Connect (std::string path, CallbackBase const &cb); - static void Disconnect (std::string path, CallbackBase const &cb); - static void Register (std::string name, - Callback createResolver); -private: - static CompositeTraceResolver *GetComposite (void); -}; - -}// namespace ns3 - -#endif /* TRACE_ROOT_H */ diff --git a/src/common/wscript b/src/common/wscript index c6e9cb45d..2472ecd1e 100644 --- a/src/common/wscript +++ b/src/common/wscript @@ -12,14 +12,6 @@ def build(bld): 'tags.cc', 'tag-registry.cc', 'pcap-writer.cc', - 'variable-tracer-test.cc', - 'trace-context.cc', - 'trace-context-element.cc', - 'trace-resolver.cc', - 'callback-trace-source.cc', - 'empty-trace-resolver.cc', - 'composite-trace-resolver.cc', - 'trace-root.cc', 'data-rate.cc', ] @@ -35,18 +27,6 @@ def build(bld): 'packet.h', 'packet-printer.h', 'packet-metadata.h', - 'uv-trace-source.h', - 'sv-trace-source.h', - 'fv-trace-source.h', 'pcap-writer.h', - 'callback-trace-source.h', - 'trace-context.h', - 'trace-context-element.h', - 'trace-resolver.h', - 'empty-trace-resolver.h', - 'composite-trace-resolver.h', - 'array-trace-resolver.h', - 'trace-root.h', - 'terminal-trace-resolver.h', 'data-rate.h', ] diff --git a/src/core/array-trace-resolver.h b/src/core/array-trace-resolver.h new file mode 100644 index 000000000..ecbc63d5d --- /dev/null +++ b/src/core/array-trace-resolver.h @@ -0,0 +1,205 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 INRIA + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Mathieu Lacage + */ +#ifndef ARRAY_TRACE_RESOLVER_H +#define ARRAY_TRACE_RESOLVER_H + +#include +#include +#include "callback.h" +#include "trace-resolver.h" +#include "object.h" + +namespace ns3 { + +/** + * \brief a helper class to offer trace resolution for an array of objects. + * \ingroup tracing + * + * \class ArrayTraceResolver + * + * An ArrayTraceResolver is a resolver which can match any input integer + * against an element in an array. The array is accessed using a + * pair iterators. Each element of the array is expected + * to be a subclass of the Object base class. + * + * When the Connect method is called, this trace resolver will + * automatically store in the TraceContext of each resolved object + * its index through an object of type INDEX specified during the + * instanciation of the ArrayTraceResolver template. + */ +template +class ArrayTraceResolver : public TraceResolver +{ +public: + ArrayTraceResolver (); + ~ArrayTraceResolver (); + + /** + * \param begin an iterator which points to the start of the array. + * \param end an iterator which points to the end of the array. + */ + template + void SetIterators (T begin, T end); + + // inherited from TraceResolver + virtual void Connect (std::string path, CallbackBase const &cb, const TraceContext &context); + virtual void Disconnect (std::string path, CallbackBase const &cb); + virtual void CollectSources (std::string path, const TraceContext &context, + SourceCollection *collection); + virtual void TraceAll (std::ostream &os, const TraceContext &context); + +private: + class IteratorBase + { + public: + virtual ~IteratorBase () {} + virtual void Next (void) = 0; + virtual bool HasNext (void) = 0; + virtual Ptr Get (void) = 0; + virtual void Rewind (void) = 0; + }; + IteratorBase *m_iter; +}; +}//namespace ns3 + + +// implementation +namespace ns3 { + +template +ArrayTraceResolver::ArrayTraceResolver () + : m_iter (0) +{} + +template +ArrayTraceResolver::~ArrayTraceResolver () +{ + delete m_iter; +} + +template +template +void +ArrayTraceResolver::SetIterators (T begin, T end) +{ + class Iterator : public IteratorBase + { + public: + Iterator (T begin, T end) + : m_begin (begin), m_end (end), m_cur (begin) + {} + virtual void Next (void) + {m_cur++;} + virtual bool HasNext (void) + {return m_cur != m_end;} + virtual Ptr Get (void) + {return *m_cur;} + virtual void Rewind (void) + {m_cur = m_begin;} + private: + T m_begin; + T m_end; + T m_cur; + }; + delete m_iter; + m_iter = new Iterator (begin, end); +} + +template +void +ArrayTraceResolver::Connect (std::string path, CallbackBase const &cb, const TraceContext &context) +{ + if (path == "") + { + return; + } + std::string id = GetElement (path); + std::string subpath = GetSubpath (path); + if (id == "*") + { + uint32_t j = 0; + for (m_iter->Rewind (); m_iter->HasNext (); m_iter->Next ()) + { + TraceContext tmp = context; + INDEX index = j; + tmp.AddElement (index); + Ptr obj = m_iter->Get (); + obj->GetTraceResolver ()->Connect (subpath, cb, tmp); + j++; + } + } +} +template +void +ArrayTraceResolver::Disconnect (std::string path, CallbackBase const &cb) +{ + if (path == "") + { + return; + } + std::string id = GetElement (path); + std::string subpath = GetSubpath (path); + if (id == "*") + { + for (m_iter->Rewind (); m_iter->HasNext (); m_iter->Next ()) + { + Ptr obj = m_iter->Get (); + obj->TraceDisconnect (subpath, cb); + } + } +} +template +void +ArrayTraceResolver::CollectSources (std::string path, const TraceContext &context, + SourceCollection *collection) +{ + path.append ("/[0-n]"); + uint32_t j = 0; + for (m_iter->Rewind (); m_iter->HasNext (); m_iter->Next ()) + { + TraceContext tmp = context; + INDEX index = j; + tmp.AddElement (index); + Ptr obj = m_iter->Get (); + obj->GetTraceResolver ()->CollectSources (path, tmp, collection); + j++; + } +} + +template +void +ArrayTraceResolver::TraceAll (std::ostream &os, const TraceContext &context) +{ + uint32_t j = 0; + for (m_iter->Rewind (); m_iter->HasNext (); m_iter->Next ()) + { + TraceContext tmp = context; + INDEX index = j; + tmp.AddElement (index); + Ptr obj = m_iter->Get (); + obj->GetTraceResolver ()->TraceAll (os, tmp); + j++; + } +} + +}//namespace ns3 + +#endif /* ARRAY_TRACE_RESOLVER_H */ diff --git a/src/core/callback-test.cc b/src/core/callback-test.cc index 9e8cf259f..4fb062321 100644 --- a/src/core/callback-test.cc +++ b/src/core/callback-test.cc @@ -57,6 +57,21 @@ void *Test10 (bool *a, int const & b) return a; } +void TestFZero (void) {} +void TestFOne (int) {} +void TestFTwo (int, int) {} +void TestFThree (int, int, int) {} +void TestFFour (int, int, int, int) {} +void TestFFive (int, int, int, int, int) {} +void TestFSix (int, int, int, int, int, int) {} + +void TestFROne (int &) {} +void TestFRTwo (int &, int &) {} +void TestFRThree (int &, int &, int &) {} +void TestFRFour (int &, int &, int &, int &) {} +void TestFRFive (int &, int &, int &, int &, int &) {} +void TestFRSix (int &, int &, int &, int &, int &, int &) {} + class CallbackTest : public ns3::Test { private: bool m_test1; @@ -73,6 +88,22 @@ public: void Test3 (double a); int Test4 (double a, int b); void Test8 (Callback callback); + + void TestZero (void) {} + void TestOne (int) {} + void TestTwo (int, int) {} + void TestThree (int, int, int) {} + void TestFour (int, int, int, int) {} + void TestFive (int, int, int, int, int) {} + void TestSix (int, int, int, int, int, int) {} + + void TestCZero (void) const {} + void TestCOne (int) const {} + void TestCTwo (int, int) const {} + void TestCThree (int, int, int) const {} + void TestCFour (int, int, int, int) const {} + void TestCFive (int, int, int, int, int) const {} + void TestCSix (int, int, int, int, int, int) const {} }; CallbackTest::CallbackTest () @@ -110,6 +141,7 @@ CallbackTest::Test8 (Callback callback) { callback (3); } + bool CallbackTest::IsWrong (void) { @@ -216,6 +248,53 @@ CallbackTest::RunTests (void) MakeBoundCallback (&Test9, &v); MakeBoundCallback (&Test10, &v); + + MakeCallback (&CallbackTest::TestZero, this); + MakeCallback (&CallbackTest::TestOne, this); + MakeCallback (&CallbackTest::TestTwo, this); + MakeCallback (&CallbackTest::TestThree, this); + MakeCallback (&CallbackTest::TestFour, this); + MakeCallback (&CallbackTest::TestFive, this); + MakeCallback (&CallbackTest::TestSix, this); + + MakeCallback (&CallbackTest::TestCZero, this); + MakeCallback (&CallbackTest::TestCOne, this); + MakeCallback (&CallbackTest::TestCTwo, this); + MakeCallback (&CallbackTest::TestCThree, this); + MakeCallback (&CallbackTest::TestCFour, this); + MakeCallback (&CallbackTest::TestCFive, this); + MakeCallback (&CallbackTest::TestCSix, this); + + MakeCallback (&TestFZero); + MakeCallback (&TestFOne); + MakeCallback (&TestFTwo); + MakeCallback (&TestFThree); + MakeCallback (&TestFFour); + MakeCallback (&TestFFive); + MakeCallback (&TestFSix); + + MakeCallback (&TestFROne); + MakeCallback (&TestFRTwo); + MakeCallback (&TestFRThree); + MakeCallback (&TestFRFour); + MakeCallback (&TestFRFive); + MakeCallback (&TestFRSix); + + + MakeBoundCallback (&TestFOne, 1); + MakeBoundCallback (&TestFTwo, 1); + MakeBoundCallback (&TestFThree, 1); + MakeBoundCallback (&TestFFour, 1); + MakeBoundCallback (&TestFFive, 1); + + MakeBoundCallback (&TestFROne, 1); + MakeBoundCallback (&TestFRTwo, 1); + MakeBoundCallback (&TestFRThree, 1); + MakeBoundCallback (&TestFRFour, 1); + MakeBoundCallback (&TestFRFive, 1); + + + return ok; } diff --git a/src/common/callback-trace-source.cc b/src/core/callback-trace-source.cc similarity index 80% rename from src/common/callback-trace-source.cc rename to src/core/callback-trace-source.cc index d35b4f860..02298520e 100644 --- a/src/common/callback-trace-source.cc +++ b/src/core/callback-trace-source.cc @@ -19,7 +19,10 @@ * Author: Mathieu Lacage */ #include "callback-trace-source.h" -#include "ns3/test.h" + +#ifdef RUN_SELF_TESTS + +#include "test.h" namespace ns3 { @@ -55,7 +58,7 @@ CallbackTraceSourceTest::CbTwo (TraceContext const &context, uint8_t a, double b bool CallbackTraceSourceTest::RunTests (void) { - bool ok = true; + bool result = true; TraceContext ctx; CallbackTraceSource trace; @@ -64,32 +67,35 @@ CallbackTraceSourceTest::RunTests (void) m_one = false; m_two = false; trace (1, 2); - if (!m_one || !m_two) - { - ok = false; - } + NS_TEST_ASSERT (m_one); + NS_TEST_ASSERT (m_two); + trace.RemoveCallback (MakeCallback (&CallbackTraceSourceTest::CbOne, this)); m_one = false; m_two = false; trace (1, 2); - if (m_one || !m_two) - { - ok = false; - } + NS_TEST_ASSERT (!m_one); + NS_TEST_ASSERT (m_two); trace.RemoveCallback (MakeCallback (&CallbackTraceSourceTest::CbTwo, this)); m_one = false; m_two = false; trace (1, 2); - if (m_one || m_two) - { - ok = false; - } + NS_TEST_ASSERT (!m_one); + NS_TEST_ASSERT (!m_two); - return ok; + trace.AddCallback (MakeCallback (&CallbackTraceSourceTest::CbOne, this), ctx); + trace.AddCallback (MakeCallback (&CallbackTraceSourceTest::CbTwo, this), ctx); + m_one = false; + m_two = false; + trace (1, 2); + NS_TEST_ASSERT (m_one); + NS_TEST_ASSERT (m_two); + + return result; } CallbackTraceSourceTest g_callbackTraceTest; - - }//namespace ns3 + +#endif /* RUN_SELF_TESTS */ diff --git a/src/core/callback-trace-source.h b/src/core/callback-trace-source.h new file mode 100644 index 000000000..2e302cdc2 --- /dev/null +++ b/src/core/callback-trace-source.h @@ -0,0 +1,251 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2005,2006,2007 INRIA + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Mathieu Lacage + */ + +#ifndef CALLBACK_TRACE_H +#define CALLBACK_TRACE_H + +#include +#include "callback.h" +#include "fatal-error.h" +#include "trace-context.h" +#include "trace-source.h" + +namespace ns3 { + +/** + * \brief log arbitrary number of parameters to a matching ns3::Callback + * \ingroup tracing + * + * Whenever operator () is invoked on this class, the call and its arguments + * are forwarded to the internal matching ns3::Callback. + */ +template +class CallbackTraceSource : public TraceSource { +public: + CallbackTraceSource (); + virtual void AddCallback (CallbackBase const & callback, TraceContext const & context); + virtual void RemoveCallback (CallbackBase const & callback); + virtual void ConnectPrinter (std::ostream &os, const TraceContext &context); + void operator() (void) const; + void operator() (T1 a1) const; + void operator() (T1 a1, T2 a2) const; + void operator() (T1 a1, T2 a2, T3 a3) const; + void operator() (T1 a1, T2 a2, T3 a3, T4 a4) const; + +private: + typedef std::list > CallbackList; + TraceContext m_context; + CallbackList m_callbackList; +}; + +}; // namespace ns3 + +// implementation below. + +namespace ns3 { + +namespace internal { + +template +class TraceSinkPrint; + +template +class TraceSinkPrint +{ +public: + static Callback Make (std::ostream &os) + { + return ns3::MakeBoundCallback (&DoPrint, &os); + } +private: + static void DoPrint (std::ostream *os, const TraceContext &context, T1 a1, T2 a2, T3 a3, T4 a4) + { + *os << "context=\"" << context << "\" arg1=\"" << a1 << "\" arg2=\"" << a2 << "\" arg3=\"" << a3 << "\" arg4=\"" << a4 << "\"" << std::endl; + } +}; + +template +class TraceSinkPrint +{ +public: + static Callback Make (std::ostream &os) + { + return ns3::MakeBoundCallback (&DoPrint, &os); + } +private: + static void DoPrint (std::ostream *os, const TraceContext &context, T1 a1, T2 a2, T3 a3) + { + *os << "context=\"" << context << "\" arg1=\"" << a1 << "\" arg2=\"" << a2 << "\" arg3=\"" << a3 << "\"" << std::endl; + } +}; + +template +class TraceSinkPrint +{ +public: + static Callback Make (std::ostream &os) + { + return ns3::MakeBoundCallback (&DoPrint, &os); + } +private: + static void DoPrint (std::ostream *os, const TraceContext &context, T1 a1, T2 a2) + { + *os << "context=\"" << context << "\" arg1=\"" << a1 << "\" arg2=\"" << a2 << "\"" << std::endl; + } +}; + +template +class TraceSinkPrint +{ +public: + static Callback Make (std::ostream &os) + { + return ns3::MakeBoundCallback (&DoPrint, &os); + } +private: + static void DoPrint (std::ostream *os, const TraceContext &context, T1 a1) + { + *os << "context=\"" << context << "\" arg1=\"" << a1 << "\"" << std::endl; + } +}; + +template <> +class TraceSinkPrint +{ +public: + static Callback Make (std::ostream &os) + { + return ns3::MakeBoundCallback (&DoPrint, &os); + } +private: + static void DoPrint (std::ostream *os, const TraceContext &context) + { + *os << "context=\"" << context << std::endl; + } +}; + +} // namespace internal + + +template +CallbackTraceSource::CallbackTraceSource () + : m_callbackList () +{} +template +void +CallbackTraceSource::AddCallback (CallbackBase const & callback, + TraceContext const &context) +{ + Callback cb; + cb.Assign (callback); + m_context.Union (context); + m_callbackList.push_back (cb); +} +template +void +CallbackTraceSource::RemoveCallback (CallbackBase const & callback) +{ + for (typename CallbackList::iterator i = m_callbackList.begin (); + i != m_callbackList.end (); /* empty */) + { + if ((*i).IsEqual (callback)) + { + i = m_callbackList.erase (i); + } + else + { + i++; + } + } +} +template +void +CallbackTraceSource::ConnectPrinter (std::ostream &os, const TraceContext &context) +{ + AddCallback (ns3::internal::TraceSinkPrint::Make (os), context); +} +template +void +CallbackTraceSource::operator() (void) const +{ + for (typename CallbackList::const_iterator i = m_callbackList.begin (); + i != m_callbackList.end (); i++) + { + (*i) (m_context); + } +} +template +void +CallbackTraceSource::operator() (T1 a1) const +{ + for (typename CallbackList::const_iterator i = m_callbackList.begin (); + i != m_callbackList.end (); i++) + { + (*i) (m_context, a1); + } +} +template +void +CallbackTraceSource::operator() (T1 a1, T2 a2) const +{ + for (typename CallbackList::const_iterator i = m_callbackList.begin (); + i != m_callbackList.end (); i++) + { + (*i) (m_context, a1, a2); + } +} +template +void +CallbackTraceSource::operator() (T1 a1, T2 a2, T3 a3) const +{ + for (typename CallbackList::const_iterator i = m_callbackList.begin (); + i != m_callbackList.end (); i++) + { + (*i) (m_context, a1, a2, a3); + } +} +template +void +CallbackTraceSource::operator() (T1 a1, T2 a2, T3 a3, T4 a4) const +{ + for (typename CallbackList::const_iterator i = m_callbackList.begin (); + i != m_callbackList.end (); i++) + { + (*i) (m_context, a1, a2, a3, a4); + } +} + +}//namespace ns3 + +#endif /* CALLBACK_TRACE_H */ diff --git a/src/core/callback.h b/src/core/callback.h index 94e58ca92..ff04de447 100644 --- a/src/core/callback.h +++ b/src/core/callback.h @@ -25,6 +25,7 @@ #include "ptr.h" #include "fatal-error.h" #include "empty.h" +#include "type-traits.h" namespace ns3 { @@ -89,55 +90,62 @@ private: }; // declare the CallbackImpl class -template +template class CallbackImpl; // define CallbackImpl for 0 params template -class CallbackImpl : public CallbackImplBase { +class CallbackImpl : public CallbackImplBase { public: virtual ~CallbackImpl () {} virtual R operator() (void) = 0; }; // define CallbackImpl for 1 params template -class CallbackImpl : public CallbackImplBase { +class CallbackImpl : public CallbackImplBase { public: virtual ~CallbackImpl () {} virtual R operator() (T1) = 0; }; // define CallbackImpl for 2 params template -class CallbackImpl : public CallbackImplBase { +class CallbackImpl : public CallbackImplBase { public: virtual ~CallbackImpl () {} virtual R operator() (T1, T2) = 0; }; // define CallbackImpl for 3 params template -class CallbackImpl : public CallbackImplBase { +class CallbackImpl : public CallbackImplBase { public: virtual ~CallbackImpl () {} virtual R operator() (T1, T2, T3) = 0; }; // define CallbackImpl for 4 params template -class CallbackImpl : public CallbackImplBase { +class CallbackImpl : public CallbackImplBase { public: virtual ~CallbackImpl () {} virtual R operator() (T1, T2, T3, T4) = 0; }; // define CallbackImpl for 5 params template -class CallbackImpl : public CallbackImplBase { +class CallbackImpl : public CallbackImplBase { public: virtual ~CallbackImpl () {} virtual R operator() (T1, T2, T3, T4, T5) = 0; }; +// define CallbackImpl for 6 params + template +class CallbackImpl : public CallbackImplBase { +public: + virtual ~CallbackImpl () {} + virtual R operator() (T1, T2, T3, T4, T5, T6) = 0; +}; // an impl for Functors: -template -class FunctorCallbackImpl : public CallbackImpl { +template +class FunctorCallbackImpl : public CallbackImpl { public: FunctorCallbackImpl (T const &functor) : m_functor (functor) {} @@ -160,9 +168,12 @@ public: R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) { return m_functor (a1,a2,a3,a4,a5); } + R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6) { + return m_functor (a1,a2,a3,a4,a5,a6); + } virtual bool IsEqual (CallbackImplBase const *other) const { - FunctorCallbackImpl const *otherDerived = - dynamic_cast const *> (other); + FunctorCallbackImpl const *otherDerived = + dynamic_cast const *> (other); if (otherDerived == 0) { return false; @@ -178,8 +189,8 @@ private: }; // an impl for pointer to member functions -template -class MemPtrCallbackImpl : public CallbackImpl { +template +class MemPtrCallbackImpl : public CallbackImpl { public: MemPtrCallbackImpl (OBJ_PTR const&objPtr, MEM_PTR mem_ptr) : m_objPtr (objPtr), m_memPtr (mem_ptr) {} @@ -202,9 +213,12 @@ public: R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) { return ((CallbackTraits::GetReference (m_objPtr)).*m_memPtr) (a1, a2, a3, a4, a5); } + R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6) { + return ((CallbackTraits::GetReference (m_objPtr)).*m_memPtr) (a1, a2, a3, a4, a5, a6); + } virtual bool IsEqual (CallbackImplBase const *other) const { - MemPtrCallbackImpl const *otherDerived = - dynamic_cast const *> (other); + MemPtrCallbackImpl const *otherDerived = + dynamic_cast const *> (other); if (otherDerived == 0) { return false; @@ -260,22 +274,22 @@ public: template + typename T5 = empty, typename T6 = empty> class Callback : public CallbackBase { public: // There are two dummy args below to ensure that this constructor is // always properly disambiguited by the c++ compiler template Callback (FUNCTOR const &functor, bool, bool) - : m_impl (Create > (functor)) + : m_impl (Create > (functor)) {} template Callback (OBJ_PTR const &objPtr, MEM_PTR mem_ptr) - : m_impl (Create > (objPtr, mem_ptr)) + : m_impl (Create > (objPtr, mem_ptr)) {} - Callback (Ptr > const &impl) + Callback (Ptr > const &impl) : m_impl (impl) {} @@ -305,14 +319,17 @@ public: R operator() (T1 a1, T2 a2, T3 a3, T4 a4,T5 a5) const { return (*(PeekImpl ())) (a1,a2,a3,a4,a5); } + R operator() (T1 a1, T2 a2, T3 a3, T4 a4,T5 a5,T6 a6) const { + return (*(PeekImpl ())) (a1,a2,a3,a4,a5,a6); + } - bool IsEqual (CallbackBase const &other) { + bool IsEqual (CallbackBase const &other) const { return PeekImpl ()->IsEqual (other.PeekImpl ()); } - bool CheckType (CallbackBase const& other) { + bool CheckType (CallbackBase const& other) const { CallbackImplBase *otherBase = other.PeekImpl (); - if (dynamic_cast *> (otherBase) != 0) + if (dynamic_cast *> (otherBase) != 0) { return true; } @@ -328,27 +345,27 @@ public: " got=" << typeid (other).name () << ", expected=" << typeid (*this).name ()); } - const Callback *goodType = static_cast *> (&other); + const Callback *goodType = static_cast *> (&other); *this = *goodType; } void Assign (Ptr other) { - CallbackImpl *impl = dynamic_cast *> (PeekPointer (other)); + CallbackImpl *impl = dynamic_cast *> (PeekPointer (other)); if (other == 0) { NS_FATAL_ERROR ("Incompatible types. (feed to \"c++filt -t\")" " got=" << typeid (other).name () << ", expected=" << typeid (*impl).name ()); } - *this = Callback (impl); + *this = Callback (impl); } virtual PtrGetImpl (void) const { return m_impl; } private: - virtual CallbackImpl *PeekImpl (void) const { + virtual CallbackImpl *PeekImpl (void) const { return PeekPointer (m_impl); } - Ptr > m_impl; + Ptr > m_impl; }; /** @@ -369,7 +386,7 @@ Callback MakeCallback (R (T::*memPtr) (void), OBJ objPtr) { return Callback (objPtr, memPtr); } template -Callback MakeCallback (R (T::*mem_ptr) () const, OBJ const objPtr) { +Callback MakeCallback (R (T::*mem_ptr) () const, OBJ objPtr) { return Callback (objPtr, mem_ptr); } /** @@ -381,11 +398,11 @@ Callback MakeCallback (R (T::*mem_ptr) () const, OBJ const objPtr) { * and potentially return a value. */ template -Callback MakeCallback (R (T::*mem_ptr) (T1), OBJ *const objPtr) { +Callback MakeCallback (R (T::*mem_ptr) (T1), OBJ objPtr) { return Callback (objPtr, mem_ptr); } template -Callback MakeCallback (R (T::*mem_ptr) (T1) const, OBJ const *const objPtr) { +Callback MakeCallback (R (T::*mem_ptr) (T1) const, OBJ objPtr) { return Callback (objPtr, mem_ptr); } /** @@ -397,11 +414,11 @@ Callback MakeCallback (R (T::*mem_ptr) (T1) const, OBJ const *const objPtr * and potentially return a value. */ template -Callback MakeCallback (R (T::*mem_ptr) (T1,T2), OBJ *const objPtr) { +Callback MakeCallback (R (T::*mem_ptr) (T1,T2), OBJ objPtr) { return Callback (objPtr, mem_ptr); } template -Callback MakeCallback (R (T::*mem_ptr) (T1,T2) const, OBJ const*const objPtr) { +Callback MakeCallback (R (T::*mem_ptr) (T1,T2) const, OBJ objPtr) { return Callback (objPtr, mem_ptr); } /** @@ -413,11 +430,11 @@ Callback MakeCallback (R (T::*mem_ptr) (T1,T2) const, OBJ const*const o * and potentially return a value. */ template -Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3), OBJ *const objPtr) { +Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3), OBJ objPtr) { return Callback (objPtr, mem_ptr); } template -Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3) const, OBJ const*const objPtr) { +Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3) const, OBJ objPtr) { return Callback (objPtr, mem_ptr); } /** @@ -429,11 +446,11 @@ Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3) const, OBJ const*c * and potentially return a value. */ template -Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4), OBJ *const objPtr) { +Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4), OBJ objPtr) { return Callback (objPtr, mem_ptr); } template -Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4) const, OBJ const*const objPtr) { +Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4) const, OBJ objPtr) { return Callback (objPtr, mem_ptr); } /** @@ -445,13 +462,29 @@ Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4) const, OBJ c * and potentially return a value. */ template -Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4,T5), OBJ *const objPtr) { +Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4,T5), OBJ objPtr) { return Callback (objPtr, mem_ptr); } template -Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4,T5) const, OBJ const*const objPtr) { +Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4,T5) const, OBJ objPtr) { return Callback (objPtr, mem_ptr); } +/** + * \ingroup MakeCallback + * \param mem_ptr class method member pointer + * \param objPtr class instance + * \return a wrapper Callback + * Build Callbacks for class method members which takes five arguments + * and potentially return a value. + */ +template +Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4,T5,T6), OBJ objPtr) { + return Callback (objPtr, mem_ptr); +} +template +Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4,T5,T6) const, OBJ objPtr) { + return Callback (objPtr, mem_ptr); +} /** * \ingroup MakeCallback @@ -519,6 +552,17 @@ template MakeCallback (R (*fnPtr) (T1,T2,T3,T4,T5)) { return Callback (fnPtr, true, true); } +/** + * \ingroup MakeCallback + * \param fnPtr function pointer + * \return a wrapper Callback + * Build Callbacks for functions which takes five arguments + * and potentially return a value. + */ +template +Callback MakeCallback (R (*fnPtr) (T1,T2,T3,T4,T5,T6)) { + return Callback (fnPtr, true, true); +} @@ -587,6 +631,17 @@ template MakeNullCallback (void) { return Callback (); } +/** + * \ingroup MakeCallback + * \overload Callback MakeNullCallback (void) + * \return a wrapper Callback + * Build a null callback which takes five arguments + * and potentially return a value. + */ +template +Callback MakeNullCallback (void) { + return Callback (); +} /* @@ -596,9 +651,10 @@ Callback MakeNullCallback (void) { */ // an impl for Bound Functors: template -class BoundFunctorCallbackImpl : public CallbackImpl { +class BoundFunctorCallbackImpl : public CallbackImpl { public: - BoundFunctorCallbackImpl (T const &functor, TX a) + template + BoundFunctorCallbackImpl (FUNCTOR functor, ARG a) : m_functor (functor), m_a (a) {} virtual ~BoundFunctorCallbackImpl () {} R operator() (void) { @@ -635,38 +691,48 @@ public: } private: T m_functor; - TX m_a; + typename TypeTraits::ReferencedType m_a; }; -template -Callback MakeBoundCallback (R (*fnPtr) (TX), TX a) { - Ptr > impl = +template +Callback MakeBoundCallback (R (*fnPtr) (TX), ARG a) { + Ptr > impl = Create >(fnPtr, a); return Callback (impl); } -template -Callback MakeBoundCallback (R (*fnPtr) (TX,T1), TX a) { - Ptr > impl = +template +Callback MakeBoundCallback (R (*fnPtr) (TX,T1), ARG a) { + Ptr > impl = Create > (fnPtr, a); return Callback (impl); } -template -Callback MakeBoundCallback (R (*fnPtr) (TX,T1,T2), TX a) { - Ptr > impl = +template +Callback MakeBoundCallback (R (*fnPtr) (TX,T1,T2), ARG a) { + Ptr > impl = Create > (fnPtr, a); return Callback (impl); } -template -Callback MakeBoundCallback (R (*fnPtr) (TX,T1,T2,T3,T4), TX a) { - Ptr > impl = +template +Callback MakeBoundCallback (R (*fnPtr) (TX,T1,T2,T3), ARG a) { + Ptr > impl = + Create > (fnPtr, a); + return Callback (impl); +} +template +Callback MakeBoundCallback (R (*fnPtr) (TX,T1,T2,T3,T4), ARG a) { + Ptr > impl = Create > (fnPtr, a); return Callback (impl); } - -template -Callback MakeBoundCallback (R (*fnPtr) (TX,T1,T2,T3,T4,T5), TX a) { - Ptr > impl = +template +Callback MakeBoundCallback (R (*fnPtr) (TX,T1,T2,T3,T4,T5), ARG a) { + Ptr > impl = Create > (fnPtr, a); return Callback (impl); } diff --git a/src/core/composite-trace-resolver.cc b/src/core/composite-trace-resolver.cc new file mode 100644 index 000000000..bf59054f2 --- /dev/null +++ b/src/core/composite-trace-resolver.cc @@ -0,0 +1,595 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 INRIA + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Mathieu Lacage + */ +#include "composite-trace-resolver.h" +#include "debug.h" + +NS_DEBUG_COMPONENT_DEFINE ("CompositeTraceResolver"); + +namespace ns3 { + +CompositeTraceResolver::CompositeTraceResolver () +{} + +CompositeTraceResolver::~CompositeTraceResolver () +{ + for (TraceItems::iterator i = m_items.begin (); i != m_items.end (); i++) + { + delete *i; + } + m_items.clear (); +} + +void +CompositeTraceResolver::AddItem (ResolveItem *item) +{ + m_items.push_back (item); +} + +void +CompositeTraceResolver::Add (std::string name, + Callback > createResolver) +{ + class MakerResolveItem : public ResolveItem + { + public: + virtual void Connect (std::string subpath, const CallbackBase &cb, const TraceContext &context) + {maker ()->Connect (subpath, cb, context);} + virtual void Disconnect (std::string subpath, const CallbackBase &cb) + {maker ()->Disconnect (subpath, cb);} + virtual void CollectSources (std::string path, const TraceContext &context, + SourceCollection *collection) + { + path.append ("/"); + path.append (this->name); + TraceContext ctx = context; + ctx.Union (this->context); + this->maker ()->CollectSources (path, ctx, collection); + } + virtual void TraceAll (std::ostream &os, const TraceContext &context) + { + TraceContext ctx = context; + ctx.Union (this->context); + this->maker ()->TraceAll (os, ctx); + } + Callback > maker; + } *item = new MakerResolveItem (); + item->name = name; + item->context = TraceContext (); + item->maker = createResolver; + AddItem (item); +} + +void +CompositeTraceResolver::AddSource (std::string name, + const TraceDoc &doc, + const TraceSource &trace) +{ + DoAddSource (name, doc, trace, TraceContext ()); +} + +void +CompositeTraceResolver::DoAddSource (std::string name, + const TraceDoc &doc, + const TraceSource &trace, + const TraceContext &context) +{ + class SourceResolveItem : public ResolveItem + { + public: + virtual void Connect (std::string subpath, const CallbackBase &cb, const TraceContext &context) + {if (subpath == "") {trace->AddCallback (cb, context);}} + virtual void Disconnect (std::string subpath, const CallbackBase &cb) + {if (subpath == "") {trace->RemoveCallback (cb);}} + virtual void CollectSources (std::string path, const TraceContext &context, + SourceCollection *collection) + { + path.append ("/"); + path.append (this->name); + TraceContext ctx = context; + ctx.Union (this->context); + collection->AddUnique (path, ctx, this->doc); + } + virtual void TraceAll (std::ostream &os, const TraceContext &context) + { + TraceContext ctx = context; + ctx.Union (this->context); + this->trace->ConnectPrinter (os, ctx); + } + TraceSource *trace; + TraceDoc doc; + } *item = new SourceResolveItem (); + item->name = name; + item->context = context; + item->trace = const_cast (&trace); + item->doc = doc; + AddItem (item); +} + + + + +void +CompositeTraceResolver::AddComposite (std::string name, Ptr composite) +{ + DoAddComposite (name, composite, TraceContext ()); +} +void +CompositeTraceResolver::DoAddComposite (std::string name, Ptr composite, const TraceContext &context) +{ + class CompositeResolveItem : public ResolveItem + { + public: + virtual void Connect (std::string subpath, const CallbackBase &cb, const TraceContext &context) + {composite->GetTraceResolver ()->Connect (subpath, cb, context);} + virtual void Disconnect (std::string subpath, const CallbackBase &cb) + {composite->TraceDisconnect (subpath, cb);} + virtual void CollectSources (std::string path, const TraceContext &context, + SourceCollection *collection) + { + path.append ("/"); + path.append (this->name); + TraceContext ctx = context; + ctx.Union (this->context); + this->composite->GetTraceResolver ()->CollectSources (path, ctx, collection); + } + virtual void TraceAll (std::ostream &os, const TraceContext &context) + { + TraceContext ctx = context; + ctx.Union (this->context); + this->composite->GetTraceResolver ()->TraceAll (os, ctx); + } + + Ptr composite; + } *item = new CompositeResolveItem (); + item->name = name; + item->context = context; + item->composite = composite; + AddItem (item); +} + +void +CompositeTraceResolver::SetParentResolver (Ptr resolver) +{ + m_parent = resolver; +} + +void +CompositeTraceResolver::Connect (std::string path, CallbackBase const &cb, const TraceContext &context) +{ + NS_DEBUG ("connect path="<name == id) + { + operation.Do (subpath, *i); + operation.DoParent (path, m_parent); + return; + } + } + } + std::list names; + std::string alternatives = std::string (id, start+1, end-1); + std::string::size_type next_pos, cur_pos; + next_pos = 0; + cur_pos = 0; + while (true) + { + std::string element; + next_pos = alternatives.find ("|", cur_pos); + if (next_pos == std::string::npos) + { + element = std::string (alternatives, cur_pos, alternatives.size ()); + names.push_back (element); + break; + } + element = std::string (alternatives, cur_pos, next_pos); + names.push_back (element); + cur_pos = next_pos + 1; + } + for (std::list::const_iterator i = names.begin (); i != names.end (); i++) + { + for (TraceItems::const_iterator j = m_items.begin (); j != m_items.end (); j++) + { + if ((*j)->name == *i) + { + operation.Do (subpath, *j); + break; + } + } + } + operation.DoParent (path, m_parent); +} + +void +CompositeTraceResolver::Disconnect (std::string path, CallbackBase const &cb) +{ + NS_DEBUG ("disconnect path="<name); + (*i)->CollectSources (path, context, collection); + } + if (m_parent != 0) + { + m_parent->CollectSources (path, context, collection); + } +} +void +CompositeTraceResolver::TraceAll (std::ostream &os, const TraceContext &context) +{ + for (TraceItems::const_iterator i = m_items.begin (); i != m_items.end (); i++) + { + NS_DEBUG ("print " << (*i)->name); + (*i)->TraceAll (os, context); + } + if (m_parent != 0) + { + m_parent->TraceAll (os, context); + } +} + + +}//namespace ns3 + +#ifdef RUN_SELF_TESTS + +#include "test.h" +#include "trace-context-element.h" + +namespace ns3 { + +class TraceSourceTest : public TraceContextElement +{ +public: + enum Sources { + DOUBLEA, + DOUBLEB, + UINT16_T + }; + static uint16_t GetUid (void) + {static uint16_t uid = AllocateUid ("TraceSourceTest"); return uid;} + void Print (std::ostream &os) + {os << "tracesource="; + if (m_sources == DOUBLEA) {os << "doubleA";} + else if (m_sources == DOUBLEB) {os << "doubleB";} + else if (m_sources == UINT16_T) {os << "uint16_t";} + } + std::string GetTypeName (void) {return "ns3::TraceSourceTest";} + TraceSourceTest () : m_sources (TraceSourceTest::DOUBLEA) {} + TraceSourceTest (enum Sources sources) :m_sources (sources) {} + bool IsDoubleA (void) const {return m_sources == TraceSourceTest::DOUBLEA;} + bool IsDoubleB (void) const {return m_sources == TraceSourceTest::DOUBLEB;} + bool IsUint16 (void) const {return m_sources == TraceSourceTest::UINT16_T;} +private: + enum TraceSourceTest::Sources m_sources; +}; + +class SubTraceSourceTest : public TraceContextElement +{ +public: + enum Sources { + INT, + }; + static uint16_t GetUid (void) + {static uint16_t uid = AllocateUid ("SubTraceSourceTest"); return uid;} + void Print (std::ostream &os) + {os << "subtracesource=int";} + std::string GetTypeName (void) const {return "ns3::SubTraceSourceTest";} + SubTraceSourceTest () : m_sources (SubTraceSourceTest::INT) {} + SubTraceSourceTest (enum Sources sources) : m_sources (sources) {} +private: + enum Sources m_sources; +}; + +class CompositeTraceResolverTest : public Test +{ +public: + CompositeTraceResolverTest (); + virtual ~CompositeTraceResolverTest (); + virtual bool RunTests (void); +private: + void TraceDouble (TraceContext const &context, double v); + void TraceInt (TraceContext const &context, int v); + Ptr CreateSubResolver (); + + + bool m_gotDoubleA; + bool m_gotDoubleB; + CallbackTraceSource m_traceInt; + bool m_gotInt; +}; + +CompositeTraceResolverTest::CompositeTraceResolverTest () + : Test ("CompositeTraceResolver") +{} +CompositeTraceResolverTest::~CompositeTraceResolverTest () +{} +void +CompositeTraceResolverTest::TraceDouble (TraceContext const &context, double v) +{ + TraceSourceTest source; + context.GetElement (source); + if (source.IsDoubleA ()) + { + m_gotDoubleA = true; + } + else if (source.IsDoubleB ()) + { + m_gotDoubleB = true; + } + else + { + NS_FATAL_ERROR ("should not get any other trace source in this sink"); + } + +} + +void +CompositeTraceResolverTest::TraceInt (TraceContext const &context, int v) +{ + m_gotInt = true; +} + +Ptr +CompositeTraceResolverTest::CreateSubResolver (void) +{ + Ptr subresolver = Create (); + subresolver->AddSource ("trace-int", TraceDoc ("test source"), m_traceInt, + SubTraceSourceTest (SubTraceSourceTest::INT)); + return subresolver; +} +bool +CompositeTraceResolverTest::RunTests (void) +{ + bool ok = true; + + CallbackTraceSource traceDoubleA; + CallbackTraceSource traceDoubleB; + TraceContext context; + + CompositeTraceResolver resolver; + + resolver.AddSource ("trace-double-a", TraceDoc ("test source"), traceDoubleA, + TraceSourceTest (TraceSourceTest::DOUBLEA)); + resolver.AddSource ("trace-double-b", TraceDoc ("test source"), traceDoubleB, + TraceSourceTest (TraceSourceTest::DOUBLEB)); + + resolver.Connect ("/*", MakeCallback (&CompositeTraceResolverTest::TraceDouble, this), TraceContext ()); + + m_gotDoubleA = false; + m_gotDoubleB = false; + traceDoubleA (0); + if (!m_gotDoubleA || m_gotDoubleB) + { + ok = false; + } + m_gotDoubleA = false; + traceDoubleA (0); + traceDoubleB (0); + if (!m_gotDoubleA || !m_gotDoubleB) + { + ok = false; + } + m_gotDoubleA = false; + m_gotDoubleB = false; + + resolver.Disconnect ("/*", MakeCallback (&CompositeTraceResolverTest::TraceDouble, this)); + + m_gotDoubleA = false; + m_gotDoubleB = false; + traceDoubleA (0); + traceDoubleB (0); + if (m_gotDoubleA || m_gotDoubleB) + { + ok = false; + } + + resolver.Connect ("/trace-double-a", + MakeCallback (&CompositeTraceResolverTest::TraceDouble, this), TraceContext ()); + m_gotDoubleA = false; + m_gotDoubleB = false; + traceDoubleA (0); + traceDoubleB (0); + if (!m_gotDoubleA || m_gotDoubleB) + { + ok = false; + } + resolver.Disconnect ("/trace-double-a", + MakeCallback (&CompositeTraceResolverTest::TraceDouble, this)); + + resolver.Connect ("/(trace-double-a)", + MakeCallback (&CompositeTraceResolverTest::TraceDouble, this), TraceContext ()); + m_gotDoubleA = false; + m_gotDoubleB = false; + traceDoubleA (0); + traceDoubleB (0); + if (!m_gotDoubleA || m_gotDoubleB) + { + ok = false; + } + resolver.Disconnect ("/trace-double-a", + MakeCallback (&CompositeTraceResolverTest::TraceDouble, this)); + + resolver.Connect ("/(trace-double-a|trace-double-b)", + MakeCallback (&CompositeTraceResolverTest::TraceDouble, this), TraceContext ()); + m_gotDoubleA = false; + m_gotDoubleB = false; + traceDoubleA (0); + traceDoubleB (0); + if (!m_gotDoubleA || !m_gotDoubleB) + { + ok = false; + } + resolver.Disconnect ("/trace-double-a", + MakeCallback (&CompositeTraceResolverTest::TraceDouble, this)); + m_gotDoubleA = false; + m_gotDoubleB = false; + traceDoubleA (0); + traceDoubleB (0); + if (m_gotDoubleA || !m_gotDoubleB) + { + ok = false; + } + + + resolver.Disconnect ("/(trace-double-a|trace-double-b)", + MakeCallback (&CompositeTraceResolverTest::TraceDouble, this)); + m_gotDoubleA = false; + m_gotDoubleB = false; + traceDoubleA (0); + traceDoubleB (0); + if (m_gotDoubleA || m_gotDoubleB) + { + ok = false; + } + + resolver.Add ("subresolver", + MakeCallback (&CompositeTraceResolverTest::CreateSubResolver, this)); + + resolver.Connect ("/subresolver/trace-int", + MakeCallback (&CompositeTraceResolverTest::TraceInt, this), TraceContext ()); + m_gotInt = false; + m_traceInt (1); + if (!m_gotInt) + { + ok = false; + } + + resolver.Disconnect ("/subresolver/trace-int", + MakeCallback (&CompositeTraceResolverTest::TraceInt, this)); + m_gotInt = false; + m_traceInt (1); + if (m_gotInt) + { + ok = false; + } + + resolver.Connect ("/*/trace-int", + MakeCallback (&CompositeTraceResolverTest::TraceInt, this), TraceContext ()); + m_gotInt = false; + m_traceInt (1); + if (!m_gotInt) + { + ok = false; + } + + resolver.Disconnect ("/subresolver/trace-int", + MakeCallback (&CompositeTraceResolverTest::TraceInt, this)); + m_gotInt = false; + m_traceInt (1); + if (m_gotInt) + { + ok = false; + } + + SVTraceSource source; + + resolver.AddSource ("uint16_t", TraceDoc ("test source"), source, TraceSourceTest (TraceSourceTest::UINT16_T)); + + + return ok; +} + +static CompositeTraceResolverTest g_compositeTraceResolverTest; + +}//namespace ns3 + + +#endif /* RUN_SELF_TESTS */ diff --git a/src/core/composite-trace-resolver.h b/src/core/composite-trace-resolver.h new file mode 100644 index 000000000..ceca4044a --- /dev/null +++ b/src/core/composite-trace-resolver.h @@ -0,0 +1,233 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 INRIA + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Mathieu Lacage + */ +#ifndef COMPOSITE_TRACE_RESOLVER_H +#define COMPOSITE_TRACE_RESOLVER_H + +#include +#include "callback.h" +#include "ptr.h" +#include "trace-resolver.h" +#include "callback-trace-source.h" +#include "uv-trace-source.h" +#include "sv-trace-source.h" +#include "fv-trace-source.h" +#include "array-trace-resolver.h" +#include "trace-doc.h" + +namespace ns3 { + +/** + * \brief a helper class to aggregate contained TraceResolver and other trace sources. + * \ingroup tracing + */ +class CompositeTraceResolver : public TraceResolver +{ +public: + CompositeTraceResolver (); + virtual ~CompositeTraceResolver (); + /** + * \param name name of trace source + * \param doc the documentation associated to this trace source + * \param trace a callback trace source + * \param context the context associated to this trace source + * + * Add a callback trace source in this resolver. This trace + * source will match the name specified during namespace + * resolution. The TraceContext of this trace source will also + * be automatically extended to contain the input context. + */ + template + void AddSource (std::string name, const TraceDoc &doc, + const TraceSource &trace, T const &context); + /** + * \param name name of trace source + * \param doc the documentation associated to this trace source + * \param trace a callback trace source + * + * Add a callback trace source in this resolver. This trace + * source will match the name specified during namespace + * resolution. + */ + void AddSource (std::string name, + const TraceDoc &doc, + const TraceSource &trace); + + /** + * \param name the name of the composite element + * \param composite the composite object + * + * The input composite object will be used to resolve a connection + * of a disconnection attempt if its name matches the trace path. + * + */ + void AddComposite (std::string name, Ptr composite); + + /** + * \param name the name of the composite element + * \param composite the composite object + * \param contextElement the context element associated to the composite + * + * The input composite object will be used to resolve a connection + * of a disconnection attempt if its name matches the trace path. + * The contextElement will be appended to the TraceContext during connection. + */ + template + void AddComposite (std::string name, Ptr composite, const T &contextElement); + + /** + * \param name the name of the array + * \param begin an iterator which points to the first element of the array + * \param end an iterator which points to the last element of the array + * \param index an object which can store the index of an element in the + * array. In practice, this object should support a constructor + * whose single argument is an array index. + */ + template + void AddArray (std::string name, + ITERATOR begin, ITERATOR end, INDEX index); + + /** + * \param parent the parent trace resolver + * + * The parent trace resolver is the trace resolver returned by the + * GetTraceResolver method of the base class of the caller. It is + * used during connection and disconnection to chain up the connect + * and disconnect calls to the parent. + */ + void SetParentResolver (Ptr parent); + + +private: + virtual void Connect (std::string path, CallbackBase const &cb, const TraceContext &context); + virtual void Disconnect (std::string path, CallbackBase const &cb); + virtual void CollectSources (std::string path, const TraceContext &context, + SourceCollection *collection); + virtual void TraceAll (std::ostream &os, const TraceContext &context); + friend class CompositeTraceResolverTest; + class ResolveItem + { + public: + virtual ~ResolveItem () {} + virtual void Connect (std::string subpath, const CallbackBase &cb, const TraceContext &context) = 0; + virtual void Disconnect (std::string subpath, const CallbackBase &cb) = 0; + virtual void CollectSources (std::string path, const TraceContext &context, + SourceCollection *collection) = 0; + virtual void TraceAll (std::ostream &os, const TraceContext &context) = 0; + + std::string name; + TraceContext context; + }; + typedef std::vector TraceItems; + class Operation + { + public: + virtual ~Operation () {} + virtual void Do (std::string subpath, ResolveItem *item) const = 0; + virtual void DoParent (std::string path, Ptr parent) const = 0; + }; + + void AddItem (ResolveItem *item); + void DoRecursiveOperation (std::string path, + const Operation &operation); + void DoRecursiveOperationForParent (std::string path, + const Operation &operation); + void DoAddComposite (std::string name, Ptr composite, const TraceContext &context); + void DoAddSource (std::string name, + const TraceDoc &doc, + const TraceSource &trace, + const TraceContext &context); + void Add (std::string name, + Callback > createResolver); + + + CompositeTraceResolver::TraceItems m_items; + Ptr m_parent; +}; + +}//namespace ns3 + +namespace ns3 { + + + +template +void +CompositeTraceResolver::AddSource (std::string name, + const TraceDoc &doc, + const TraceSource &trace, + T const &context) +{ + TraceContext ctx; + ctx.AddElement (context); + DoAddSource (name, doc, trace, ctx); +} + +template +void +CompositeTraceResolver::AddArray (std::string name, + ITERATOR begin, ITERATOR end, INDEX index) +{ + class ArrayResolveItem : public ResolveItem + { + public: + virtual void Connect (std::string subpath, const CallbackBase &cb, const TraceContext &context) + {array->Connect (subpath, cb, context);} + virtual void Disconnect (std::string subpath, const CallbackBase &cb) + {array->Disconnect (subpath, cb);} + virtual void CollectSources (std::string path, const TraceContext &context, + SourceCollection *collection) + { + path.append ("/"); + path.append (this->name); + TraceContext ctx = context; + ctx.Union (this->context); + array->CollectSources (path, ctx, collection); + } + virtual void TraceAll (std::ostream &os, const TraceContext &context) + { + TraceContext ctx = context; + ctx.Union (this->context); + array->TraceAll (os, ctx); + } + + Ptr > array; + } *item = new ArrayResolveItem (); + item->name = name; + item->context = TraceContext (); + item->array = Create > (); + item->array->SetIterators (begin, end); + AddItem (item); +} + +template +void +CompositeTraceResolver::AddComposite (std::string name, Ptr composite, const T &contextElement) +{ + TraceContext context; + context.AddElement (contextElement); + DoAddComposite (name, composite, context); +} + + + +}//namespace ns3 + +#endif /* COMPOSITE_TRACE_RESOLVER_H */ diff --git a/src/common/fv-trace-source.h b/src/core/fv-trace-source.h similarity index 82% rename from src/common/fv-trace-source.h rename to src/core/fv-trace-source.h index 2e059303b..c0f816dbb 100644 --- a/src/common/fv-trace-source.h +++ b/src/core/fv-trace-source.h @@ -23,11 +23,12 @@ #define F_VARIABLE_TRACER_H #include "callback-trace-source.h" +#include "trace-source.h" #include namespace ns3 { -class FVTraceSourceBase { +class FVTraceSourceBase : public TraceSource { public: typedef CallbackTraceSource ChangeNotifyCallback; @@ -39,12 +40,15 @@ public: ~FVTraceSourceBase () {} - void AddCallback (CallbackBase const & callback, TraceContext const & context) { + virtual void AddCallback (CallbackBase const & callback, TraceContext const & context) { m_callback.AddCallback (callback, context); } - void RemoveCallback (CallbackBase const & callback) { + virtual void RemoveCallback (CallbackBase const & callback) { m_callback.RemoveCallback (callback); } + virtual void ConnectPrinter (std::ostream &os, const TraceContext &context) { + m_callback.ConnectPrinter (os, context); + } protected: void notify (double oldVal, double newVal) { if (oldVal != newVal) diff --git a/src/core/object.cc b/src/core/object.cc index 9b4812c42..27ac31917 100644 --- a/src/core/object.cc +++ b/src/core/object.cc @@ -22,8 +22,12 @@ #include "assert.h" #include "singleton.h" #include "uid-manager.h" +#include "trace-resolver.h" +#include "debug.h" #include +NS_DEBUG_COMPONENT_DEFINE ("Object"); + namespace { class IidManager : public ns3::UidManager @@ -34,6 +38,7 @@ class IidTree public: void SetParent (uint16_t child, const uint16_t *parent); uint16_t LookupParent (uint16_t child); + private: std::vector m_parents; }; @@ -55,6 +60,68 @@ IidTree::LookupParent (uint16_t child) namespace ns3 { +class InterfaceIdTraceResolver : public TraceResolver +{ +public: + InterfaceIdTraceResolver (Ptr aggregate); + virtual void Connect (std::string path, CallbackBase const &cb, const TraceContext &context); + virtual void Disconnect (std::string path, CallbackBase const &cb); + virtual void CollectSources (std::string path, const TraceContext &context, + SourceCollection *collection); + virtual void TraceAll (std::ostream &os, const TraceContext &context); +private: + Ptr ParseForInterface (std::string path); + Ptr m_aggregate; +}; + +InterfaceIdTraceResolver::InterfaceIdTraceResolver (Ptr aggregate) + : m_aggregate (aggregate) +{} +Ptr +InterfaceIdTraceResolver::ParseForInterface (std::string path) +{ + std::string element = GetElement (path); + std::string::size_type dollar_pos = element.find ("$"); + if (dollar_pos != 0) + { + return 0; + } + std::string interfaceName = element.substr (1, std::string::npos); + InterfaceId interfaceId = InterfaceId::LookupByName (interfaceName); + Ptr interface = m_aggregate->QueryInterface (interfaceId); + return interface; +} +void +InterfaceIdTraceResolver::Connect (std::string path, CallbackBase const &cb, const TraceContext &context) +{ + Ptr interface = ParseForInterface (path); + if (interface != 0) + { + interface->GetTraceResolver ()->Connect (GetSubpath (path), cb, context); + } +} +void +InterfaceIdTraceResolver::Disconnect (std::string path, CallbackBase const &cb) +{ + Ptr interface = ParseForInterface (path); + if (interface != 0) + { + interface->TraceDisconnect (GetSubpath (path), cb); + } +} +void +InterfaceIdTraceResolver::CollectSources (std::string path, const TraceContext &context, + SourceCollection *collection) +{ + m_aggregate->DoCollectSources (path, context, collection); +} +void +InterfaceIdTraceResolver::TraceAll (std::ostream &os, const TraceContext &context) +{ + m_aggregate->DoTraceAll (os, context); +} + + InterfaceId::InterfaceId (uint16_t iid) : m_iid (iid) {} @@ -72,6 +139,12 @@ InterfaceId::LookupParent (InterfaceId iid) { return Singleton::Get ()->LookupParent (iid.m_iid); } +std::string +InterfaceId::GetName (void) const +{ + std::string name = Singleton::Get ()->LookupByUid (m_iid); + return name; +} bool operator == (const InterfaceId &a, const InterfaceId &b) { @@ -109,6 +182,7 @@ Object::Object () : m_count (1), m_iid (Object::iid), m_disposed (false), + m_collecting (false), m_next (this) {} Object::~Object () @@ -163,6 +237,17 @@ Object::AddInterface (Ptr o) NS_ASSERT (o->Check ()); } +void +Object::TraceConnect (std::string path, const CallbackBase &cb) const +{ + GetTraceResolver ()->Connect (path, cb, TraceContext ()); +} +void +Object::TraceDisconnect (std::string path, const CallbackBase &cb) const +{ + GetTraceResolver ()->Disconnect (path, cb); +} + void Object::SetInterfaceId (InterfaceId iid) { @@ -176,6 +261,14 @@ Object::DoDispose (void) NS_ASSERT (!m_disposed); } +Ptr +Object::GetTraceResolver (void) const +{ + Ptr resolver = + Create (this); + return resolver; +} + bool Object::Check (void) const { @@ -209,12 +302,77 @@ Object::MaybeDelete (void) const } while (current != end); } +void +Object::DoCollectSources (std::string path, const TraceContext &context, + TraceResolver::SourceCollection *collection) const +{ + const Object *current; + current = this; + do { + if (current->m_collecting) + { + return; + } + current = current->m_next; + } while (current != this); + + m_collecting = true; + + current = this->m_next; + while (current != this) + { + NS_ASSERT (current != 0); + NS_DEBUG ("collect current=" << current); + InterfaceId cur = current->m_iid; + while (cur != Object::iid) + { + std::string name = cur.GetName (); + std::string fullpath = path; + fullpath.append ("/$"); + fullpath.append (name); + NS_DEBUG ("collect: " << fullpath); + current->GetTraceResolver ()->CollectSources (fullpath, context, collection); + cur = InterfaceId::LookupParent (cur); + } + current = current->m_next; + } + + m_collecting = false; +} +void +Object::DoTraceAll (std::ostream &os, const TraceContext &context) const +{ + const Object *current; + current = this; + do { + if (current->m_collecting) + { + return; + } + current = current->m_next; + } while (current != this); + + m_collecting = true; + + current = this->m_next; + while (current != this) + { + NS_ASSERT (current != 0); + current->GetTraceResolver ()->TraceAll (os, context); + current = current->m_next; + } + + m_collecting = false; +} + } // namespace ns3 #ifdef RUN_SELF_TESTS #include "test.h" +#include "sv-trace-source.h" +#include "composite-trace-resolver.h" namespace { @@ -226,7 +384,18 @@ public: { SetInterfaceId (BaseA::iid); } + void BaseGenerateTrace (int16_t v) + { m_source = v; } virtual void Dispose (void) {} + virtual ns3::Ptr GetTraceResolver (void) const + { + ns3::Ptr resolver = + ns3::Create (); + resolver->AddSource ("basea-x", ns3::TraceDoc ("test source"), m_source); + resolver->SetParentResolver (Object::GetTraceResolver ()); + return resolver; + } + ns3::SVTraceSource m_source; }; class DerivedA : public BaseA @@ -237,9 +406,20 @@ public: { SetInterfaceId (DerivedA::iid); } + void DerivedGenerateTrace (int16_t v) + { m_sourceDerived = v; } virtual void Dispose (void) { BaseA::Dispose (); } + virtual ns3::Ptr GetTraceResolver (void) const + { + ns3::Ptr resolver = + ns3::Create (); + resolver->AddSource ("deriveda-x", ns3::TraceDoc ("test source"), m_sourceDerived); + resolver->SetParentResolver (BaseA::GetTraceResolver ()); + return resolver; + } + ns3::SVTraceSource m_sourceDerived; }; const ns3::InterfaceId BaseA::iid = @@ -255,7 +435,18 @@ public: { SetInterfaceId (BaseB::iid); } + void BaseGenerateTrace (int16_t v) + { m_source = v; } virtual void Dispose (void) {} + virtual ns3::Ptr GetTraceResolver (void) const + { + ns3::Ptr resolver = + ns3::Create (); + resolver->AddSource ("baseb-x", ns3::TraceDoc ("test source"), m_source); + resolver->SetParentResolver (Object::GetTraceResolver ()); + return resolver; + } + ns3::SVTraceSource m_source; }; class DerivedB : public BaseB @@ -266,9 +457,20 @@ public: { SetInterfaceId (DerivedB::iid); } + void DerivedGenerateTrace (int16_t v) + { m_sourceDerived = v; } virtual void Dispose (void) { BaseB::Dispose (); } + virtual ns3::Ptr GetTraceResolver (void) const + { + ns3::Ptr resolver = + ns3::Create (); + resolver->AddSource ("derivedb-x", ns3::TraceDoc ("test source"), m_sourceDerived); + resolver->SetParentResolver (BaseB::GetTraceResolver ()); + return resolver; + } + ns3::SVTraceSource m_sourceDerived; }; const ns3::InterfaceId BaseB::iid = @@ -285,120 +487,82 @@ class ObjectTest : public Test public: ObjectTest (); virtual bool RunTests (void); +private: + void BaseATrace (const TraceContext &context, int64_t oldValue, int64_t newValue); + void DerivedATrace (const TraceContext &context, int64_t oldValue, int64_t newValue); + void BaseBTrace (const TraceContext &context, int64_t oldValue, int64_t newValue); + void DerivedBTrace (const TraceContext &context, int64_t oldValue, int64_t newValue); + + bool m_baseATrace; + bool m_derivedATrace; + bool m_baseBTrace; + bool m_derivedBTrace; }; ObjectTest::ObjectTest () : Test ("Object") {} +void +ObjectTest::BaseATrace (const TraceContext &context, int64_t oldValue, int64_t newValue) +{ + m_baseATrace = true; +} +void +ObjectTest::DerivedATrace (const TraceContext &context, int64_t oldValue, int64_t newValue) +{ + m_derivedATrace = true; +} +void +ObjectTest::BaseBTrace (const TraceContext &context, int64_t oldValue, int64_t newValue) +{ + m_baseBTrace = true; +} +void +ObjectTest::DerivedBTrace (const TraceContext &context, int64_t oldValue, int64_t newValue) +{ + m_derivedBTrace = true; +} + bool ObjectTest::RunTests (void) { - bool ok = true; + bool result = true; Ptr baseA = Create (); - if (baseA->QueryInterface (BaseA::iid) != baseA) - { - ok = false; - } - if (baseA->QueryInterface (DerivedA::iid) != 0) - { - ok = false; - } - if (baseA->QueryInterface (DerivedA::iid) != 0) - { - ok = false; - } + NS_TEST_ASSERT_EQUAL (baseA->QueryInterface (BaseA::iid), baseA); + NS_TEST_ASSERT_EQUAL (baseA->QueryInterface (DerivedA::iid), 0); + NS_TEST_ASSERT_EQUAL (baseA->QueryInterface (DerivedA::iid), 0); baseA = Create (10); - if (baseA->QueryInterface (BaseA::iid) != baseA) - { - ok = false; - } - if (baseA->QueryInterface (DerivedA::iid) != baseA) - { - ok = false; - } - if (baseA->QueryInterface (DerivedA::iid) == 0) - { - ok = false; - } + NS_TEST_ASSERT_EQUAL (baseA->QueryInterface (BaseA::iid), baseA); + NS_TEST_ASSERT_EQUAL (baseA->QueryInterface (DerivedA::iid), baseA); + NS_TEST_ASSERT_UNEQUAL (baseA->QueryInterface (DerivedA::iid), 0); baseA = Create (); Ptr baseB = Create (); Ptr baseBCopy = baseB; baseA->AddInterface (baseB); - if (baseA->QueryInterface (BaseA::iid) == 0) - { - ok = false; - } - if (baseA->QueryInterface (DerivedA::iid) != 0) - { - ok = false; - } - if (baseA->QueryInterface (BaseB::iid) == 0) - { - ok = false; - } - if (baseA->QueryInterface (DerivedB::iid) != 0) - { - ok = false; - } - if (baseB->QueryInterface (BaseB::iid) == 0) - { - ok = false; - } - if (baseB->QueryInterface (DerivedB::iid) != 0) - { - ok = false; - } - if (baseB->QueryInterface (BaseA::iid) == 0) - { - ok = false; - } - if (baseB->QueryInterface (DerivedA::iid) != 0) - { - ok = false; - } - if (baseBCopy->QueryInterface (BaseA::iid) == 0) - { - ok = false; - } + NS_TEST_ASSERT_UNEQUAL (baseA->QueryInterface (BaseA::iid), 0); + NS_TEST_ASSERT_EQUAL (baseA->QueryInterface (DerivedA::iid), 0); + NS_TEST_ASSERT_UNEQUAL (baseA->QueryInterface (BaseB::iid), 0); + NS_TEST_ASSERT_EQUAL (baseA->QueryInterface (DerivedB::iid), 0); + NS_TEST_ASSERT_UNEQUAL (baseB->QueryInterface (BaseB::iid), 0); + NS_TEST_ASSERT_EQUAL (baseB->QueryInterface (DerivedB::iid), 0); + NS_TEST_ASSERT_UNEQUAL (baseB->QueryInterface (BaseA::iid), 0); + NS_TEST_ASSERT_EQUAL (baseB->QueryInterface (DerivedA::iid), 0); + NS_TEST_ASSERT_UNEQUAL (baseBCopy->QueryInterface (BaseA::iid), 0); baseA = Create (1); baseB = Create (1); baseBCopy = baseB; baseA->AddInterface (baseB); - if (baseA->QueryInterface (DerivedB::iid) == 0) - { - ok = false; - } - if (baseA->QueryInterface (BaseB::iid) == 0) - { - ok = false; - } - if (baseB->QueryInterface (DerivedA::iid) == 0) - { - ok = false; - } - if (baseB->QueryInterface (BaseA::iid) == 0) - { - ok = false; - } - if (baseBCopy->QueryInterface (DerivedA::iid) == 0) - { - ok = false; - } - if (baseBCopy->QueryInterface (BaseA::iid) == 0) - { - ok = false; - } - if (baseB->QueryInterface (DerivedB::iid) == 0) - { - ok = false; - } - if (baseB->QueryInterface (BaseB::iid) == 0) - { - ok = false; - } + NS_TEST_ASSERT_UNEQUAL (baseA->QueryInterface (DerivedB::iid), 0); + NS_TEST_ASSERT_UNEQUAL (baseA->QueryInterface (BaseB::iid), 0); + NS_TEST_ASSERT_UNEQUAL (baseB->QueryInterface (DerivedA::iid), 0); + NS_TEST_ASSERT_UNEQUAL (baseB->QueryInterface (BaseA::iid), 0); + NS_TEST_ASSERT_UNEQUAL (baseBCopy->QueryInterface (DerivedA::iid), 0); + NS_TEST_ASSERT_UNEQUAL (baseBCopy->QueryInterface (BaseA::iid), 0); + NS_TEST_ASSERT_UNEQUAL (baseB->QueryInterface (DerivedB::iid), 0); + NS_TEST_ASSERT_UNEQUAL (baseB->QueryInterface (BaseB::iid), 0) baseA = Create (); baseB = Create (); @@ -406,7 +570,76 @@ ObjectTest::RunTests (void) baseA = 0; baseA = baseB->QueryInterface (BaseA::iid); - return ok; + baseA = Create (); + baseA->TraceConnect ("/basea-x", MakeCallback (&ObjectTest::BaseATrace, this)); + m_baseATrace = false; + baseA->BaseGenerateTrace (1); + NS_TEST_ASSERT (m_baseATrace); + baseA->TraceDisconnect ("/basea-x", MakeCallback (&ObjectTest::BaseATrace, this)); + + baseB = Create (); + baseB->TraceConnect ("/baseb-x", MakeCallback (&ObjectTest::BaseBTrace, this)); + m_baseBTrace = false; + baseB->BaseGenerateTrace (2); + NS_TEST_ASSERT (m_baseBTrace); + baseB->TraceDisconnect ("/baseb-x", MakeCallback (&ObjectTest::BaseBTrace, this)); + + baseA->AddInterface (baseB); + + baseA->TraceConnect ("/basea-x", MakeCallback (&ObjectTest::BaseATrace, this)); + m_baseATrace = false; + baseA->BaseGenerateTrace (3); + NS_TEST_ASSERT (m_baseATrace); + baseA->TraceDisconnect ("/basea-x", MakeCallback (&ObjectTest::BaseATrace, this)); + + baseA->TraceConnect ("/$BaseB/baseb-x", MakeCallback (&ObjectTest::BaseBTrace, this)); + m_baseBTrace = false; + baseB->BaseGenerateTrace (4); + NS_TEST_ASSERT (m_baseBTrace); + baseA->TraceDisconnect ("/$BaseB/baseb-x", MakeCallback (&ObjectTest::BaseBTrace, this)); + m_baseBTrace = false; + baseB->BaseGenerateTrace (5); + NS_TEST_ASSERT (!m_baseBTrace); + + baseB->TraceConnect ("/$BaseA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this)); + m_baseATrace = false; + baseA->BaseGenerateTrace (6); + NS_TEST_ASSERT (m_baseATrace); + baseB->TraceDisconnect ("/$BaseA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this)); + + baseA->TraceConnect ("/$BaseA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this)); + m_baseATrace = false; + baseA->BaseGenerateTrace (7); + NS_TEST_ASSERT (m_baseATrace); + baseA->TraceDisconnect ("/$BaseA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this)); + + Ptr derivedA; + derivedA = Create (1); + baseB = Create (); + derivedA->AddInterface (baseB); + baseB->TraceConnect ("/$DerivedA/deriveda-x", MakeCallback (&ObjectTest::DerivedATrace, this)); + baseB->TraceConnect ("/$DerivedA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this)); + m_derivedATrace = false; + m_baseATrace = false; + derivedA->DerivedGenerateTrace (8); + derivedA->BaseGenerateTrace (9); + NS_TEST_ASSERT (m_derivedATrace); + NS_TEST_ASSERT (m_baseATrace); + baseB->TraceDisconnect ("/$DerivedA/deriveda-x", MakeCallback (&ObjectTest::BaseATrace, this)); + baseB->TraceDisconnect ("/$DerivedA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this)); + + baseB->TraceConnect ("/$DerivedA/*", MakeCallback (&ObjectTest::DerivedATrace, this)); + m_derivedATrace = false; + derivedA->DerivedGenerateTrace (10); + NS_TEST_ASSERT (m_derivedATrace); + // here, we have connected the derived trace sink to all + // trace sources, including the base trace source. + m_derivedATrace = false; + derivedA->BaseGenerateTrace (11); + NS_TEST_ASSERT (m_derivedATrace); + baseB->TraceDisconnect ("/$DerivedA/*", MakeCallback (&ObjectTest::BaseATrace, this)); + + return result; } static ObjectTest g_interfaceObjectTests; diff --git a/src/core/object.h b/src/core/object.h index d45d7f67c..36aa3a384 100644 --- a/src/core/object.h +++ b/src/core/object.h @@ -24,9 +24,13 @@ #include #include #include "ptr.h" +#include "trace-resolver.h" namespace ns3 { +class TraceContext; +class CallbackBase; + /** * \brief a unique identifier for an interface. * @@ -56,6 +60,11 @@ public: * id is not a valid interface id. */ static InterfaceId LookupParent (InterfaceId iid); + + /** + * \returns the name of this interface. + */ + std::string GetName (void) const; ~InterfaceId (); private: InterfaceId (uint16_t iid); @@ -131,6 +140,30 @@ public: * on one to get the other, and vice-versa. */ void AddInterface (Ptr other); + + /** + * \param path the path to match for the callback + * \param cb callback to connect + * + * Connect the input callback to all trace sources which + * match the input path. + * + */ + void TraceConnect (std::string path, const CallbackBase &cb) const; + /** + * \param path the path to match for the callback + * \param cb callback to disconnect + * + * Disconnect the input callback from all trace sources which + * match the input path. + */ + void TraceDisconnect (std::string path, const CallbackBase &cb) const; + /** + * \returns the trace resolver associated to this object. + * + * This method should be rarely called by users. + */ + virtual Ptr GetTraceResolver (void) const; protected: /** * \param iid an InterfaceId @@ -147,12 +180,17 @@ protected: */ virtual void DoDispose (void); private: + friend class InterfaceIdTraceResolver; Ptr DoQueryInterface (InterfaceId iid) const; + void DoCollectSources (std::string path, const TraceContext &context, + TraceResolver::SourceCollection *collection) const; + void DoTraceAll (std::ostream &os, const TraceContext &context) const; bool Check (void) const; void MaybeDelete (void) const; mutable uint32_t m_count; InterfaceId m_iid; bool m_disposed; + mutable bool m_collecting; Object *m_next; }; diff --git a/src/core/random-variable-default-value.cc b/src/core/random-variable-default-value.cc index 3217c3513..14fdfa5a3 100644 --- a/src/core/random-variable-default-value.cc +++ b/src/core/random-variable-default-value.cc @@ -19,7 +19,7 @@ * Author: Mathieu Lacage */ #include "random-variable-default-value.h" -#include "ns3/debug.h" +#include "debug.h" NS_DEBUG_COMPONENT_DEFINE ("RandomVariableDefaultValue"); diff --git a/src/common/stream-tracer-test.cc b/src/core/stream-tracer-test.cc similarity index 98% rename from src/common/stream-tracer-test.cc rename to src/core/stream-tracer-test.cc index f38e80dc4..f708015b6 100644 --- a/src/common/stream-tracer-test.cc +++ b/src/core/stream-tracer-test.cc @@ -19,7 +19,7 @@ * Author: Mathieu Lacage */ #include "stream-tracer.h" -#include "ns3/test.h" +#include "test.h" #include #ifdef RUN_SELF_TESTS diff --git a/src/common/stream-tracer.h b/src/core/stream-tracer.h similarity index 100% rename from src/common/stream-tracer.h rename to src/core/stream-tracer.h diff --git a/src/common/sv-trace-source.h b/src/core/sv-trace-source.h similarity index 93% rename from src/common/sv-trace-source.h rename to src/core/sv-trace-source.h index ce5511705..8cbb2447b 100644 --- a/src/common/sv-trace-source.h +++ b/src/core/sv-trace-source.h @@ -23,11 +23,12 @@ #define SV_TRACE_SOURCE_H #include "callback-trace-source.h" +#include "trace-source.h" #include namespace ns3 { -class SVTraceSourceBase { +class SVTraceSourceBase : public TraceSource { public: typedef CallbackTraceSource ChangeNotifyCallback; @@ -37,14 +38,17 @@ public: return *this; } - ~SVTraceSourceBase () {} + virtual ~SVTraceSourceBase () {} - void AddCallback (CallbackBase const & callback, TraceContext const & context) { + virtual void AddCallback (CallbackBase const & callback, TraceContext const & context) { m_callback.AddCallback (callback, context); } - void RemoveCallback (CallbackBase const & callback) { + virtual void RemoveCallback (CallbackBase const & callback) { m_callback.RemoveCallback (callback); } + virtual void ConnectPrinter (std::ostream &os, const TraceContext &context) { + m_callback.ConnectPrinter (os, context); + } protected: void Notify (int64_t oldVal, int64_t newVal) { if (oldVal != newVal) @@ -62,7 +66,7 @@ class UVTraceSource; /** * \brief trace variables of type "signed integer" - * \ingroup lowleveltracing + * \ingroup tracing * * This template class implements a POD type: it * behaves like any other variable of type "signed integer" @@ -74,7 +78,7 @@ class UVTraceSource; * ns3::UVTraceSource : \code #include - #include "ns3/sv-trace-source.h" + #include "sv-trace-source.h" ns3::SVTraceSource var; \endcode diff --git a/src/core/test.h b/src/core/test.h index 356c08ee2..809c44f0d 100644 --- a/src/core/test.h +++ b/src/core/test.h @@ -118,6 +118,23 @@ private: << ", got " << (got) << std::endl; \ result = false; \ } +/** + * Convenience macro to check that a value returned by a test is what + * is expected. Note: this macro assumes a 'bool result = true' + * declaration exists in the test function body, and that the function + * returns that value. + * + * \param got value obtained from the test + * \param expected value that the test is expected to return + */ +#define NS_TEST_ASSERT_UNEQUAL(got, expected) \ + if ((got) == (expected)) \ + { \ + Failure () << __FILE__ << ":" <<__LINE__ \ + << ": did not want " << (expected) \ + << ", got " << (got) << std::endl; \ + result = false; \ + } /** * Convenience macro to check an assertion is held during an unit * test. Note: this macro assumes a 'bool result = true' declaration diff --git a/src/common/trace-context-element.cc b/src/core/trace-context-element.cc similarity index 80% rename from src/common/trace-context-element.cc rename to src/core/trace-context-element.cc index 838250af8..dee4e97f4 100644 --- a/src/common/trace-context-element.cc +++ b/src/core/trace-context-element.cc @@ -2,6 +2,13 @@ namespace ns3 { +std::string +ElementRegistry::GetTypeName (uint16_t uid) +{ + InfoVector *vec = GetInfoVector (); + struct Info info = (*vec)[uid - 1]; + return info.getTypeName (); +} uint32_t ElementRegistry::GetSize (uint16_t uid) { diff --git a/src/common/trace-context-element.h b/src/core/trace-context-element.h similarity index 87% rename from src/common/trace-context-element.h rename to src/core/trace-context-element.h index e1c36c4d9..aba7c2598 100644 --- a/src/common/trace-context-element.h +++ b/src/core/trace-context-element.h @@ -37,6 +37,8 @@ namespace ns3 { * This method takes a c++ output stream and argument and is * expected to write an ascii string describing its content * in this output stream. + * - a public GetTypeName method which returns the fully-qualified + * c++ type name of this subclass as a string. * * A typical subclass should look like this: * \code @@ -48,6 +50,7 @@ namespace ns3 { * MyContext (); * ~MyContext (); * void Print (std::ostream &os) const; + * std::string GetTypeName (void) const; * * // the user-specific API to manipulate the context. * void SetData (uint8_t data); @@ -71,6 +74,12 @@ namespace ns3 { * { * os << "mycontext=" << (uint32_t) m_myContextData; * } + * std::string + * MyContext::GetTypeName (void) const + * { + * // return a fully-qualified c++ type name + * return "MyContext"; + * } * void * MyContext::SetData (uint8_t data) * { @@ -115,19 +124,24 @@ public: static uint32_t GetSize (uint16_t uid); static void Print (uint16_t uid, uint8_t *instance, std::ostream &os); + static std::string GetTypeName (uint16_t uid); static void Destroy (uint16_t uid, uint8_t *instance); private: + typedef std::string (*GetTypeNameCb) (void); typedef void (*PrintCb) (uint8_t *instance, std::ostream &os); typedef void (*DestroyCb) (uint8_t *instance); struct Info { uint32_t size; std::string uidString; + GetTypeNameCb getTypeName; PrintCb print; DestroyCb destroy; }; typedef std::vector InfoVector; static InfoVector *GetInfoVector (void); template + static std::string DoGetTypeName (void); + template static void DoPrint (uint8_t *instance, std::ostream &os); template static void DoDestroy (uint8_t *instance); @@ -143,6 +157,13 @@ ElementRegistry::DoPrint (uint8_t *instance, std::ostream &os) obj.Print (os); } template +std::string +ElementRegistry::DoGetTypeName (void) +{ + static T obj; + return obj.GetTypeName (); +} +template void ElementRegistry::DoDestroy (uint8_t *instance) { @@ -169,6 +190,7 @@ ElementRegistry::AllocateUid (std::string name) struct Info info; info.size = sizeof (T); info.uidString = name; + info.getTypeName = &ElementRegistry::DoGetTypeName; info.print = &ElementRegistry::DoPrint; info.destroy = &ElementRegistry::DoDestroy; vec->push_back (info); diff --git a/src/common/trace-context.cc b/src/core/trace-context.cc similarity index 65% rename from src/common/trace-context.cc rename to src/core/trace-context.cc index 50e9d0a73..af3ac2cfa 100644 --- a/src/common/trace-context.cc +++ b/src/core/trace-context.cc @@ -20,10 +20,56 @@ */ #include "trace-context.h" #include "trace-context-element.h" -#include "ns3/assert.h" +#include "assert.h" namespace ns3 { +TraceContext::Iterator::Iterator () + : m_buffer (0), + m_size (0), + m_current (0) +{} +TraceContext::Iterator::Iterator (uint8_t *buffer, uint16_t size) + : m_buffer (buffer), + m_size (size), + m_current (0) +{ + m_uid = m_buffer[m_current]; +} +bool +TraceContext::Iterator::IsLast (void) const +{ + if (m_buffer == 0 || m_uid == 0 || m_current >= m_size) + { + return true; + } + return false; +} +void +TraceContext::Iterator::Next (void) +{ + if (m_buffer == 0) + { + return; + } + if (m_uid == 0) + { + return; + } + else + { + uint8_t size = ElementRegistry::GetSize (m_uid); + m_current += 1 + size; + } + m_uid = m_buffer[m_current]; +} +std::string +TraceContext::Iterator::Get (void) const +{ + std::string name = ElementRegistry::GetTypeName (m_uid); + return name; +} + TraceContext::TraceContext () : m_data (0) {} @@ -68,7 +114,7 @@ TraceContext::~TraceContext () } void -TraceContext::Add (TraceContext const &o) +TraceContext::Union (TraceContext const &o) { if (o.m_data == 0) { @@ -230,10 +276,93 @@ TraceContext::Print (std::ostream &os) const } } while (true); } +TraceContext::Iterator +TraceContext::Begin (void) const +{ + if (m_data == 0) + { + return Iterator (); + } + return Iterator (m_data->data, m_data->size); +} + +void +TraceContext::PrintAvailable (std::ostream &os, std::string separator) const +{ + if (m_data == 0) + { + return; + } + uint8_t currentUid; + uint16_t i = 0; + do { + currentUid = m_data->data[i]; + uint8_t size = ElementRegistry::GetSize (currentUid); + os << ElementRegistry::GetTypeName (currentUid); + i += 1 + size; + if (i < m_data->size && currentUid != 0) + { + os << separator; + } + else + { + break; + } + } while (true); +} + +bool +TraceContext::IsSimilar (const TraceContext &o) const +{ + if (m_data == 0 && o.m_data == 0) + { + return true; + } + if ((m_data != 0 && o.m_data == 0) || + (m_data == 0 && o.m_data != 0)) + { + return false; + } + uint8_t myCurrentUid; + uint16_t myI = 0; + uint8_t otherCurrentUid; + uint16_t otherI = 0; + + myCurrentUid = m_data->data[myI]; + otherCurrentUid = o.m_data->data[otherI]; + + while (myCurrentUid == otherCurrentUid && + myCurrentUid != 0 && + otherCurrentUid != 0 && + myI < m_data->size && + otherI < o.m_data->size) + { + uint8_t mySize = ElementRegistry::GetSize (myCurrentUid); + uint8_t otherSize = ElementRegistry::GetSize (otherCurrentUid); + myI += 1 + mySize; + otherI += 1 + otherSize; + myCurrentUid = m_data->data[myI]; + otherCurrentUid = o.m_data->data[otherI]; + } + if (myCurrentUid == 0 && otherCurrentUid == 0) + { + return true; + } + else + { + return false; + } +} + +std::ostream& operator<< (std::ostream& os, const TraceContext &context) +{ + context.Print (os); + return os; +} }//namespace ns3 -#include "ns3/test.h" +#include "test.h" #include namespace ns3 { @@ -242,8 +371,8 @@ template class Ctx : public TraceContextElement { public: - static uint16_t GetUid (void) {static uint16_t uid = AllocateUid > (GetName ()); return uid;} - static std::string GetName (void) {std::ostringstream oss; oss << "Ctx" << N; return oss.str ();} + static uint16_t GetUid (void) {static uint16_t uid = AllocateUid > (GetTypeName ()); return uid;} + static std::string GetTypeName (void) {std::ostringstream oss; oss << "Ctx" << N; return oss.str ();} Ctx () : m_v (0) {} Ctx (int v) : m_v (v) {} void Print (std::ostream &os) {os << N;} @@ -278,31 +407,31 @@ TraceContextTest::RunTests (void) { ok = false; } - ctx.Add (v0); - ctx.Add (v0); + ctx.AddElement (v0); + ctx.AddElement (v0); if (ctx.SafeAdd (v01)) { ok = false; } - ctx.Get (v0); - ctx.Add (v1); - ctx.Get (v1); - ctx.Get (v0); - ctx.Get (v1); + ctx.GetElement (v0); + ctx.AddElement (v1); + ctx.GetElement (v1); + ctx.GetElement (v0); + ctx.GetElement (v1); TraceContext copy = ctx; - ctx.Get (v0); - ctx.Get (v1); - copy.Get (v0); - copy.Get (v1); - copy.Add (v2); - copy.Get (v0); - copy.Get (v1); - copy.Get (v2); - ctx.Add (v3); - ctx.Get (v0); - ctx.Get (v1); - ctx.Get (v3); + ctx.GetElement (v0); + ctx.GetElement (v1); + copy.GetElement (v0); + copy.GetElement (v1); + copy.AddElement (v2); + copy.GetElement (v0); + copy.GetElement (v1); + copy.GetElement (v2); + ctx.AddElement (v3); + ctx.GetElement (v0); + ctx.GetElement (v1); + ctx.GetElement (v3); if (ctx.SafeGet (v2)) { @@ -312,14 +441,14 @@ TraceContextTest::RunTests (void) { ok = false; } - ctx.Add (copy); - ctx.Get (v2); + ctx.Union (copy); + ctx.GetElement (v2); if (copy.SafeGet (v3)) { ok = false; } - copy.Add (ctx); - copy.Get (v3); + copy.Union (ctx); + copy.GetElement (v3); return ok; } diff --git a/src/common/trace-context.h b/src/core/trace-context.h similarity index 65% rename from src/common/trace-context.h rename to src/core/trace-context.h index eee3c960c..908f3ecb9 100644 --- a/src/common/trace-context.h +++ b/src/core/trace-context.h @@ -23,26 +23,28 @@ #include #include -#include "ns3/fatal-error.h" +#include "fatal-error.h" #include "trace-context-element.h" namespace ns3 { /** * \brief Provide context to trace sources - * \ingroup lowleveltracing + * \ingroup tracing * * Instances of this class are used to hold context * for each trace source. Each instance holds a list of - * 'contexts'. Trace sinks can lookup these contexts + * TraceContextElement. Trace sinks can lookup these contexts * from this list with the ns3::TraceContext::Get method. + * They can also ask the TraceContext for the list of + * TraceContextElements it contains with the PrintAvailable method. * * This class is implemented * using Copy On Write which means that copying unmodified * versions of this class is very cheap. However, modifying * the content of this class through a call - * to ns3::TraceContext::Add will trigger a costly memory - * reallocation if needed. + * to ns3::TraceContext::AddElement or ns3::TraceContext::Union + * will trigger a costly memory reallocation if needed. */ class TraceContext { @@ -54,32 +56,73 @@ public: /** * \param context add context to list of trace contexts. + * + * A copy of the input context is appended at the end of the list + * stored in this TraceContext. */ template - void Add (T const &context); + void AddElement (T const &context); /** * \param o the other context * * Perform the Union operation (in the sense of set theory) on the * two input lists of elements. This method is used in the - * ns3::CallbackTraceSourceSource class when multiple sinks are connected + * ns3::CallbackTraceSource class when multiple sinks are connected * to a single source to ensure that the source does not need * to store a single TraceContext instance per connected sink. * Instead, all sinks share the same TraceContext. */ - void Add (TraceContext const &o); + void Union (TraceContext const &o); /** * \param context context to get from this list of trace contexts. - * - * This method cannot fail. If the requested trace context is not - * stored in this TraceContext, then, the program will halt. + * \returns true if the requested trace context element was found + * in this TraceContext, false otherwise. */ template - void Get (T &context) const; + bool GetElement (T &context) const; + /** + * \param os a c++ STL output stream + * + * Iterate over the list of TraceContextElement stored in this + * TraceContext and invoke each of their Print method. + */ void Print (std::ostream &os) const; + /** + * \param os a c++ STL output stream + * \param separator the separator inserted between each TraceContextElement typename. + * + * Print the typename of each TraceContextElement stored in this TraceContext. + */ + void PrintAvailable (std::ostream &os, std::string separator) const; + class Iterator + { + public: + void Next (void); + bool IsLast (void) const; + std::string Get (void) const; + private: + friend class TraceContext; + Iterator (); + Iterator (uint8_t *buffer, uint16_t index); + uint8_t *m_buffer; + uint16_t m_size; + uint16_t m_current; + uint8_t m_uid; + }; + Iterator Begin (void) const; + /** + * \param o another trace context + * \returns true if the input trace context contains exactly the same set of + * TraceContextElement instances, false otherwise. + * + * This method does not test for equality: the content of each matching + * TraceContextElement could be different. It merely checks that both + * trace contexts contain the same types of TraceContextElements. + */ + bool IsSimilar (const TraceContext &o) const; private: friend class TraceContextTest; // used exclusively for testing code. @@ -99,13 +142,15 @@ private: } * m_data; }; +std::ostream& operator<< (std::ostream& os, const TraceContext &context); + }//namespace ns3 namespace ns3 { template void -TraceContext::Add (T const &context) +TraceContext::AddElement (T const &context) { const TraceContextElement *parent; // if the following assignment fails, it is because the input @@ -119,8 +164,8 @@ TraceContext::Add (T const &context) } } template -void -TraceContext::Get (T &context) const +bool +TraceContext::GetElement (T &context) const { TraceContextElement *parent; // if the following assignment fails, it is because the input @@ -128,10 +173,7 @@ TraceContext::Get (T &context) const parent = &context; uint8_t *data = (uint8_t *) &context; bool found = DoGet (T::GetUid (), data); - if (!found) - { - NS_FATAL_ERROR ("Type not stored in TraceContext"); - } + return found; } template bool diff --git a/src/core/trace-doc.cc b/src/core/trace-doc.cc new file mode 100644 index 000000000..b41089d10 --- /dev/null +++ b/src/core/trace-doc.cc @@ -0,0 +1,74 @@ +#include "trace-doc.h" + +namespace ns3 { + +TraceDoc::TraceDoc () + : m_help ("empty help") +{} + +TraceDoc::TraceDoc (std::string help) + : m_help (help) +{} +TraceDoc::TraceDoc (std::string help, + std::string arg0Type, + std::string arg0Help) + : m_help (help) +{ + m_argVector.push_back (std::make_pair (arg0Type, arg0Help)); +} +TraceDoc::TraceDoc (std::string help, + std::string arg0Type, + std::string arg0Help, + std::string arg1Type, + std::string arg1Help) + : m_help (help) +{ + m_argVector.push_back (std::make_pair (arg0Type, arg0Help)); + m_argVector.push_back (std::make_pair (arg1Type, arg1Help)); +} +TraceDoc::TraceDoc (std::string help, + std::string arg0Type, + std::string arg0Help, + std::string arg1Type, + std::string arg1Help, + std::string arg2Type, + std::string arg2Help) + : m_help (help) +{ + m_argVector.push_back (std::make_pair (arg0Type, arg0Help)); + m_argVector.push_back (std::make_pair (arg1Type, arg1Help)); + m_argVector.push_back (std::make_pair (arg2Type, arg2Help)); +} +TraceDoc::TraceDoc (std::string help, + std::string arg0Type, + std::string arg0Help, + std::string arg1Type, + std::string arg1Help, + std::string arg2Type, + std::string arg2Help, + std::string arg3Type, + std::string arg3Help) + : m_help (help) +{ + m_argVector.push_back (std::make_pair (arg0Type, arg0Help)); + m_argVector.push_back (std::make_pair (arg1Type, arg1Help)); + m_argVector.push_back (std::make_pair (arg2Type, arg2Help)); + m_argVector.push_back (std::make_pair (arg3Type, arg3Help)); +} +std::string +TraceDoc::GetHelp (void) const +{ + return m_help; +} +TraceDoc::Iterator +TraceDoc::ArgsBegin (void) const +{ + return m_argVector.begin (); +} +TraceDoc::Iterator +TraceDoc::ArgsEnd (void) const +{ + return m_argVector.end (); +} + +} // namespace ns3 diff --git a/src/core/trace-doc.h b/src/core/trace-doc.h new file mode 100644 index 000000000..e3236826a --- /dev/null +++ b/src/core/trace-doc.h @@ -0,0 +1,103 @@ +#ifndef TRACE_DOC_H +#define TRACE_DOC_H + +#include +#include + +namespace ns3 { + +/** + * \brief describe the signature of a trace source + */ +class TraceDoc +{ + typedef std::vector > ArgVector; +public: + typedef ArgVector::const_iterator Iterator; + TraceDoc (); + /** + * \param help a description of the purpose of the trace source + */ + TraceDoc (std::string help); + /** + * \param help a description of the purpose of the trace source + * \param arg1Type the fully-qualified typename of the first argument of the trace source + * \param arg1Help the purpose of the first argument of the trace source + */ + TraceDoc (std::string help, + std::string arg1Type, + std::string arg1Help); + /** + * \param help a description of the purpose of the trace source + * \param arg1Type the fully-qualified typename of the first argument of the trace source + * \param arg1Help the purpose of the first argument of the trace source + * \param arg2Type the fully-qualified typename of the second argument of the trace source + * \param arg2Help the purpose of the second argument of the trace source + */ + TraceDoc (std::string help, + std::string arg1Type, + std::string arg1Help, + std::string arg2Type, + std::string arg2Help); + /** + * \param help a description of the purpose of the trace source + * \param arg1Type the fully-qualified typename of the first argument of the trace source + * \param arg1Help the purpose of the first argument of the trace source + * \param arg2Type the fully-qualified typename of the second argument of the trace source + * \param arg2Help the purpose of the second argument of the trace source + * \param arg3Type the fully-qualified typename of the third argument of the trace source + * \param arg3Help the purpose of the third argument of the trace source + */ + TraceDoc (std::string help, + std::string arg1Type, + std::string arg1Help, + std::string arg2Type, + std::string arg2Help, + std::string arg3Type, + std::string arg3Help); + /** + * \param help a description of the purpose of the trace source + * \param arg1Type the fully-qualified typename of the first argument of the trace source + * \param arg1Help the purpose of the first argument of the trace source + * \param arg2Type the fully-qualified typename of the second argument of the trace source + * \param arg2Help the purpose of the second argument of the trace source + * \param arg3Type the fully-qualified typename of the third argument of the trace source + * \param arg3Help the purpose of the third argument of the trace source + * \param arg4Type the fully-qualified typename of the fourth argument of the trace source + * \param arg4Help the purpose of the fourth argument of the trace source + */ + TraceDoc (std::string help, + std::string arg1Type, + std::string arg1Help, + std::string arg2Type, + std::string arg2Help, + std::string arg3Type, + std::string arg3Help, + std::string arg4Type, + std::string arg4Help); + /** + * \returns the help string associated to this trace source + */ + std::string GetHelp (void) const; + /** + * \returns an iterator which points to the first descriptor of the trace source. + * + * Each descriptor is a pair of strings. The first one describes the type of the argument + * while the second one describeds the purpose of the argument. + */ + Iterator ArgsBegin (void) const; + /** + * \returns an iterator which points to the last descriptor of the trace source. + * + * Each descriptor is a pair of strings. The first one describes the type of the argument + * while the second one describeds the purpose of the argument. + */ + Iterator ArgsEnd (void) const; +private: + ArgVector m_argVector; + std::string m_help; +}; + +} // namespace ns3 + +#endif /* TRACE_DOC_H */ diff --git a/src/core/trace-resolver.cc b/src/core/trace-resolver.cc new file mode 100644 index 000000000..d891c94c4 --- /dev/null +++ b/src/core/trace-resolver.cc @@ -0,0 +1,107 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 INRIA + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Mathieu Lacage + */ +#include "trace-resolver.h" +#include "debug.h" + +NS_DEBUG_COMPONENT_DEFINE ("TraceResolver"); + +namespace ns3 { + +TraceResolver::TraceResolver () + : m_count (1) +{} + +TraceResolver::~TraceResolver () +{} + +void +TraceResolver::Ref (void) +{ + m_count++; +} +void +TraceResolver::Unref (void) +{ + m_count--; + if (m_count == 0) + { + NS_DEBUG ("delete "<path == path && + context.IsSimilar (i->context)) + { + return; + } + } + struct Source source; + source.path = path; + source.context = context; + source.doc = doc; + m_sources.push_back (source); +} +TraceResolver::SourceCollection::Iterator +TraceResolver::SourceCollection::Begin (void) const +{ + return m_sources.begin (); +} +TraceResolver::SourceCollection::Iterator +TraceResolver::SourceCollection::End (void) const +{ + return m_sources.end (); +} +}//namespace ns3 diff --git a/src/core/trace-resolver.h b/src/core/trace-resolver.h new file mode 100644 index 000000000..027beb5c1 --- /dev/null +++ b/src/core/trace-resolver.h @@ -0,0 +1,159 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 INRIA + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Mathieu Lacage + */ +#ifndef TRACE_RESOLVER_H +#define TRACE_RESOLVER_H + +#include +#include +#include "trace-context.h" +#include "trace-doc.h" + +namespace ns3 { + +class CallbackBase; + +/** + * \brief the base class which is used to recursively perform trace + * namespace resolution. + * \ingroup tracing + * + * Although users could conceivably implement their own trace resolver + * subclasses, doing so is complicated so, it is recommended to use + * the default implementation ns3::CompositeTraceResolver instead. + */ +class TraceResolver +{ +public: + + TraceResolver (); + virtual ~TraceResolver (); + void Ref (void); + void Unref (void); + + /** + * \param path the namespace path to resolver + * \param cb the callback to connect to the matching namespace + * \param context the context in which to store the trace context + * + * First, extract the leading path element from the input path, and + * match this leading patch element against any terminal trace source + * contained in this trace resolver. + * Second, recursively resolve the rest of the path using other + * objects if there are any. + * If there is any TraceContextElement associated to one of the matching + * elements, it should be added to the input TraceContext. + */ + virtual void Connect (std::string path, CallbackBase const &cb, const TraceContext &context) = 0; + /** + * \param path the namespace path to resolver + * \param cb the callback to disconnect in the matching namespace + * + * This method should behave as Connect. + */ + virtual void Disconnect (std::string path, CallbackBase const &cb) = 0; + + /** + * \brief hold a list of trace sources + */ + class SourceCollection + { + public: + /** + * \brief describe a single trace source + */ + struct Source + { + /** + * The trace path associated to this trace source + */ + std::string path; + /** + * The trace context associated to this trace source + */ + TraceContext context; + /** + * Document the signature of this trace source + */ + TraceDoc doc; + }; + typedef std::vector::const_iterator Iterator; + void AddUnique (std::string path, + const TraceContext &context, + const TraceDoc &doc); + + /** + * \returns an iterator which points to the first element of the set of + * trace sources collected in this SourceCollection object. + */ + Iterator Begin (void) const; + /** + * \returns an iterator which points to the last element of the set of + * trace sources collected in this SourceCollection object. + */ + Iterator End (void) const; + private: + typedef std::vector SourceVector; + SourceVector m_sources; + }; + /** + * \param path the path to the current recursive level. + * \param context the trace context associated to the current recursive level + * \param collection the collection in which to gather every trace source found. + * + * This method is invoked recursively until all trace sources have been + * stored in the output SourceCollection argument. + */ + virtual void CollectSources (std::string path, const TraceContext &context, + SourceCollection *collection) = 0; + + /** + * \param os the output stream to which ascii output should be written. + * \param context the context associated to the current recursive level. + * + * This method is invoked recursively until each trace source has been + * connected to a trace sink which can output an ascii representation + * of each trace event on the output stream specified. + */ + virtual void TraceAll (std::ostream &os, const TraceContext &context) = 0; +protected: + /** + * \param path a namespace path + * \returns the initial element of the path. + * + * If the input path is "/foo/...", the return + * value is "foo". + */ + std::string GetElement (std::string path); + /** + * \param path a namespace path + * \returns the subpath. + * + * If the input path is "/foo/bar/...", the return + * value is "/bar/...". + */ + std::string GetSubpath (std::string path); +private: + uint32_t m_count; +}; + +}//namespace ns3 + +#endif /* TRACE_RESOLVER_H */ diff --git a/src/common/empty-trace-resolver.cc b/src/core/trace-source.cc similarity index 80% rename from src/common/empty-trace-resolver.cc rename to src/core/trace-source.cc index 18b9e5301..64c7d8960 100644 --- a/src/common/empty-trace-resolver.cc +++ b/src/core/trace-source.cc @@ -1,7 +1,6 @@ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2007 INRIA - * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -18,8 +17,15 @@ * * Author: Mathieu Lacage */ -#include "empty-trace-resolver.h" +#include "trace-source.h" +#include "trace-context.h" -ns3::EmptyTraceResolver::EmptyTraceResolver (TraceContext const &context) - : TraceResolver (context) -{} +namespace ns3 { + +void +TraceSource::AddCallback (CallbackBase const & callback) +{ + AddCallback (callback, TraceContext ()); +} + +} // namespace ns3 diff --git a/src/core/trace-source.h b/src/core/trace-source.h new file mode 100644 index 000000000..9a35a80ad --- /dev/null +++ b/src/core/trace-source.h @@ -0,0 +1,61 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 INRIA + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Mathieu Lacage + */ +#ifndef TRACE_SOURCE_H +#define TRACE_SOURCE_H + +#include + +namespace ns3 { + +class CallbackBase; +class TraceContext; + +/** + * \brief the base class for all trace sources + * + * Every trace source which wishes to be connectable and disconnectable with + * the TraceResolver system should derive from this base class and implement + * all three methods below. + */ +class TraceSource +{ +public: + virtual ~TraceSource () {} + /** + * \param callback the callback to connect to this trace source + * \param context the context associated to the input callback which should be passed + * back to the user. + */ + virtual void AddCallback (CallbackBase const & callback, TraceContext const & context) = 0; + /** + * \param callback the callback to connect to this trace source + */ + void AddCallback (CallbackBase const & callback); + /** + * \param callback the callback to disconnect from this trace source + */ + virtual void RemoveCallback (CallbackBase const & callback) = 0; + virtual void ConnectPrinter (std::ostream &os, TraceContext const &context) = 0; +}; + +} // namespace ns3 + +#endif /* TRACE_SOURCE_H */ diff --git a/src/core/uid-manager.cc b/src/core/uid-manager.cc index f6aa3f6de..364ab769c 100644 --- a/src/core/uid-manager.cc +++ b/src/core/uid-manager.cc @@ -19,8 +19,8 @@ * Author: Mathieu Lacage */ #include "uid-manager.h" -#include "ns3/fatal-error.h" -#include "ns3/assert.h" +#include "fatal-error.h" +#include "assert.h" namespace ns3 { diff --git a/src/common/uv-trace-source.h b/src/core/uv-trace-source.h similarity index 93% rename from src/common/uv-trace-source.h rename to src/core/uv-trace-source.h index b83873580..0fe84c826 100644 --- a/src/common/uv-trace-source.h +++ b/src/core/uv-trace-source.h @@ -23,11 +23,12 @@ #define UV_TRACE_SOURCE_H #include "callback-trace-source.h" +#include "trace-source.h" #include namespace ns3 { -class UVTraceSourceBase { +class UVTraceSourceBase : public TraceSource { public: typedef CallbackTraceSource ChangeNotifyCallback; @@ -42,11 +43,14 @@ public: } ~UVTraceSourceBase () {} - void AddCallback (CallbackBase const & callback, TraceContext const & context) { + virtual void AddCallback (CallbackBase const & callback, TraceContext const & context) { m_callback.AddCallback (callback, context); } - void RemoveCallback (CallbackBase const & callback) { - m_callback.RemoveCallback (callback); + virtual void RemoveCallback (CallbackBase const & callback) { + m_callback.RemoveCallback (callback); + } + virtual void ConnectPrinter (std::ostream &os, const TraceContext &context) { + m_callback.ConnectPrinter (os, context); } protected: @@ -66,7 +70,7 @@ class SVTraceSource; /** * \brief trace variables of type "unsigned integer" - * \ingroup lowleveltracing + * \ingroup tracing * * This template class implements a POD type: it * behaves like any other variable of type "unsigned integer" @@ -78,7 +82,7 @@ class SVTraceSource; * ns3::UVTraceSource : \code #include - #include "ns3/uv-trace-source.h" + #include "uv-trace-source.h" ns3::UVTraceSource var; \endcode diff --git a/src/common/variable-tracer-test.cc b/src/core/variable-tracer-test.cc similarity index 98% rename from src/common/variable-tracer-test.cc rename to src/core/variable-tracer-test.cc index 29f3fc148..bd996e739 100644 --- a/src/common/variable-tracer-test.cc +++ b/src/core/variable-tracer-test.cc @@ -22,8 +22,8 @@ #include "uv-trace-source.h" #include "sv-trace-source.h" #include "trace-context.h" -#include "ns3/test.h" -#include "ns3/callback.h" +#include "test.h" +#include "callback.h" namespace ns3 { diff --git a/src/core/wscript b/src/core/wscript index bba53ae71..455779fd6 100644 --- a/src/core/wscript +++ b/src/core/wscript @@ -42,6 +42,14 @@ def build(bld): 'type-name.cc', 'component-manager.cc', 'random-variable-default-value.cc', + 'variable-tracer-test.cc', + 'trace-context.cc', + 'trace-context-element.cc', + 'trace-resolver.cc', + 'callback-trace-source.cc', + 'composite-trace-resolver.cc', + 'trace-doc.cc', + 'trace-source.cc', ] if sys.platform == 'win32': @@ -73,5 +81,16 @@ def build(bld): 'component-manager.h', 'type-traits.h', 'random-variable-default-value.h', + 'trace-source.h', + 'uv-trace-source.h', + 'sv-trace-source.h', + 'fv-trace-source.h', + 'callback-trace-source.h', + 'trace-context.h', + 'trace-context-element.h', + 'trace-resolver.h', + 'composite-trace-resolver.h', + 'array-trace-resolver.h', + 'trace-doc.h', ] diff --git a/src/devices/csma/csma-net-device.cc b/src/devices/csma/csma-net-device.cc index 7cdcd455c..015b69913 100644 --- a/src/devices/csma/csma-net-device.cc +++ b/src/devices/csma/csma-net-device.cc @@ -57,6 +57,16 @@ CsmaTraceType::GetUid (void) static uint16_t uid = AllocateUid ("CsmaTraceType"); return uid; } +std::string +CsmaTraceType::GetTypeName (void) const +{ + return "ns3::CsmaTraceType"; +} +enum CsmaTraceType::Type +CsmaTraceType::Get (void) const +{ + return m_type; +} CsmaNetDevice::CsmaNetDevice (Ptr node) : NetDevice (node, Eui48Address::Allocate ()), @@ -449,20 +459,23 @@ CsmaNetDevice::TransmitReadyEvent (void) } } -TraceResolver * -CsmaNetDevice::DoCreateTraceResolver (TraceContext const &context) +Ptr +CsmaNetDevice::GetTraceResolver (void) const { - CompositeTraceResolver *resolver = new CompositeTraceResolver (context); - resolver->Add ("queue", - MakeCallback (&Queue::CreateTraceResolver, - PeekPointer (m_queue))); - resolver->Add ("rx", - m_rxTrace, - CsmaTraceType (CsmaTraceType::RX)); - resolver->Add ("drop", - m_dropTrace, - CsmaTraceType (CsmaTraceType::DROP)); - return resolver; + Ptr resolver = Create (); + resolver->AddComposite ("queue", m_queue); + resolver->AddSource ("rx", + TraceDoc ("receive MAC packet", + "const Packet &", "packet received"), + m_rxTrace, + CsmaTraceType (CsmaTraceType::RX)); + resolver->AddSource ("drop", + TraceDoc ("drop MAC packet", + "const Packet &", "packet dropped"), + m_dropTrace, + CsmaTraceType (CsmaTraceType::DROP)); + resolver->SetParentResolver (NetDevice::GetTraceResolver ()); + return resolver; } bool diff --git a/src/devices/csma/csma-net-device.h b/src/devices/csma/csma-net-device.h index 1c9ac075d..3c161cbf7 100644 --- a/src/devices/csma/csma-net-device.h +++ b/src/devices/csma/csma-net-device.h @@ -41,6 +41,9 @@ namespace ns3 { class Queue; class CsmaChannel; +/** + * \brief hold in a TraceContext the type of trace source from a CsmaNetDevice + */ class CsmaTraceType : public TraceContextElement { public: @@ -52,6 +55,11 @@ public: CsmaTraceType (); void Print (std::ostream &os) const; static uint16_t GetUid (void); + std::string GetTypeName (void) const; + /** + * \returns the type of the trace source which generated an event. + */ + enum Type Get (void) const; private: enum Type m_type; }; @@ -237,6 +245,13 @@ enum CsmaEncapsulationMode { protected: virtual bool DoNeedsArp (void) const; virtual void DoDispose (void); + /** + * Create a Trace Resolver for events in the net device. + * (NOT TESTED) + * @see class TraceResolver + */ + virtual Ptr GetTraceResolver (void) const; + /** * Get a copy of the attached Queue. * @@ -352,12 +367,6 @@ private: * @see TransmitStart () */ void TransmitReadyEvent (void); - /** - * Create a Trace Resolver for events in the net device. - * (NOT TESTED) - * @see class TraceResolver - */ - virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context); /** * Aborts the transmission of the current packet diff --git a/src/devices/point-to-point/point-to-point-net-device.cc b/src/devices/point-to-point/point-to-point-net-device.cc index ae4da905b..be7153074 100644 --- a/src/devices/point-to-point/point-to-point-net-device.cc +++ b/src/devices/point-to-point/point-to-point-net-device.cc @@ -51,6 +51,11 @@ PointToPointTraceType::GetUid (void) static uint16_t uid = AllocateUid ("PointToPointTraceType"); return uid; } +std::string +PointToPointTraceType::GetTypeName (void) const +{ + return "ns3::PointToPointTraceType"; +} PointToPointNetDevice::PointToPointNetDevice (Ptr node, @@ -190,15 +195,17 @@ void PointToPointNetDevice::TransmitComplete (void) TransmitStart(p); } -TraceResolver* PointToPointNetDevice::DoCreateTraceResolver ( - TraceContext const &context) +Ptr +PointToPointNetDevice::GetTraceResolver (void) const { - CompositeTraceResolver *resolver = new CompositeTraceResolver (context); - resolver->Add ("queue", - MakeCallback (&Queue::CreateTraceResolver, PeekPointer (m_queue))); - resolver->Add ("rx", - m_rxTrace, - PointToPointTraceType ()); + Ptr resolver = Create (); + resolver->AddComposite ("queue", m_queue); + resolver->AddSource ("rx", + TraceDoc ("receive MAC packet", + "const Packet &", "packet received"), + m_rxTrace, + PointToPointTraceType ()); + resolver->SetParentResolver (NetDevice::GetTraceResolver ()); return resolver; } diff --git a/src/devices/point-to-point/point-to-point-net-device.h b/src/devices/point-to-point/point-to-point-net-device.h index fa3d3b838..a5868bea4 100644 --- a/src/devices/point-to-point/point-to-point-net-device.h +++ b/src/devices/point-to-point/point-to-point-net-device.h @@ -38,12 +38,16 @@ namespace ns3 { class Queue; class PointToPointChannel; +/** + * \brief hold in a TraceContext the type of trace source from a PointToPointNetDevice + */ class PointToPointTraceType : public TraceContextElement { public: PointToPointTraceType (); void Print (std::ostream &os) const; static uint16_t GetUid (void); + std::string GetTypeName (void) const; }; /** @@ -152,6 +156,12 @@ public: */ void Receive (Packet& p); protected: + /** + * Create a Trace Resolver for events in the net device. + * + * @see class TraceResolver + */ + virtual Ptr GetTraceResolver (void) const; virtual void DoDispose (void); /** * Get a copy of the attached Queue. @@ -237,12 +247,6 @@ private: * */ void TransmitComplete(void); - /** - * Create a Trace Resolver for events in the net device. - * - * @see class TraceResolver - */ - virtual TraceResolver* DoCreateTraceResolver (TraceContext const &context); virtual bool DoNeedsArp (void) const; /** * Enumeration of the states of the transmit machine of the net device. diff --git a/src/internet-node/arp-cache.cc b/src/internet-node/arp-cache.cc index b4987daef..15a1d9316 100644 --- a/src/internet-node/arp-cache.cc +++ b/src/internet-node/arp-cache.cc @@ -19,16 +19,16 @@ * Author: Mathieu Lacage */ #include "ns3/assert.h" - #include "ns3/packet.h" #include "ns3/simulator.h" #include "arp-cache.h" #include "arp-header.h" +#include "ipv4-interface.h" namespace ns3 { -ArpCache::ArpCache (Ptr device, Ipv4Interface *interface) +ArpCache::ArpCache (Ptr device, Ptr interface) : m_device (device), m_interface (interface), m_aliveTimeout (Seconds (120)), @@ -47,7 +47,7 @@ ArpCache::GetDevice (void) const return m_device; } -Ipv4Interface * +Ptr ArpCache::GetInterface (void) const { return m_interface; diff --git a/src/internet-node/arp-cache.h b/src/internet-node/arp-cache.h index 2cd88c85f..adf106009 100644 --- a/src/internet-node/arp-cache.h +++ b/src/internet-node/arp-cache.h @@ -48,7 +48,7 @@ public: * \param device The hardware NetDevice associated with this ARP chache * \param interface the Ipv4Interface associated with this ARP chache */ - ArpCache (Ptr device, Ipv4Interface *interface); + ArpCache (Ptr device, Ptr interface); ~ArpCache (); /** * \return The NetDevice that this ARP cache is associated with @@ -57,7 +57,7 @@ public: /** * \return the Ipv4Interface that this ARP cache is associated with */ - Ipv4Interface *GetInterface (void) const; + Ptr GetInterface (void) const; void SetAliveTimeout (Time aliveTimeout); void SetDeadTimeout (Time deadTimeout); @@ -152,7 +152,7 @@ private: typedef sgi::hash_map::iterator CacheI; Ptr m_device; - Ipv4Interface *m_interface; + Ptr m_interface; Time m_aliveTimeout; Time m_deadTimeout; Time m_waitReplyTimeout; diff --git a/src/internet-node/arp-ipv4-interface.cc b/src/internet-node/arp-ipv4-interface.cc index 1584f087c..ed8ef584c 100644 --- a/src/internet-node/arp-ipv4-interface.cc +++ b/src/internet-node/arp-ipv4-interface.cc @@ -47,17 +47,16 @@ ArpIpv4Interface::~ArpIpv4Interface () NS_DEBUG ("ArpIpv4Interface::~ArpIpv4Interface ()"); } -TraceResolver * -ArpIpv4Interface::DoCreateTraceResolver (TraceContext const &context) +Ptr +ArpIpv4Interface::GetTraceResolver (void) const { NS_DEBUG ("ArpIpv4Interface::DoCreateTraceResolver ()"); - CompositeTraceResolver *resolver = new CompositeTraceResolver (context); + Ptr resolver = Create (); if (GetDevice () != 0) { - resolver->Add ("netdevice", - MakeCallback (&NetDevice::CreateTraceResolver, PeekPointer (GetDevice ()))); + resolver->AddComposite ("netdevice", GetDevice ()); } - + resolver->SetParentResolver (Ipv4Interface::GetTraceResolver ()); return resolver; } diff --git a/src/internet-node/arp-ipv4-interface.h b/src/internet-node/arp-ipv4-interface.h index 130a52256..ac4fc0e30 100644 --- a/src/internet-node/arp-ipv4-interface.h +++ b/src/internet-node/arp-ipv4-interface.h @@ -43,9 +43,10 @@ class ArpIpv4Interface : public Ipv4Interface ArpIpv4Interface (Ptr node, Ptr device); virtual ~ArpIpv4Interface (); - private: +protected: + virtual Ptr GetTraceResolver (void) const; +private: virtual void SendTo (Packet p, Ipv4Address dest); - virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context); Ptr m_node; }; diff --git a/src/internet-node/arp-l3-protocol.cc b/src/internet-node/arp-l3-protocol.cc index 100f1df88..bcc62bfe2 100644 --- a/src/internet-node/arp-l3-protocol.cc +++ b/src/internet-node/arp-l3-protocol.cc @@ -20,7 +20,6 @@ */ #include "ns3/packet.h" #include "ns3/debug.h" -#include "ns3/empty-trace-resolver.h" #include "ns3/node.h" #include "ns3/net-device.h" @@ -58,12 +57,6 @@ ArpL3Protocol::DoDispose (void) Object::DoDispose (); } -TraceResolver * -ArpL3Protocol::CreateTraceResolver (TraceContext const &context) -{ - return new EmptyTraceResolver (context); -} - ArpCache * ArpL3Protocol::FindCache (Ptr device) { @@ -75,7 +68,7 @@ ArpL3Protocol::FindCache (Ptr device) } } Ptr ipv4 = m_node->QueryInterface (Ipv4L3Protocol::iid); - Ipv4Interface *interface = ipv4->FindInterfaceForDevice (device); + Ptr interface = ipv4->FindInterfaceForDevice (device); ArpCache * cache = new ArpCache (device, interface); NS_ASSERT (device->IsBroadcast ()); device->SetLinkChangeCallback (MakeCallback (&ArpCache::Flush, cache)); diff --git a/src/internet-node/arp-l3-protocol.h b/src/internet-node/arp-l3-protocol.h index a2ea8227e..5f6819df6 100644 --- a/src/internet-node/arp-l3-protocol.h +++ b/src/internet-node/arp-l3-protocol.h @@ -48,8 +48,6 @@ public: */ ArpL3Protocol (Ptr node); virtual ~ArpL3Protocol (); - - virtual TraceResolver *CreateTraceResolver (TraceContext const &context); /** * \brief Recieve a packet */ diff --git a/src/internet-node/ascii-trace.cc b/src/internet-node/ascii-trace.cc index 961edd709..6c4d11c87 100644 --- a/src/internet-node/ascii-trace.cc +++ b/src/internet-node/ascii-trace.cc @@ -21,9 +21,9 @@ #include "ascii-trace.h" #include "ns3/trace-context.h" -#include "ns3/trace-root.h" #include "ns3/simulator.h" #include "ns3/node.h" +#include "ns3/node-list.h" #include "ns3/packet.h" #include "ns3/queue.h" @@ -41,19 +41,19 @@ void AsciiTrace::TraceAllQueues (void) { Packet::EnableMetadata (); - TraceRoot::Connect ("/nodes/*/devices/*/queue/enqueue", + NodeList::Connect ("/nodes/*/devices/*/queue/enqueue", MakeCallback (&AsciiTrace::LogDevQueueEnqueue, this)); - TraceRoot::Connect ("/nodes/*/devices/*/queue/dequeue", + NodeList::Connect ("/nodes/*/devices/*/queue/dequeue", MakeCallback (&AsciiTrace::LogDevQueueDequeue, this)); - TraceRoot::Connect ("/nodes/*/devices/*/queue/drop", + NodeList::Connect ("/nodes/*/devices/*/queue/drop", MakeCallback (&AsciiTrace::LogDevQueueDrop, this)); } void AsciiTrace::TraceAllNetDeviceRx (void) { Packet::EnableMetadata (); - TraceRoot::Connect ("/nodes/*/devices/*/rx", - MakeCallback (&AsciiTrace::LogDevRx, this)); + NodeList::Connect ("/nodes/*/devices/*/rx", + MakeCallback (&AsciiTrace::LogDevRx, this)); } void diff --git a/src/internet-node/internet-node.cc b/src/internet-node/internet-node.cc index 5c2a3de72..5a927b55f 100644 --- a/src/internet-node/internet-node.cc +++ b/src/internet-node/internet-node.cc @@ -74,13 +74,14 @@ InternetNode::Construct (void) Object::AddInterface (ipv4L4Demux); } -void -InternetNode::DoFillTraceResolver (CompositeTraceResolver &resolver) +Ptr +InternetNode::GetTraceResolver () const { - Node::DoFillTraceResolver (resolver); + Ptr resolver = Create (); Ptr ipv4 = QueryInterface (Ipv4L3Protocol::iid); - resolver.Add ("ipv4", - MakeCallback (&Ipv4L3Protocol::CreateTraceResolver, PeekPointer (ipv4))); + resolver->AddComposite ("ipv4", ipv4); + resolver->SetParentResolver (Node::GetTraceResolver ()); + return resolver; } void diff --git a/src/internet-node/internet-node.h b/src/internet-node/internet-node.h index deabd20eb..0c855029e 100644 --- a/src/internet-node/internet-node.h +++ b/src/internet-node/internet-node.h @@ -42,8 +42,8 @@ public: protected: virtual void DoDispose(void); + virtual Ptr GetTraceResolver (void) const; private: - virtual void DoFillTraceResolver (CompositeTraceResolver &resolver); bool ReceiveFromDevice (Ptr device, const Packet &p, uint16_t protocolNumber) const; void Construct (void); }; diff --git a/src/internet-node/ipv4-interface.cc b/src/internet-node/ipv4-interface.cc index c22a1e783..3c66ba7c4 100644 --- a/src/internet-node/ipv4-interface.cc +++ b/src/internet-node/ipv4-interface.cc @@ -22,6 +22,7 @@ #include "ipv4-interface.h" #include "ns3/ipv4-address.h" #include "ns3/net-device.h" +#include "ns3/trace-resolver.h" #include "ns3/debug.h" NS_DEBUG_COMPONENT_DEFINE ("Ipv4Interface"); @@ -46,6 +47,13 @@ Ipv4Interface::~Ipv4Interface () NS_DEBUG ("Ipv4Interface::~Ipv4Interface ()"); } +void +Ipv4Interface::DoDispose (void) +{ + m_netdevice = 0; + Object::DoDispose (); +} + Ptr Ipv4Interface::GetDevice (void) const { @@ -53,13 +61,6 @@ Ipv4Interface::GetDevice (void) const return m_netdevice; } -TraceResolver * -Ipv4Interface::CreateTraceResolver (TraceContext const &context) -{ - NS_DEBUG ("Ipv4Interface::CreateTraceResolver (" << &context << ")"); - return DoCreateTraceResolver (context); -} - void Ipv4Interface::SetAddress (Ipv4Address a) { diff --git a/src/internet-node/ipv4-interface.h b/src/internet-node/ipv4-interface.h index 1098c567c..1836aa3b7 100644 --- a/src/internet-node/ipv4-interface.h +++ b/src/internet-node/ipv4-interface.h @@ -26,6 +26,7 @@ #include #include "ns3/ipv4-address.h" #include "ns3/ptr.h" +#include "ns3/object.h" namespace ns3 { @@ -60,9 +61,8 @@ class TraceContext; * * Subclasses must implement the two methods: * - Ipv4Interface::SendTo - * - Ipv4Interface::DoCreateTraceResolver */ -class Ipv4Interface +class Ipv4Interface : public Object { public: /** @@ -73,17 +73,6 @@ public: Ipv4Interface (Ptr nd); virtual ~Ipv4Interface(); - /** - * \param context the trace context to use to construct the - * TraceResolver to return - * \returns a TraceResolver which can resolve all traces - * performed in this object. The caller must - * delete the returned object. - * - * This method will delegate the work to the private DoCreateTraceResolver - * method which is supposed to be implemented by subclasses. - */ - TraceResolver *CreateTraceResolver (TraceContext const &context); /** * \returns the underlying NetDevice. This method can return * zero if this interface has no associated NetDevice. @@ -150,10 +139,10 @@ public: */ void Send(Packet p, Ipv4Address dest); - - private: +protected: + virtual void DoDispose (void); +private: virtual void SendTo (Packet p, Ipv4Address dest) = 0; - virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context) = 0; Ptr m_netdevice; bool m_ifup; Ipv4Address m_address; diff --git a/src/internet-node/ipv4-l3-protocol.cc b/src/internet-node/ipv4-l3-protocol.cc index 80fefecfe..1c211edf1 100644 --- a/src/internet-node/ipv4-l3-protocol.cc +++ b/src/internet-node/ipv4-l3-protocol.cc @@ -22,7 +22,6 @@ #include "ns3/packet.h" #include "ns3/debug.h" #include "ns3/composite-trace-resolver.h" -#include "ns3/array-trace-resolver.h" #include "ns3/callback.h" #include "ns3/ipv4-address.h" #include "ns3/ipv4-route.h" @@ -88,30 +87,40 @@ Ipv4L3ProtocolTraceContextElement::GetUid (void) static uint16_t uid = AllocateUid ("Ipv4L3ProtocolTraceContextElement"); return uid; } +std::string +Ipv4L3ProtocolTraceContextElement::GetTypeName (void) const +{ + return "ns3::Ipv4L3ProtocolTraceContextElement"; +} -Ipv4l3ProtocolInterfaceIndex::Ipv4l3ProtocolInterfaceIndex () +Ipv4L3ProtocolInterfaceIndex::Ipv4L3ProtocolInterfaceIndex () : m_index (0) {} -Ipv4l3ProtocolInterfaceIndex::Ipv4l3ProtocolInterfaceIndex (uint32_t index) +Ipv4L3ProtocolInterfaceIndex::Ipv4L3ProtocolInterfaceIndex (uint32_t index) : m_index (index) {} uint32_t -Ipv4l3ProtocolInterfaceIndex::Get (void) const +Ipv4L3ProtocolInterfaceIndex::Get (void) const { return m_index; } void -Ipv4l3ProtocolInterfaceIndex::Print (std::ostream &os) const +Ipv4L3ProtocolInterfaceIndex::Print (std::ostream &os) const { os << "ipv4-interface=" << m_index; } uint16_t -Ipv4l3ProtocolInterfaceIndex::GetUid (void) +Ipv4L3ProtocolInterfaceIndex::GetUid (void) { - static uint16_t uid = AllocateUid ("Ipv4l3ProtocolInterfaceIndex"); + static uint16_t uid = AllocateUid ("Ipv4L3ProtocolInterfaceIndex"); return uid; } +std::string +Ipv4L3ProtocolInterfaceIndex::GetTypeName (void) const +{ + return "ns3::Ipv4L3ProtocolInterfaceIndex"; +} Ipv4L3Protocol::Ipv4L3Protocol(Ptr node) @@ -138,11 +147,6 @@ Ipv4L3Protocol::DoDispose (void) { NS_DEBUG("Ipv4L3Protocol::DoDispose ()"); - for (Ipv4InterfaceList::iterator i = m_interfaces.begin (); - i != m_interfaces.end (); i++) - { - delete (*i); - } m_interfaces.clear (); m_node = 0; m_staticRouting->Dispose (); @@ -155,7 +159,7 @@ Ipv4L3Protocol::SetupLoopback (void) { NS_DEBUG("Ipv4L3Protocol::SetupLoopback ()"); - Ipv4LoopbackInterface * interface = new Ipv4LoopbackInterface (m_node); + Ptr interface = Create (m_node); interface->SetAddress (Ipv4Address::GetLoopback ()); interface->SetNetworkMask (Ipv4Mask::GetLoopback ()); uint32_t index = AddIpv4Interface (interface); @@ -163,30 +167,29 @@ Ipv4L3Protocol::SetupLoopback (void) interface->SetUp (); } -TraceResolver * -Ipv4L3Protocol::CreateTraceResolver (TraceContext const &context) +Ptr +Ipv4L3Protocol::GetTraceResolver (void) const { - NS_DEBUG("Ipv4L3Protocol::CreateTraceResolver ()"); + NS_DEBUG("Ipv4L3Protocol::GetTraceResolver ()"); - CompositeTraceResolver *resolver = new CompositeTraceResolver (context); - resolver->Add ("tx", m_txTrace, Ipv4L3ProtocolTraceContextElement(Ipv4L3ProtocolTraceContextElement::TX)); - resolver->Add ("rx", m_rxTrace, Ipv4L3ProtocolTraceContextElement(Ipv4L3ProtocolTraceContextElement::RX)); - resolver->Add ("drop", m_dropTrace, Ipv4L3ProtocolTraceContextElement (Ipv4L3ProtocolTraceContextElement::DROP)); - resolver->Add ("interfaces", - MakeCallback (&Ipv4L3Protocol::InterfacesCreateTraceResolver, this)); - return resolver; -} - -TraceResolver * -Ipv4L3Protocol::InterfacesCreateTraceResolver (TraceContext const &context) const -{ - NS_DEBUG("Ipv4L3Protocol::InterfacesCreateTraceResolver ()"); - - ArrayTraceResolver *resolver = - new ArrayTraceResolver - (context, - MakeCallback (&Ipv4L3Protocol::GetNInterfaces, this), - MakeCallback (&Ipv4L3Protocol::GetInterface, this)); + Ptr resolver = Create (); + resolver->AddSource ("tx", + TraceDoc ("send ipv4 packet to outgoing interface", + "const Packet &", "packet sent", + "uint32_t", "index of output ipv4 interface"), + m_txTrace, Ipv4L3ProtocolTraceContextElement(Ipv4L3ProtocolTraceContextElement::TX)); + resolver->AddSource ("rx", + TraceDoc ("receive ipv4 packet from incoming interface", + "const Packet &", "packet received", + "uint32_t", "index of input ipv4 interface"), + m_rxTrace, Ipv4L3ProtocolTraceContextElement(Ipv4L3ProtocolTraceContextElement::RX)); + resolver->AddSource ("drop", + TraceDoc ("drop ipv4 packet", + "const Packet &", "packet dropped"), + m_dropTrace, Ipv4L3ProtocolTraceContextElement (Ipv4L3ProtocolTraceContextElement::DROP)); + resolver->AddArray ("interfaces", + m_interfaces.begin (), m_interfaces.end (), + Ipv4L3ProtocolInterfaceIndex ()); return resolver; } @@ -399,12 +402,12 @@ uint32_t Ipv4L3Protocol::AddInterface (Ptr device) { NS_DEBUG("Ipv4L3Protocol::AddInterface (" << &device << ")"); - Ipv4Interface *interface = new ArpIpv4Interface (m_node, device); + Ptr interface = Create (m_node, device); return AddIpv4Interface (interface); } uint32_t -Ipv4L3Protocol::AddIpv4Interface (Ipv4Interface *interface) +Ipv4L3Protocol::AddIpv4Interface (Ptrinterface) { NS_DEBUG("Ipv4L3Protocol::AddIpv4Interface (" << interface << ")"); uint32_t index = m_nInterfaces; @@ -413,7 +416,7 @@ Ipv4L3Protocol::AddIpv4Interface (Ipv4Interface *interface) return index; } -Ipv4Interface * +Ptr Ipv4L3Protocol::GetInterface (uint32_t index) const { NS_DEBUG("Ipv4L3Protocol::GetInterface (" << index << ")"); @@ -479,7 +482,7 @@ Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const return 0; } -Ipv4Interface * +Ptr Ipv4L3Protocol::FindInterfaceForDevice (Ptr device) { NS_DEBUG("Ipv4L3Protocol::FindInterfaceForDevice (" << &device << ")"); @@ -558,7 +561,7 @@ Ipv4L3Protocol::Send (Packet const &packet, for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin (); ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++) { - Ipv4Interface *outInterface = *ifaceIter; + Ptr outInterface = *ifaceIter; Packet packetCopy = packet; NS_ASSERT (packetCopy.GetSize () <= outInterface->GetMtu ()); @@ -602,7 +605,7 @@ Ipv4L3Protocol::SendRealOut (bool found, route.GetInterface ()); packet.AddHeader (ipHeader); - Ipv4Interface *outInterface = GetInterface (route.GetInterface ()); + Ptr outInterface = GetInterface (route.GetInterface ()); NS_ASSERT (packet.GetSize () <= outInterface->GetMtu ()); m_txTrace (packet, route.GetInterface ()); if (route.IsGateway ()) @@ -643,7 +646,7 @@ Ipv4L3Protocol::Forwarding ( for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++) { - Ipv4Interface *interface = *i; + Ptr interface = *i; if (interface->GetDevice () == device) { if (ipHeader.GetDestination ().IsEqual (interface->GetBroadcast ())) @@ -745,7 +748,7 @@ void Ipv4L3Protocol::SetAddress (uint32_t i, Ipv4Address address) { NS_DEBUG("Ipv4L3Protocol::SetAddress (" << i << ", " << address << ")"); - Ipv4Interface *interface = GetInterface (i); + Ptr interface = GetInterface (i); interface->SetAddress (address); } @@ -753,7 +756,7 @@ void Ipv4L3Protocol::SetNetworkMask (uint32_t i, Ipv4Mask mask) { NS_DEBUG("Ipv4L3Protocol::SetNetworkMask (" << i << ", " << mask << ")"); - Ipv4Interface *interface = GetInterface (i); + Ptr interface = GetInterface (i); interface->SetNetworkMask (mask); } @@ -761,7 +764,7 @@ Ipv4Mask Ipv4L3Protocol::GetNetworkMask (uint32_t i) const { NS_DEBUG("Ipv4L3Protocol::GetNetworkMask (" << i << ")"); - Ipv4Interface *interface = GetInterface (i); + Ptr interface = GetInterface (i); return interface->GetNetworkMask (); } @@ -769,7 +772,7 @@ Ipv4Address Ipv4L3Protocol::GetAddress (uint32_t i) const { NS_DEBUG("Ipv4L3Protocol::GetAddress (" << i << ")"); - Ipv4Interface *interface = GetInterface (i); + Ptr interface = GetInterface (i); return interface->GetAddress (); } @@ -849,7 +852,7 @@ uint16_t Ipv4L3Protocol::GetMtu (uint32_t i) const { NS_DEBUG("Ipv4L3Protocol::GetMtu (" << i << ")"); - Ipv4Interface *interface = GetInterface (i); + Ptr interface = GetInterface (i); return interface->GetMtu (); } @@ -857,7 +860,7 @@ bool Ipv4L3Protocol::IsUp (uint32_t i) const { NS_DEBUG("Ipv4L3Protocol::IsUp (" << i << ")"); - Ipv4Interface *interface = GetInterface (i); + Ptr interface = GetInterface (i); return interface->IsUp (); } @@ -865,7 +868,7 @@ void Ipv4L3Protocol::SetUp (uint32_t i) { NS_DEBUG("Ipv4L3Protocol::SetUp (" << i << ")"); - Ipv4Interface *interface = GetInterface (i); + Ptr interface = GetInterface (i); interface->SetUp (); // If interface address and network mask have been set, add a route @@ -883,7 +886,7 @@ void Ipv4L3Protocol::SetDown (uint32_t ifaceIndex) { NS_DEBUG("Ipv4L3Protocol::SetDown (" << ifaceIndex << ")"); - Ipv4Interface *interface = GetInterface (ifaceIndex); + Ptr interface = GetInterface (ifaceIndex); interface->SetDown (); // Remove all routes that are going through this interface diff --git a/src/internet-node/ipv4-l3-protocol.h b/src/internet-node/ipv4-l3-protocol.h index fdc2456f5..001852571 100644 --- a/src/internet-node/ipv4-l3-protocol.h +++ b/src/internet-node/ipv4-l3-protocol.h @@ -44,6 +44,9 @@ class Node; class TraceResolver; class TraceContext; +/** + * \brief hold in a TraceContext the type of trace source used by this Ipv4L3Protocol + */ class Ipv4L3ProtocolTraceContextElement : public TraceContextElement { public: @@ -54,23 +57,40 @@ public: }; Ipv4L3ProtocolTraceContextElement (); Ipv4L3ProtocolTraceContextElement (enum Type type); + /** + * \returns true if this is a tx event, false otherwise. + */ bool IsTx (void) const; + /** + * \returns true if this is a rx event, false otherwise. + */ bool IsRx (void) const; + /** + * \returns true if this is a drop event, false otherwise. + */ bool IsDrop (void) const; void Print (std::ostream &os) const; static uint16_t GetUid (void); + std::string GetTypeName (void) const; private: enum Type m_type; }; -class Ipv4l3ProtocolInterfaceIndex : public TraceContextElement +/** + * \brief hold in a TraceContext the index of an Ipv4Interface within the ipv4 stack of a Node + */ +class Ipv4L3ProtocolInterfaceIndex : public TraceContextElement { public: - Ipv4l3ProtocolInterfaceIndex (); - Ipv4l3ProtocolInterfaceIndex (uint32_t index); + Ipv4L3ProtocolInterfaceIndex (); + Ipv4L3ProtocolInterfaceIndex (uint32_t index); + /** + * \returns the index of the Ipv4Interface within a Node. + */ uint32_t Get (void) const; void Print (std::ostream &os) const; static uint16_t GetUid (void); + std::string GetTypeName (void) const; private: uint32_t m_index; }; @@ -85,15 +105,6 @@ public: Ipv4L3Protocol(Ptr node); virtual ~Ipv4L3Protocol (); - /** - * \param context the trace context to use to construct the - * TraceResolver to return - * \returns a TraceResolver which can resolve all traces - * performed in this object. The caller must - * delete the returned object. - */ - virtual TraceResolver *CreateTraceResolver (TraceContext const &context); - /** * \param ttl default ttl to use * @@ -109,7 +120,7 @@ public: * Try to find an Ipv4Interface whose NetDevice is equal to * the input NetDevice. */ - Ipv4Interface *FindInterfaceForDevice (Ptr device); + Ptr FindInterfaceForDevice (Ptr device); /** * Lower layer calls this method after calling L3Demux::Lookup @@ -174,7 +185,7 @@ public: void RemoveMulticastRoute (uint32_t i); uint32_t AddInterface (Ptr device); - Ipv4Interface * GetInterface (uint32_t i) const; + Ptr GetInterface (uint32_t i) const; uint32_t GetNInterfaces (void) const; uint32_t FindInterfaceForAddr (Ipv4Address addr) const; @@ -200,6 +211,7 @@ public: protected: virtual void DoDispose (void); + virtual Ptr GetTraceResolver (void) const; private: void Lookup (uint32_t ifIndex, @@ -216,15 +228,13 @@ private: Ipv4Header &ipHeader, Ptr device); void ForwardUp (Packet p, Ipv4Header const&ip); - uint32_t AddIpv4Interface (Ipv4Interface *interface); + uint32_t AddIpv4Interface (Ptr interface); void SetupLoopback (void); - TraceResolver *InterfacesCreateTraceResolver (TraceContext const &context) const; - typedef std::list Ipv4InterfaceList; + typedef std::list > Ipv4InterfaceList; typedef std::list > Ipv4MulticastGroupList; - typedef std::list > > - Ipv4RoutingProtocolList; + typedef std::list< std::pair< int, Ptr > > Ipv4RoutingProtocolList; Ipv4InterfaceList m_interfaces; uint32_t m_nInterfaces; diff --git a/src/internet-node/ipv4-l4-demux.cc b/src/internet-node/ipv4-l4-demux.cc index 977b802ba..ae4a09e42 100644 --- a/src/internet-node/ipv4-l4-demux.cc +++ b/src/internet-node/ipv4-l4-demux.cc @@ -54,6 +54,11 @@ Ipv4L4ProtocolTraceContextElement::GetUid (void) static uint16_t uid = AllocateUid ("Ipv4L4ProtocolTraceContextElement"); return uid; } +std::string +Ipv4L4ProtocolTraceContextElement::GetTypeName (void) const +{ + return "ns3::Ipv4L4ProtocolTraceContextElement"; +} Ipv4L4Demux::Ipv4L4Demux (Ptr node) @@ -78,21 +83,19 @@ Ipv4L4Demux::DoDispose (void) Object::DoDispose (); } -TraceResolver * -Ipv4L4Demux::CreateTraceResolver (TraceContext const &context) +Ptr +Ipv4L4Demux::GetTraceResolver (void) const { - CompositeTraceResolver *resolver = new CompositeTraceResolver (context); + Ptr resolver = Create (); for (L4List_t::const_iterator i = m_protocols.begin(); i != m_protocols.end(); ++i) { Ptr protocol = *i; - std::string protValue; - std::ostringstream oss (protValue); - oss << (*i)->GetProtocolNumber (); + std::ostringstream oss; + oss << (unsigned int) (*i)->GetProtocolNumber (); Ipv4L4ProtocolTraceContextElement protocolNumber = (*i)->GetProtocolNumber (); - resolver->Add (protValue, - MakeCallback (&Ipv4L4Protocol::CreateTraceResolver, PeekPointer (protocol)), - protocolNumber); + resolver->AddComposite (oss.str (), protocol, protocolNumber); } + resolver->SetParentResolver (Object::GetTraceResolver ()); return resolver; } void diff --git a/src/internet-node/ipv4-l4-demux.h b/src/internet-node/ipv4-l4-demux.h index 7e7fba62e..6e1208c13 100644 --- a/src/internet-node/ipv4-l4-demux.h +++ b/src/internet-node/ipv4-l4-demux.h @@ -37,14 +37,21 @@ class Node; class TraceResolver; class TraceContext; +/** + * \brief hold in a TraceContext the protocol number of a L4 Protocol + */ class Ipv4L4ProtocolTraceContextElement : public TraceContextElement { public: Ipv4L4ProtocolTraceContextElement (); Ipv4L4ProtocolTraceContextElement (int protocolNumber); + /** + * \returns the protocol number as registered in the Ipv4L4Demux. + */ int Get (void) const; void Print (std::ostream &os) const; static uint16_t GetUid (void); + std::string GetTypeName (void) const; private: int m_protocolNumber; }; @@ -59,14 +66,6 @@ public: Ipv4L4Demux (Ptr node); virtual ~Ipv4L4Demux(); - /** - * \param context the trace context to use to construct the - * TraceResolver to return - * \returns a TraceResolver which can resolve all traces - * performed in this object. The caller must - * delete the returned object. - */ - TraceResolver *CreateTraceResolver (TraceContext const &context); /** * \param protocol a template for the protocol to add to this L4 Demux. * \returns the L4Protocol effectively added. @@ -95,8 +94,10 @@ public: * returned from the Ipv4L4Protocol::Insert method. */ void Remove (Ptr protocol); -private: +protected: + Ptr GetTraceResolver (void) const; virtual void DoDispose (void); +private: typedef std::list > L4List_t; L4List_t m_protocols; Ptr m_node; diff --git a/src/internet-node/ipv4-l4-protocol.h b/src/internet-node/ipv4-l4-protocol.h index f23aa510b..e54dfcc97 100644 --- a/src/internet-node/ipv4-l4-protocol.h +++ b/src/internet-node/ipv4-l4-protocol.h @@ -37,10 +37,6 @@ class TraceContext; /** * \brief L4 Protocol base class * - * All subclasses must implement: - * - Ipv4L4Protocol::Copy - * - Ipv4L4Protocol::CreateTraceResolver - * * If you want to implement a new L4 protocol, all you have to do is * implement a subclass of this base class and add it to an L4Demux. */ @@ -59,8 +55,6 @@ public: */ int GetVersion() const; - virtual TraceResolver *CreateTraceResolver (TraceContext const &context) = 0; - /** * \param p packet to forward up * \param source source address of packet received diff --git a/src/internet-node/ipv4-loopback-interface.cc b/src/internet-node/ipv4-loopback-interface.cc index 52fab7e5a..a4e8b6bfb 100644 --- a/src/internet-node/ipv4-loopback-interface.cc +++ b/src/internet-node/ipv4-loopback-interface.cc @@ -21,7 +21,6 @@ */ #include "ns3/debug.h" -#include "ns3/empty-trace-resolver.h" #include "ns3/net-device.h" #include "ns3/node.h" #include "ns3/eui48-address.h" @@ -44,13 +43,6 @@ Ipv4LoopbackInterface::~Ipv4LoopbackInterface () NS_DEBUG("Ipv4LoopbackInterface::~Ipv4LoopbackInterface ()"); } -TraceResolver * -Ipv4LoopbackInterface::DoCreateTraceResolver (TraceContext const &context) -{ - NS_DEBUG("Ipv4LoopbackInterface::DoCreateTraceResolver ()"); - return new EmptyTraceResolver (context); -} - void Ipv4LoopbackInterface::SendTo (Packet packet, Ipv4Address dest) { diff --git a/src/internet-node/ipv4-loopback-interface.h b/src/internet-node/ipv4-loopback-interface.h index 3eead3a01..8e33f81d7 100644 --- a/src/internet-node/ipv4-loopback-interface.h +++ b/src/internet-node/ipv4-loopback-interface.h @@ -43,7 +43,6 @@ class Ipv4LoopbackInterface : public Ipv4Interface private: virtual void SendTo (Packet p, Ipv4Address dest); - virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context); Ptr m_node; }; diff --git a/src/internet-node/pcap-trace.cc b/src/internet-node/pcap-trace.cc index 240100fb5..3378b52c5 100644 --- a/src/internet-node/pcap-trace.cc +++ b/src/internet-node/pcap-trace.cc @@ -22,7 +22,7 @@ #include -#include "ns3/trace-root.h" +#include "ns3/node-list.h" #include "ns3/trace-context.h" #include "ns3/callback.h" #include "ns3/pcap-writer.h" @@ -50,8 +50,8 @@ PcapTrace::~PcapTrace () void PcapTrace::TraceAllIp (void) { - TraceRoot::Connect ("/nodes/*/ipv4/(tx|rx)", - MakeCallback (&PcapTrace::LogIp, this)); + NodeList::Connect ("/nodes/*/ipv4/(tx|rx)", + MakeCallback (&PcapTrace::LogIp, this)); } PcapWriter * @@ -83,7 +83,7 @@ void PcapTrace::LogIp (TraceContext const &context, Packet const &p, uint32_t interfaceIndex) { NodeListIndex nodeIndex; - context.Get (nodeIndex); + context.GetElement (nodeIndex); PcapWriter *writer = GetStream (nodeIndex.Get (), interfaceIndex); writer->WritePacket (p); } diff --git a/src/internet-node/udp-l4-protocol.cc b/src/internet-node/udp-l4-protocol.cc index 2626866b8..adf462f05 100644 --- a/src/internet-node/udp-l4-protocol.cc +++ b/src/internet-node/udp-l4-protocol.cc @@ -22,7 +22,6 @@ #include "ns3/debug.h" #include "ns3/assert.h" #include "ns3/packet.h" -#include "ns3/empty-trace-resolver.h" #include "ns3/node.h" #include "udp-l4-protocol.h" @@ -52,13 +51,6 @@ UdpL4Protocol::~UdpL4Protocol () NS_DEBUG("UdpL4Protocol::~UdpL4Protocol ()"); } -TraceResolver * -UdpL4Protocol::CreateTraceResolver (TraceContext const &context) -{ - NS_DEBUG("UdpL4Protocol::CreateTraceResolver ()"); - return new EmptyTraceResolver (context); -} - void UdpL4Protocol::DoDispose (void) { diff --git a/src/internet-node/udp-l4-protocol.h b/src/internet-node/udp-l4-protocol.h index 4d7a082d4..46fe62761 100644 --- a/src/internet-node/udp-l4-protocol.h +++ b/src/internet-node/udp-l4-protocol.h @@ -49,7 +49,6 @@ public: UdpL4Protocol (Ptr node); virtual ~UdpL4Protocol (); - virtual TraceResolver *CreateTraceResolver (TraceContext const &context); /** * \return A smart Socket pointer to a UdpSocket, allocated by this instance * of the UDP protocol diff --git a/src/mobility/hierarchical-mobility-model.cc b/src/mobility/hierarchical-mobility-model.cc index 7e4aa3fe3..046f98056 100644 --- a/src/mobility/hierarchical-mobility-model.cc +++ b/src/mobility/hierarchical-mobility-model.cc @@ -41,8 +41,8 @@ HierarchicalMobilityModel::HierarchicalMobilityModel (Ptr child, parentNotifier = Create (); parent->AddInterface (parentNotifier); } - childNotifier->RegisterListener (MakeCallback (&HierarchicalMobilityModel::ChildChanged, this)); - parentNotifier->RegisterListener (MakeCallback (&HierarchicalMobilityModel::ParentChanged, this)); + childNotifier->TraceConnect ("/course-changed", MakeCallback (&HierarchicalMobilityModel::ChildChanged, this)); + parentNotifier->TraceConnect ("/course-changed", MakeCallback (&HierarchicalMobilityModel::ParentChanged, this)); } Ptr @@ -89,13 +89,13 @@ HierarchicalMobilityModel::DoGetSpeed (void) const } void -HierarchicalMobilityModel::ParentChanged (Ptr model) +HierarchicalMobilityModel::ParentChanged (const TraceContext &context, Ptr model) { MobilityModel::NotifyCourseChange (); } void -HierarchicalMobilityModel::ChildChanged (Ptr model) +HierarchicalMobilityModel::ChildChanged (const TraceContext &context, Ptr model) { MobilityModel::NotifyCourseChange (); } diff --git a/src/mobility/hierarchical-mobility-model.h b/src/mobility/hierarchical-mobility-model.h index 1502c516a..16be7820b 100644 --- a/src/mobility/hierarchical-mobility-model.h +++ b/src/mobility/hierarchical-mobility-model.h @@ -63,8 +63,8 @@ private: virtual void DoSet (const Position &position); virtual Speed DoGetSpeed (void) const; - void ParentChanged (Ptr model); - void ChildChanged (Ptr model); + void ParentChanged (const TraceContext &context, Ptr model); + void ChildChanged (const TraceContext &context, Ptr model); Ptr m_child; Ptr m_parent; diff --git a/src/mobility/mobility-model-notifier.cc b/src/mobility/mobility-model-notifier.cc index abb476c20..ebe64f3df 100644 --- a/src/mobility/mobility-model-notifier.cc +++ b/src/mobility/mobility-model-notifier.cc @@ -19,6 +19,8 @@ * Author: Mathieu Lacage */ #include "mobility-model-notifier.h" +#include "ns3/composite-trace-resolver.h" +#include "ns3/trace-doc.h" namespace ns3 { @@ -32,37 +34,24 @@ MobilityModelNotifier::MobilityModelNotifier () SetInterfaceId (MobilityModelNotifier::iid); } -void -MobilityModelNotifier::RegisterListener (Listener listener) -{ - m_listeners.push_back (listener); -} -void -MobilityModelNotifier::UnregisterListener (Listener callback) -{ - for (std::list::iterator i = m_listeners.begin (); - i != m_listeners.end ();) - { - Listener listener = *i; - if (listener.IsEqual (callback)) - { - i = m_listeners.erase (i); - } - else - { - i++; - } - } -} void MobilityModelNotifier::Notify (Ptr position) const { - for (std::list::const_iterator i = m_listeners.begin (); - i != m_listeners.end (); i++) - { - Listener listener = *i; - listener (position); - } + m_trace (position); +} + +Ptr +MobilityModelNotifier::GetTraceResolver (void) const +{ + Ptr resolver = + Create (); + resolver->AddSource ("course-change", + TraceDoc ("The value of the speed vector changed", + "Ptr", + "the mobility model whose course changed"), + m_trace); + resolver->SetParentResolver (Object::GetTraceResolver ()); + return resolver; } } // namespace ns3 diff --git a/src/mobility/mobility-model-notifier.h b/src/mobility/mobility-model-notifier.h index 8aec327de..1d2409f8e 100644 --- a/src/mobility/mobility-model-notifier.h +++ b/src/mobility/mobility-model-notifier.h @@ -24,6 +24,7 @@ #include "ns3/object.h" #include "ns3/component-manager.h" #include "ns3/callback.h" +#include "ns3/callback-trace-source.h" #include "mobility-model.h" namespace ns3 { @@ -37,8 +38,6 @@ public: static const InterfaceId iid; static const ClassId cid; - typedef Callback > Listener; - /** * Create a new position notifier */ @@ -48,23 +47,10 @@ public: * \param position the position which just changed. */ void Notify (Ptr position) const; - - /** - * \param listener listener to add - * - * The listener will be notified upon every position change. - */ - void RegisterListener (Listener listener); - /** - * \param listener listener to remove - * - * The listener will not be notified anymore upon every - * position change. It is not an error to try to unregister - * a non-registered liste - */ - void UnregisterListener (Listener listener); +protected: + virtual Ptr GetTraceResolver (void) const; private: - std::list m_listeners; + CallbackTraceSource > m_trace; }; } // namespace ns3 diff --git a/src/node/net-device.cc b/src/node/net-device.cc index 4e6710758..0e8223f60 100644 --- a/src/node/net-device.cc +++ b/src/node/net-device.cc @@ -23,6 +23,7 @@ #include "ns3/assert.h" #include "ns3/object.h" #include "ns3/debug.h" +#include "ns3/trace-resolver.h" #include "channel.h" @@ -201,12 +202,6 @@ NetDevice::Send(const Packet& p, const Address& dest, uint16_t protocolNumber) } } -TraceResolver * -NetDevice::CreateTraceResolver (TraceContext const &context) -{ - return DoCreateTraceResolver (context); -} - Ptr NetDevice::GetChannel (void) const { diff --git a/src/node/net-device.h b/src/node/net-device.h index dd622ae90..7c95d5b84 100644 --- a/src/node/net-device.h +++ b/src/node/net-device.h @@ -63,14 +63,6 @@ public: static const InterfaceId iid; virtual ~NetDevice(); - /** - * \param context the trace context to use to construct the - * TraceResolver to return - * \returns a TraceResolver which can resolve all traces - * performed in this object. The caller must - * delete the returned object. - */ - TraceResolver *CreateTraceResolver (TraceContext const &context); /** * \return the channel this NetDevice is connected to. The value @@ -343,15 +335,6 @@ public: * Subclasses must implement this method. */ virtual bool DoNeedsArp (void) const = 0; - /** - * \param context the trace context to associated to the - * trace resolver. - * \returns a trace resolver associated to the input context. - * the caller takes ownership of the pointer returned. - * - * Subclasses must implement this method. - */ - virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context) = 0; /** * \returns the channel associated to this NetDevice. * diff --git a/src/node/node-list.cc b/src/node/node-list.cc index eb43727d9..1accfa2be 100644 --- a/src/node/node-list.cc +++ b/src/node/node-list.cc @@ -20,24 +20,12 @@ * Mathieu Lacage , */ -#include "ns3/array-trace-resolver.h" -#include "ns3/trace-root.h" +#include "ns3/composite-trace-resolver.h" #include "ns3/simulator.h" #include "ns3/simulation-singleton.h" #include "node-list.h" #include "node.h" -namespace { -static class Initialization -{ -public: - Initialization () - { - ns3::TraceRoot::Register ("nodes", ns3::MakeCallback (&ns3::NodeList::CreateTraceResolver)); - } -} g_initialization; -} - namespace ns3 { NodeListIndex::NodeListIndex () @@ -62,6 +50,11 @@ NodeListIndex::Get (void) const { return m_index; } +std::string +NodeListIndex::GetTypeName (void) const +{ + return "ns3::NodeListIndex"; +} /** @@ -74,9 +67,9 @@ public: ~NodeListPriv (); uint32_t Add (Ptr node); - NodeList::Iterator Begin (void); - NodeList::Iterator End (void); - TraceResolver *CreateTraceResolver (TraceContext const &context); + NodeList::Iterator Begin (void) const; + NodeList::Iterator End (void) const; + Ptr GetTraceResolver (void) const; Ptr GetNode (uint32_t n); uint32_t GetNNodes (void); @@ -108,12 +101,12 @@ NodeListPriv::Add (Ptr node) } NodeList::Iterator -NodeListPriv::Begin (void) +NodeListPriv::Begin (void) const { return m_nodes.begin (); } NodeList::Iterator -NodeListPriv::End (void) +NodeListPriv::End (void) const { return m_nodes.end (); } @@ -130,14 +123,11 @@ NodeListPriv::GetNode (uint32_t n) } -TraceResolver * -NodeListPriv::CreateTraceResolver (TraceContext const &context) +Ptr +NodeListPriv::GetTraceResolver (void) const { - ArrayTraceResolver, NodeListIndex> *resolver = - new ArrayTraceResolver, NodeListIndex> - (context, - MakeCallback (&NodeListPriv::GetNNodes, this), - MakeCallback (&NodeListPriv::GetNode, this)); + Ptr resolver = Create (); + resolver->AddArray ("nodes", Begin (), End (), NodeListIndex ()); return resolver; } @@ -165,17 +155,30 @@ NodeList::End (void) { return SimulationSingleton::Get ()->End (); } -TraceResolver * -NodeList::CreateTraceResolver (TraceContext const &context) -{ - return SimulationSingleton::Get ()->CreateTraceResolver (context); -} Ptr NodeList::GetNode (uint32_t n) { return SimulationSingleton::Get ()->GetNode (n); } - - +void +NodeList::Connect (std::string name, const CallbackBase &cb) +{ + SimulationSingleton::Get ()->GetTraceResolver ()->Connect (name, cb, TraceContext ()); +} +void +NodeList::Disconnect (std::string name, const CallbackBase &cb) +{ + SimulationSingleton::Get ()->GetTraceResolver ()->Disconnect (name, cb); +} +void +NodeList::TraceAll (std::ostream &os) +{ + SimulationSingleton::Get ()->GetTraceResolver ()->TraceAll (os, TraceContext ()); +} +Ptr +NodeList::GetTraceResolver (void) +{ + return SimulationSingleton::Get ()->GetTraceResolver (); +} }//namespace ns3 diff --git a/src/node/node-list.h b/src/node/node-list.h index 1fdcd9e0e..ef3ee6348 100644 --- a/src/node/node-list.h +++ b/src/node/node-list.h @@ -29,9 +29,12 @@ namespace ns3 { class Node; +class CallbackBase; class TraceResolver; -class TraceContext; +/** + * \brief hold in a TraceContext the index of a node within a NodeList. + */ class NodeListIndex : public TraceContextElement { public: @@ -39,7 +42,11 @@ public: NodeListIndex (uint32_t index); void Print (std::ostream &os); static uint16_t GetUid (void); + /** + * \returns the index of the node within the NodeList + */ uint32_t Get (void) const; + std::string GetTypeName (void) const; private: uint32_t m_index; }; @@ -53,7 +60,7 @@ private: class NodeList { public: - typedef std::vector< Ptr >::iterator Iterator; + typedef std::vector< Ptr >::const_iterator Iterator; /** * \param node node to add @@ -73,19 +80,50 @@ public: * list. */ static Iterator End (void); - /** - * \param context trace context to use for trace resolver - * to create. - * \returns the requested trace resolver. The caller - * takes ownership of the returned pointer. - */ - static TraceResolver *CreateTraceResolver (TraceContext const &context); - /** * \param n index of requested node. * \returns the Node associated to index n. */ static Ptr GetNode (uint32_t n); + /** + * \param name namespace regexp to match + * \param cb callback to connect + * + * Connect input callback to all trace sources which match + * the input namespace regexp. + * A tutorial which explains how to use this method can be + * found in the \ref tracing section. + */ + static void Connect (std::string name, const CallbackBase &cb); + /** + * \param name namespace regexp to match + * \param cb callback to connect + * + * Disconnect input callback from all trace sources which match + * the input namespace regexp. + */ + static void Disconnect (std::string name, const CallbackBase &cb); + /** + * \param os the output stream on which the content of each trace event should be + * dumped in ascii format. + * + * Enable _every_ trace source accessible from the NodeList and write to the + * output stream an ascii representation of each trace event. + * This method is very useful to get quick-and-dirty trace output from a + * simulation. + * More fancy tracing output could be generated with the ns3::NodeList::Connect + * method as explained in the \ref tracing section. + */ + static void TraceAll (std::ostream &os); + /** + * \returns the trace resolver used by the ns3::NodeList::Connect, + * ns3::NodeList::Disconnect, and, ns3::NodeList::TraceAll methods. + * + * Using this method directly is not really recommended. Instead, users + * should use one of the three methods ns3::NodeList::Connect, + * ns3::NodeList::Disconnect, or, ns3::NodeList::TraceAll methods. + */ + static Ptr GetTraceResolver (void); }; }//namespace ns3 diff --git a/src/node/node.cc b/src/node/node.cc index ee83e8588..171af4e2d 100644 --- a/src/node/node.cc +++ b/src/node/node.cc @@ -25,7 +25,6 @@ #include "packet-socket-factory.h" #include "ns3/simulator.h" #include "ns3/composite-trace-resolver.h" -#include "ns3/array-trace-resolver.h" namespace ns3{ @@ -53,6 +52,11 @@ NodeNetDeviceIndex::GetUid (void) static uint16_t uid = AllocateUid ("NodeNetDeviceIndex"); return uid; } +std::string +NodeNetDeviceIndex::GetTypeName (void) const +{ + return "ns3::NodeNetDeviceIndex"; +} @@ -82,11 +86,12 @@ Node::Construct (void) Node::~Node () {} -TraceResolver * -Node::CreateTraceResolver (TraceContext const &context) +Ptr +Node::GetTraceResolver (void) const { - CompositeTraceResolver *resolver = new CompositeTraceResolver (context); - DoFillTraceResolver (*resolver); + Ptr resolver = Create (); + resolver->AddArray ("devices", m_devices.begin (), m_devices.end (), NodeNetDeviceIndex ()); + resolver->SetParentResolver (Object::GetTraceResolver ()); return resolver; } @@ -141,25 +146,6 @@ Node::GetNApplications (void) const return m_applications.size (); } -TraceResolver * -Node::CreateDevicesTraceResolver (const TraceContext &context) -{ - ArrayTraceResolver,NodeNetDeviceIndex> *resolver = - new ArrayTraceResolver,NodeNetDeviceIndex> - (context, - MakeCallback (&Node::GetNDevices, this), - MakeCallback (&Node::GetDevice, this)); - - return resolver; -} - -void -Node::DoFillTraceResolver (CompositeTraceResolver &resolver) -{ - resolver.Add ("devices", - MakeCallback (&Node::CreateDevicesTraceResolver, this)); -} - void Node::DoDispose() { diff --git a/src/node/node.h b/src/node/node.h index f4d898f53..cd032e2e0 100644 --- a/src/node/node.h +++ b/src/node/node.h @@ -37,13 +37,20 @@ class Packet; class Address; class CompositeTraceResolver; +/** + * \brief hold in a TraceContext the index of a NetDevice within a Node + */ class NodeNetDeviceIndex : public TraceContextElement { public: NodeNetDeviceIndex (); NodeNetDeviceIndex (uint32_t index); + /** + * \returns the index of the NetDevice within its container Node. + */ uint32_t Get (void) const; void Print (std::ostream &os) const; + std::string GetTypeName (void) const; static uint16_t GetUid (void); private: uint32_t m_index; @@ -84,17 +91,6 @@ public: virtual ~Node(); - /** - * \param context the trace context for the TraceResolver to create - * \returns a newly-created TraceResolver. The caller takes - * ownership of the returned pointer. - * - * Request the Node to create a trace resolver. This method - * could be used directly by a user who needs access to very low-level - * trace configuration. - */ - TraceResolver *CreateTraceResolver (TraceContext const &context); - /** * \returns the unique id of this node. * @@ -183,23 +179,15 @@ public: void UnregisterProtocolHandler (ProtocolHandler handler); protected: + virtual Ptr GetTraceResolver (void) const; /** * The dispose method. Subclasses must override this method * and must chain up to it by calling Node::DoDispose at the * end of their own DoDispose method. */ virtual void DoDispose (void); - /** - * \param resolver the resolver to store trace sources in. - * - * If a subclass wants to add new traces to a Node, it needs - * to override this method and record the new trace sources - * in the input resolver. Subclasses also _must_ chain up to - * their parent's DoFillTraceResolver method prior - * to recording they own trace sources. - */ - virtual void DoFillTraceResolver (CompositeTraceResolver &resolver); private: + /** * \param device the device added to this Node. * @@ -213,7 +201,6 @@ private: bool ReceiveFromDevice (Ptr device, const Packet &packet, uint16_t protocol, const Address &from); void Construct (void); - TraceResolver *CreateDevicesTraceResolver (const TraceContext &context); struct ProtocolHandlerEntry { ProtocolHandler handler; diff --git a/src/node/queue.cc b/src/node/queue.cc index 72eafed69..8ed033b66 100644 --- a/src/node/queue.cc +++ b/src/node/queue.cc @@ -32,6 +32,11 @@ static ClassIdDefaultValue g_classIdDefaultValue ("Queue", "Packet Queue", Queue::iid, "DropTailQueue"); +std::string +QueueTraceType::GetTypeName (void) const +{ + return "ns3::QueueTraceType"; +} uint16_t QueueTraceType::GetUid (void) { @@ -94,13 +99,23 @@ Queue::~Queue() NS_DEBUG("Queue::~Queue ()"); } -TraceResolver * -Queue::CreateTraceResolver (TraceContext const &context) +Ptr +Queue::GetTraceResolver (void) const { - CompositeTraceResolver *resolver = new CompositeTraceResolver (context); - resolver->Add ("enqueue", m_traceEnqueue, QueueTraceType (QueueTraceType::ENQUEUE)); - resolver->Add ("dequeue", m_traceDequeue, QueueTraceType (QueueTraceType::DEQUEUE)); - resolver->Add ("drop", m_traceDrop, QueueTraceType (QueueTraceType::DROP)); + Ptr resolver = Create (); + resolver->AddSource ("enqueue", + TraceDoc ("store packet in queue", + "const Packet &", "packet queued"), + m_traceEnqueue, QueueTraceType (QueueTraceType::ENQUEUE)); + resolver->AddSource ("dequeue", + TraceDoc ("remove packet from queue", + "const Packet &", "packet dequeued"), + m_traceDequeue, QueueTraceType (QueueTraceType::DEQUEUE)); + resolver->AddSource ("drop", + TraceDoc ("drop packet from queue", + "const Packet &", "packet dropped"), + m_traceDrop, QueueTraceType (QueueTraceType::DROP)); + resolver->SetParentResolver (Object::GetTraceResolver ()); return resolver; } diff --git a/src/node/queue.h b/src/node/queue.h index d135fff68..b8531c9c7 100644 --- a/src/node/queue.h +++ b/src/node/queue.h @@ -37,6 +37,9 @@ namespace ns3 { class StringEnumDefaultValue; +/** + * \brief hold in a TraceContext the type of a trace source + */ class QueueTraceType : public TraceContextElement { public: @@ -48,10 +51,20 @@ public: static uint16_t GetUid (void); QueueTraceType (); QueueTraceType (enum Type type); + /** + * \returns true if this is an enqueue event, false otherwise. + */ bool IsEnqueue (void) const; + /** + * \returns true if this is a dequeue event, false otherwise. + */ bool IsDequeue (void) const; + /** + * \returns true if this is a drop event, false otherwise. + */ bool IsDrop (void) const; void Print (std::ostream &os) const; + std::string GetTypeName (void) const; private: enum Type m_type; }; @@ -69,8 +82,6 @@ public: Queue (); virtual ~Queue (); - - TraceResolver *CreateTraceResolver (TraceContext const &context); /** * \return true if the queue is empty; false otherwise @@ -167,6 +178,7 @@ private: virtual bool DoPeek (Packet &p) = 0; protected: + Ptr GetTraceResolver (void) const; // called by subclasses to notify parent of packet drops. void Drop (const Packet& p); diff --git a/src/routing/global-routing/global-route-manager-impl.cc b/src/routing/global-routing/global-route-manager-impl.cc index c2b7021c9..10f07ca85 100644 --- a/src/routing/global-routing/global-route-manager-impl.cc +++ b/src/routing/global-routing/global-route-manager-impl.cc @@ -1407,27 +1407,6 @@ GlobalRouteManagerImpl::SPFVertexAddParent (SPFVertex* v) namespace ns3 { -class GlobalRouterTestNode : public Node -{ -public: - GlobalRouterTestNode (); - -private: - virtual void DoAddDevice (Ptr device) const {}; - virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context); -}; - -GlobalRouterTestNode::GlobalRouterTestNode () -{ -// Ptr ipv4 = Create (this); -} - - TraceResolver* -GlobalRouterTestNode::DoCreateTraceResolver (TraceContext const &context) -{ - return 0; -} - class GlobalRouteManagerImplTest : public Test { public: GlobalRouteManagerImplTest (); diff --git a/utils/bench-packets.cc b/utils/bench-packets.cc index a6986d272..e16c17b02 100644 --- a/utils/bench-packets.cc +++ b/utils/bench-packets.cc @@ -32,12 +32,15 @@ class BenchHeader : public Header public: BenchHeader (); bool IsOk (void) const; + + static uint32_t GetUid (void); + + static std::string GetName (void); + void Print (std::ostream &os) const; + uint32_t GetSerializedSize (void) const; + void Serialize (Buffer::Iterator start) const; + uint32_t Deserialize (Buffer::Iterator start); private: - virtual std::string DoGetName (void) const; - virtual void PrintTo (std::ostream &os) const; - virtual uint32_t GetSerializedSize (void) const; - virtual void SerializeTo (Buffer::Iterator start) const; - virtual uint32_t DeserializeFrom (Buffer::Iterator start); bool m_ok; }; @@ -53,18 +56,26 @@ BenchHeader::IsOk (void) const return m_ok; } +template +uint32_t +BenchHeader::GetUid (void) +{ + static uint32_t uid = AllocateUid > (GetName ()); + return uid; +} + template std::string -BenchHeader::DoGetName (void) const +BenchHeader::GetName (void) { std::ostringstream oss; - oss << N; + oss << "BenchHeader" << N; return oss.str (); } template void -BenchHeader::PrintTo (std::ostream &os) const +BenchHeader::Print (std::ostream &os) const { NS_ASSERT (false); } @@ -76,13 +87,13 @@ BenchHeader::GetSerializedSize (void) const } template void -BenchHeader::SerializeTo (Buffer::Iterator start) const +BenchHeader::Serialize (Buffer::Iterator start) const { start.WriteU8 (N, N); } template uint32_t -BenchHeader::DeserializeFrom (Buffer::Iterator start) +BenchHeader::Deserialize (Buffer::Iterator start) { m_ok = true; for (int i = 0; i < N; i++) @@ -156,6 +167,7 @@ benchPtrC (uint32_t n) } } +#if 0 static void benchPrint (uint32_t n) { @@ -171,6 +183,7 @@ benchPrint (uint32_t n) p.Print (std::cerr, printer); } } +#endif static void @@ -205,7 +218,7 @@ int main (int argc, char *argv[]) runBench (&benchPtrC, n, "c"); Packet::EnableMetadata (); - runBench (&benchPrint, n, "print"); + //runBench (&benchPrint, n, "print"); PacketMetadata::SetOptOne (false); runBench (&benchPtrA, n, "meta-a"); runBench (&benchPtrB, n, "meta-b"); diff --git a/utils/print-trace-sources.cc b/utils/print-trace-sources.cc new file mode 100644 index 000000000..af7cfb755 --- /dev/null +++ b/utils/print-trace-sources.cc @@ -0,0 +1,100 @@ +#include "ns3/internet-node.h" +#include "ns3/ptr.h" +#include "ns3/trace-resolver.h" +#include "ns3/node-list.h" +#include "ns3/point-to-point-net-device.h" +#include "ns3/csma-net-device.h" +#include "ns3/queue.h" +#include "ns3/mobility-model-notifier.h" + +using namespace ns3; + +void +PrintSimpleText (const TraceResolver::SourceCollection *sources, std::ostream &os) +{ + for (TraceResolver::SourceCollection::Iterator i = sources->Begin (); i != sources->End (); i++) + { + os << "source=" << i->path << std::endl; + os << "TraceContext=["; + i->context.PrintAvailable (os, ","); + os << "]" << std::endl; + os << "help=\"" << i->doc.GetHelp () << "\"" << std::endl; + os << "void TraceSinkCallback (const TraceContext &"; + for (TraceDoc::Iterator k = i->doc.ArgsBegin (); k != i->doc.ArgsEnd (); k++) + { + os << ", " << k->first; + } + os << ")" << std::endl; + os << "argument 1 -- the trace context associated to the connected trace source." << std::endl; + uint32_t k = 2; + for (TraceDoc::Iterator j = i->doc.ArgsBegin (); j != i->doc.ArgsEnd (); j++) + { + os << "argument " << k << " -- " << j->second << "." << std::endl; + k++; + } + os << std::endl; + } +} +void +PrintDoxygenText (const TraceResolver::SourceCollection *sources, std::ostream &os) +{ + uint32_t z = 0; + for (TraceResolver::SourceCollection::Iterator i = sources->Begin (); i != sources->End (); i++) + { + os << "///" << std::endl; + os << "/// \\ingroup TraceSourceList" << std::endl; + os << "/// \\brief " << i->doc.GetHelp () << std::endl; + os << "/// \\param arg1 the trace context associated to the connected trace source." << std::endl; + uint32_t j = 2; + for (TraceDoc::Iterator l = i->doc.ArgsBegin (); l != i->doc.ArgsEnd (); l++) + { + os << "/// \\param arg" << j << " " << l->second << "." << std::endl; + j++; + } + os << "///" << std::endl; + os << "///" << std::endl; + os << "/// The path to this trace source is: " << i->path << "." << std::endl; + os << "///" << std::endl; + if (i->context.Begin ().IsLast ()) + { + os << "/// No data can be extracted from \\p arg1 with ns3::TraceContext::GetElement." << std::endl; + } + else + { + os << "/// The following classes can be extracted from \\p arg1 with " << std::endl; + os << "/// ns3::TraceContext::GetElement:" << std::endl; + for (TraceContext::Iterator m = i->context.Begin (); !m.IsLast (); m.Next ()) + { + os << "/// - " << m.Get () << std::endl; + } + } + os << "void TraceSinkCallback" << z << " (const TraceContext & arg1" ; + j = 2; + for (TraceDoc::Iterator k = i->doc.ArgsBegin (); k != i->doc.ArgsEnd (); k++) + { + os << ", " << k->first << " arg" << j; + j++; + } + os << ");" << std::endl; + os << std::endl; + z++; + } +} + + +int main (int argc, char *argv[]) +{ + Ptr node = Create (); + node->AddInterface (Create ()); + + Ptr p2p = Create (node); + p2p->AddQueue (Queue::CreateDefault ()); + Ptr csma = Create (node); + csma->AddQueue (Queue::CreateDefault ()); + + TraceResolver::SourceCollection collection; + NodeList::GetTraceResolver ()->CollectSources ("", TraceContext (), &collection); + PrintDoxygenText (&collection, std::cout); + + return 0; +} diff --git a/utils/wscript b/utils/wscript index d64d46dc5..15fbfa512 100644 --- a/utils/wscript +++ b/utils/wscript @@ -14,5 +14,12 @@ def build(bld): obj = bld.create_ns3_program('bench-simulator', ['simulator']) obj.source = 'bench-simulator.cc' + obj = bld.create_ns3_program('bench-packets', ['common']) + obj.source = 'bench-packets.cc' + obj = bld.create_ns3_program('replay-simulation', ['simulator']) obj.source = 'replay-simulation.cc' + + obj = bld.create_ns3_program('print-trace-sources', + ['internet-node', 'csma-cd', 'point-to-point']) + obj.source = 'print-trace-sources.cc' diff --git a/wscript b/wscript index c72b75e1e..5904c5ad2 100644 --- a/wscript +++ b/wscript @@ -37,7 +37,7 @@ def set_options(opt): opt.add_option('-d', '--debug-level', action='callback', - type="string", dest='debug_level', default='debug', + type="string", dest='debug_level', default='ultradebug', help=('Specify the debug level, does nothing if CFLAGS is set' ' in the environment. [Allowed Values: debug, optimized].' ' WARNING: this option only has effect ' @@ -114,7 +114,7 @@ def configure(conf): if (os.path.basename(conf.env['CXX']).startswith("g++") and 'CXXFLAGS' not in os.environ): - variant_env.append_value('CXXFLAGS', ['-Wall', '-Werror']) + variant_env.append_value('CXXFLAGS', ['-Werror']) if 'debug' in Params.g_options.debug_level.lower(): variant_env.append_value('CXXDEFINES', 'NS3_DEBUG_ENABLE') @@ -129,6 +129,13 @@ def configure(conf): if flag.startswith('-g'): variant_env.append_value('CXXFLAGS', flag) + ## in optimized builds, replace -O2 with -O3 + if 'optimized' in Params.g_options.debug_level.lower(): + lst = variant_env['CXXFLAGS'] + for i, flag in enumerate(lst): + if flag == '-O2': + lst[i] = '-O3' + if sys.platform == 'win32': if os.path.basename(conf.env['CXX']).startswith("g++"): variant_env.append_value("LINKFLAGS", "-Wl,--enable-runtime-pseudo-reloc")