diff --git a/README.multicast-routing b/README.multicast-routing index a5afda564..2fe30532e 100644 --- a/README.multicast-routing +++ b/README.multicast-routing @@ -6,7 +6,7 @@ routing to ns-3. This extension allows the simulation user to: -- manually add an Ipv4 multicast route to a router +- manually add Ipv4 multicast routes 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 @@ -29,7 +29,7 @@ also touched are: virtual methods. - src/internet-node/ (several files have added tracing) -- an example script is in examples/csma-multicast.cc +- a heavily commented example script is in examples/csma-multicast.cc 2. API: @@ -114,9 +114,31 @@ To remove a route, one uses: * @see Ipv4MulticastRoute * @see Ipv4StaticRouting::AddMulticastRoute */ - Ipv4::RemoveMulticastRoute (Ipv4Address origin, Ipv4Address group, + Ipv4::RemoveMulticastRoute (Ipv4Address origin, + Ipv4Address group, uint32_t inputInterface) +For symmetry with the unicast routing interface, a method is provided to +remove routes by index: + +/** + * @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); + For compatibility, and to provide simplicity, one can set a default multicast route for a host originating data: diff --git a/changeset.txt b/changeset.txt new file mode 100644 index 000000000..837107a48 --- /dev/null +++ b/changeset.txt @@ -0,0 +1,12278 @@ +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. +