diff --git a/.hgtags b/.hgtags index aac74dfcf..68f54ead8 100644 --- a/.hgtags +++ b/.hgtags @@ -4,3 +4,4 @@ 38099dd26e9467b8f49f8632f22789858149a6e7 release ns-3.0.3 5701e60bf01a8ac1308945e69001e0cc07948faf release ns-3.0.4 08046b6aef37932507696a2f2f427b42d693781e release ns-3.0.5 +267e2ebc28e4e4ae2f579e1cfc29902acade0c34 buffer-working-before-breaking diff --git a/README.multicast-routing b/README.multicast-routing new file mode 100644 index 000000000..2fe30532e --- /dev/null +++ b/README.multicast-routing @@ -0,0 +1,235 @@ +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 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 + 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) + +- a heavily commented 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 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: + +/** + * @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 --git a/examples/csma-broadcast.cc b/examples/csma-broadcast.cc index 1cb9faa75..b032f0aea 100644 --- a/examples/csma-broadcast.cc +++ b/examples/csma-broadcast.cc @@ -66,13 +66,24 @@ 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"); +#if 0 + DebugComponentEnable("Object"); + DebugComponentEnable("Queue"); + DebugComponentEnable("DropTailQueue"); DebugComponentEnable("Channel"); DebugComponentEnable("CsmaChannel"); + DebugComponentEnable("NetDevice"); + DebugComponentEnable("CsmaNetDevice"); + DebugComponentEnable("Ipv4L3Protocol"); + DebugComponentEnable("OnOffApplication"); DebugComponentEnable("PacketSocket"); + DebugComponentEnable("UdpSocket"); + DebugComponentEnable("UdpL4Protocol"); + DebugComponentEnable("Ipv4L3Protocol"); + DebugComponentEnable("Ipv4StaticRouting"); + DebugComponentEnable("Ipv4Interface"); + DebugComponentEnable("ArpIpv4Interface"); + DebugComponentEnable("Ipv4LoopbackInterface"); #endif // Set up some default values for the simulation. Use the Bind() @@ -103,13 +114,13 @@ int main (int argc, char *argv[]) CsmaTopology::CreateCsmaChannel( DataRate(5000000), MilliSeconds(2)); - uint32_t n0ifIndex0 = CsmaIpv4Topology::AddIpv4CsmaNode (n0, channel0, + uint32_t n0ifIndex0 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n0, channel0, Eui48Address("10:54:23:54:0:50")); - uint32_t n0ifIndex1 = CsmaIpv4Topology::AddIpv4CsmaNode (n0, channel1, + uint32_t n0ifIndex1 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n0, channel1, Eui48Address("10:54:23:54:0:51")); - uint32_t n1ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n1, channel0, + uint32_t n1ifIndex = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n1, channel0, Eui48Address("10:54:23:54:23:51")); - uint32_t n2ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n2, channel1, + uint32_t n2ifIndex = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n2, channel1, Eui48Address("10:54:23:54:23:52")); // Later, we add IP addresses. @@ -125,6 +136,18 @@ int main (int argc, char *argv[]) CsmaIpv4Topology::AddIpv4Address ( n2, n2ifIndex, Ipv4Address("192.168.1.2"), Ipv4Mask("255.255.255.0")); + // XXX Is this the right thing to do? + // + // The OnOff application uses a connected socket. This socket needs to be + // able to figure out which interface to use as the source address for + // packets. When there's one interface, this isn't too hard, but node zero + // has two interfaces, and limited broadcasts will be sent out both of those + // interfaces. We need to provide some way to disambiguate the choice. + // If we supply a default route, the specified interface will be chosen. + + Ptr ipv4 = n0->QueryInterface (Ipv4::iid); + ipv4->SetDefaultRoute ("192.168.1.3", n0ifIndex0); + // Create the OnOff application to send UDP datagrams of size // 210 bytes at a rate of 448 Kb/s // from n0 to n1 diff --git a/examples/csma-multicast.cc b/examples/csma-multicast.cc new file mode 100644 index 000000000..6bae090ff --- /dev/null +++ b/examples/csma-multicast.cc @@ -0,0 +1,312 @@ +/* -*- 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 +// +// 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" +#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; + +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 +// +#if 0 + DebugComponentEnable("CsmaMulticast"); + + DebugComponentEnable("Object"); + DebugComponentEnable("Queue"); + DebugComponentEnable("DropTailQueue"); + DebugComponentEnable("Channel"); + DebugComponentEnable("CsmaChannel"); + DebugComponentEnable("NetDevice"); + DebugComponentEnable("CsmaNetDevice"); + DebugComponentEnable("Ipv4L3Protocol"); + DebugComponentEnable("OnOffApplication"); + DebugComponentEnable("PacketSocket"); + DebugComponentEnable("UdpSocket"); + DebugComponentEnable("UdpL4Protocol"); + DebugComponentEnable("Ipv4L3Protocol"); + DebugComponentEnable("Ipv4StaticRouting"); + DebugComponentEnable("Ipv4Interface"); + 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 +// 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() at +// run-time, via command-line arguments +// + CommandLine::Parse (argc, argv); +// +// 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."); +// +// 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."); +// +// 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:03")); + uint32_t nd3 __attribute__ ((unused)) = + CsmaIpv4Topology::AddIpv4CsmaNetDevice (n3, lan1, + Eui48Address("08:00:2e:00:00:04")); + uint32_t nd4 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n4, lan1, + Eui48Address("08:00:2e:00:00:05")); + + 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."); + + 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 +// + 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."); +// +// 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 (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.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 +// 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] = ifIndexLan1; + + 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 +// 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, + InetSocketAddress (multicastGroup, 80), + "Udp", + ConstantVariable(1), + ConstantVariable(0), + DataRate ("255b/s"), + 128); +// +// 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 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: +// 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 (); + NS_DEBUG("Done."); +} diff --git a/examples/csma-one-subnet.cc b/examples/csma-one-subnet.cc index dc1bd58c0..19d9200ff 100644 --- a/examples/csma-one-subnet.cc +++ b/examples/csma-one-subnet.cc @@ -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 // | | | | -// ===================== +// ================= +// LAN // -// - 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) +// - 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" @@ -58,109 +48,168 @@ #include "ns3/ipv4-route.h" #include "ns3/onoff-application.h" - using namespace ns3; +NS_DEBUG_COMPONENT_DEFINE ("CsmaOneSubnet"); -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 +// +// Users may find it convenient to turn on explicit debugging +// for selected modules; the below lines suggest how to do this +// #if 0 + DebugComponentEnable("CsmaOneSubnet"); + + DebugComponentEnable("Object"); + DebugComponentEnable("Queue"); + DebugComponentEnable("DropTailQueue"); + DebugComponentEnable("Channel"); + DebugComponentEnable("CsmaChannel"); DebugComponentEnable("CsmaNetDevice"); DebugComponentEnable("Ipv4L3Protocol"); DebugComponentEnable("NetDevice"); - DebugComponentEnable("Channel"); - DebugComponentEnable("CsmaChannel"); DebugComponentEnable("PacketSocket"); + DebugComponentEnable("OnOffApplication"); + DebugComponentEnable("UdpSocket"); + DebugComponentEnable("UdpL4Protocol"); + DebugComponentEnable("Ipv4L3Protocol"); + DebugComponentEnable("Ipv4StaticRouting"); + DebugComponentEnable("Ipv4Interface"); + DebugComponentEnable("ArpIpv4Interface"); + DebugComponentEnable("Ipv4LoopbackInterface"); #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 +// +// 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 - Ptr channel0 = - CsmaTopology::CreateCsmaChannel( - DataRate(5000000), MilliSeconds(2)); + NS_DEBUG("Create channels."); +// +// Explicitly create the channels required by the topology (shown above). +// + Ptr lan = 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")); + NS_DEBUG("Build Topology."); +// +// 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")); - // Later, we add IP addresses. - CsmaIpv4Topology::AddIpv4Address ( - n0, n0ifIndex, Ipv4Address("10.1.1.1"), Ipv4Mask("255.255.255.0")); + uint32_t nd1 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n1, lan, + Eui48Address("08:00:2e:00:00:01")); - CsmaIpv4Topology::AddIpv4Address ( - n1, n1ifIndex, Ipv4Address("10.1.1.2"), Ipv4Mask("255.255.255.0")); + uint32_t nd2 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n2, lan, + Eui48Address("08:00:2e:00:00:02")); - CsmaIpv4Topology::AddIpv4Address ( - n2, n2ifIndex, Ipv4Address("10.1.1.3"), Ipv4Mask("255.255.255.0")); + 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."); +// +// 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, InetSocketAddress ("10.1.1.2", 80), "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 +// +// 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 (); + NS_DEBUG("Done."); } diff --git a/examples/mixed-global-routing.cc b/examples/mixed-global-routing.cc index b3017e029..07dcdcaad 100644 --- a/examples/mixed-global-routing.cc +++ b/examples/mixed-global-routing.cc @@ -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 --git a/examples/simple-global-routing.cc b/examples/simple-global-routing.cc index 882e94e53..bcfc01d17 100644 --- a/examples/simple-global-routing.cc +++ b/examples/simple-global-routing.cc @@ -157,8 +157,7 @@ int main (int argc, char *argv[]) Ptr sink = Create ( n3, InetSocketAddress (Ipv4Address::GetAny (), 80), - "Udp", - true); + "Udp"); // Start the sink sink->Start (Seconds (1.0)); sink->Stop (Seconds (10.0)); @@ -178,8 +177,7 @@ int main (int argc, char *argv[]) sink = Create ( n1, InetSocketAddress (Ipv4Address::GetAny (), 80), - "Udp", - true); + "Udp"); // Start the sink sink->Start (Seconds (1.1)); sink->Stop (Seconds (10.0)); diff --git a/examples/simple-point-to-point.cc b/examples/simple-point-to-point.cc index 4e92ad460..4b9de40f4 100644 --- a/examples/simple-point-to-point.cc +++ b/examples/simple-point-to-point.cc @@ -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" @@ -68,19 +64,34 @@ 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 // remember to add #include "ns3/debug.h" before enabling these #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 // Set up some default values for the simulation. Use the Bind() @@ -102,12 +113,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)); @@ -121,6 +134,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")); @@ -137,13 +151,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), @@ -182,10 +197,10 @@ int main (int argc, char *argv[]) // Start the sink sink->Start (Seconds (1.1)); sink->Stop (Seconds (10.0)); - sink->SetQuiet (); // disable output from the Receive callback // 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); @@ -194,6 +209,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 (); @@ -206,7 +222,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 --git a/examples/wscript b/examples/wscript index 469010d25..5ba212468 100644 --- a/examples/wscript +++ b/examples/wscript @@ -22,6 +22,10 @@ def build(bld): ['csma', 'internet-node']) obj.source = 'csma-packet-socket.cc' + obj = bld.create_ns3_program('csma-multicast', + ['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 --git a/src/applications/onoff-application.cc b/src/applications/onoff-application.cc index 32bcd7564..9df4274bc 100644 --- a/src/applications/onoff-application.cc +++ b/src/applications/onoff-application.cc @@ -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() // Called at time specified by Star 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,23 +179,32 @@ void OnOffApplication::StopApplication() // Called at time specified by Stop // 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; + 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 @@ -192,12 +214,18 @@ 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()); + NS_DEBUG("OnOffApplication::ScheduleStartEvent (): " + "start at " << offInterval); 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 +233,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 +245,8 @@ void OnOffApplication::SendPacket() void OnOffApplication::ConnectionSucceeded(Ptr) { + NS_DEBUG("OnOffApplication::ConnectionSucceeded ()"); + m_connected = true; ScheduleStartEvent(); } diff --git a/src/applications/packet-sink.cc b/src/applications/packet-sink.cc index 2f767303e..2ca60bfb3 100644 --- a/src/applications/packet-sink.cc +++ b/src/applications/packet-sink.cc @@ -1,20 +1,22 @@ -/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ -// -// Copyright (c) 2006 Georgia Tech Research Corporation -// -// 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 -// +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright 2007 University of Washington + * + * 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: Tom Henderson (tomhend@u.washington.edu) + */ #include "ns3/address.h" #include "ns3/debug.h" #include "ns3/inet-socket-address.h" @@ -35,34 +37,25 @@ NS_DEBUG_COMPONENT_DEFINE ("PacketSink"); PacketSink::PacketSink (Ptr n, const Address &local, - std::string iid, - bool quiet) + std::string iid) : Application(n) { - Construct (n, local, iid, quiet); + Construct (n, local, iid); } void PacketSink::Construct (Ptr n, const Address &local, - std::string iid, - bool quiet) + std::string iid) { m_socket = 0; m_local = local; m_iid = iid; - m_quiet = quiet; } PacketSink::~PacketSink() {} -void -PacketSink::SetQuiet() -{ - m_quiet = true; -} - void PacketSink::DoDispose (void) { @@ -99,19 +92,17 @@ void PacketSink::StopApplication() // Called at time specified by Stop } } -// This callback body suggested by Joe Kopena's wiki +// This LOG output inspired by the application on Joseph Kopena's wiki void PacketSink::Receive(Ptr socket, const Packet &packet, const Address &from) { - if (!m_quiet) + if (InetSocketAddress::IsMatchingType (from)) { - if (InetSocketAddress::IsMatchingType (from)) - { - InetSocketAddress address = InetSocketAddress::ConvertFrom (from); - NS_DEBUG ( __PRETTY_FUNCTION__ << ": Received " << - packet.GetSize() << " bytes from " << address.GetIpv4() << " [" - << address << "]---'" << packet.PeekData() << "'"); - } + InetSocketAddress address = InetSocketAddress::ConvertFrom (from); + NS_DEBUG ( __PRETTY_FUNCTION__ << ": Received " << + packet.GetSize() << " bytes from " << address.GetIpv4() << " [" + << address << "]---'" << packet.PeekData() << "'"); + // TODO: Add a tracing source here } } diff --git a/src/applications/packet-sink.h b/src/applications/packet-sink.h index dc3c7d41e..8af7b3ab5 100644 --- a/src/applications/packet-sink.h +++ b/src/applications/packet-sink.h @@ -1,21 +1,22 @@ -/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ -// -// Copyright (c) 2006 Georgia Tech Research Corporation -// -// 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 -// -// +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright 2007 University of Washington + * + * 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: Tom Henderson (tomhend@u.washington.edu) + */ #ifndef __packet_sink_h__ #define __packet_sink_h__ @@ -33,34 +34,34 @@ class Packet; /** * \brief Receive and consume traffic generated to an IP address and port * - * This Application can be used as a receiver for packets generated by - * traffic sourcing applications such as OnOffApplication. The constructor - * specifies the Address (IP address and port) and the transport protocol - * to use. A virtual Receive () method is installed as a callback on - * the receiving socket. By default, it prints out the size of packets - * and their address. + * This application was written to complement OnOffApplication, but it + * is more general so a PacketSink name was selected. Functionally it is + * important to use in multicast situations, so that reception of the layer-2 + * multicast frames of interest are enabled, but it is also useful for + * unicast as an example of how you can write something simple to receive + * packets at the application layer. Also, if an IP stack generates + * ICMP Port Unreachable errors, receiving applications will be needed. + * + * The constructor specifies the Address (IP address and port) and the + * transport protocol to use. A virtual Receive () method is installed + * as a callback on the receiving socket. By default, when logging is + * enabled, it prints out the size of packets and their address, but + * we intend to also add a tracing source to Receive() at a later date. */ class PacketSink : public Application { public: /** * \param n node associated to this application - * \param local local ip address - * \param iid - * \param ontime on time random variable - * \param offtime off time random variable + * \param local local address to bind to + * \param iid string to identify transport protocol of interest */ PacketSink (Ptr n, const Address &local, - std::string iid, bool quiet=false); + std::string iid); virtual ~PacketSink (); - /** - * \brief Turn off the logging output for the receive callback - */ - void SetQuiet (void); - protected: virtual void DoDispose (void); private: @@ -70,15 +71,13 @@ private: void Construct (Ptr n, const Address &local, - std::string iid, - bool quiet); + std::string iid); virtual void Receive (Ptr socket, const Packet& packet, const Address& from); Ptr m_socket; // Associated socket Address m_local; // Local address to bind to std::string m_iid; // Protocol name (e.g., "Udp") - bool m_quiet; // Governs whether receive callback is quiet }; diff --git a/src/common/buffer.cc b/src/common/buffer.cc index 196bb4889..06af758ce 100644 --- a/src/common/buffer.cc +++ b/src/common/buffer.cc @@ -1,7 +1,6 @@ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* - * Copyright (c) 2005,2006 INRIA - * All rights reserved. + * Copyright (c) 2005,2006,2007 INRIA * * 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 @@ -20,385 +19,534 @@ */ #include "buffer.h" #include "ns3/assert.h" - +#include "ns3/debug.h" #include -//#define TRACE(x) std::cout << x << std::endl; -#define TRACE(x) + +NS_DEBUG_COMPONENT_DEFINE ("Buffer"); + +#define DEBUG_INTERNAL_STATE(y) \ +NS_DEBUG (y << "start="< { +public: + ~BufferDataList (); +}; + +static struct BufferData *BufferAllocate (uint32_t reqSize); + +static void BufferDeallocate (struct BufferData *data); + + +} // namespace ns3 + +namespace ns3 { + +#ifdef BUFFER_HEURISTICS +static uint32_t g_recommendedStart = 0; +static uint64_t g_nAddNoRealloc = 0; +static uint64_t g_nAddRealloc = 0; +static BufferDataList g_freeList; +static uint32_t g_maxSize = 0; +static uint64_t g_nAllocs = 0; +static uint64_t g_nCreates = 0; +#endif /* BUFFER_HEURISTICS */ + +BufferDataList::~BufferDataList () +{ +#ifdef PRINT_STATS +#ifdef BUFFER_HEURISTICS + double efficiency; + efficiency = g_nAllocs; + efficiency /= g_nCreates; + std::cout <<"buffer free list efficiency="<= m_data->m_dirtyStart && + m_end <= m_data->m_dirtyEnd; + bool internalSizeOk = m_end - (m_zeroAreaEnd - m_zeroAreaStart) <= m_data->m_size && + m_start <= m_data->m_size && + m_zeroAreaStart <= m_data->m_size; -namespace ns3 { + NS_ASSERT (offsetsOk); + NS_ASSERT (dirtyOk); + NS_ASSERT (internalSizeOk); + return m_data->m_count > 0 && offsetsOk && dirtyOk && + internalSizeOk; +} + +void +Buffer::Initialize (uint32_t zeroSize) +{ + m_data = Buffer::Create (0); +#ifdef BUFFER_HEURISTICS + m_start = std::min (m_data->m_size, g_recommendedStart); + m_maxZeroAreaStart = m_start; +#else + m_start = 0; +#endif /* BUFFER_HEURISTICS */ + m_zeroAreaStart = m_start; + m_zeroAreaEnd = m_zeroAreaStart + zeroSize; + m_end = m_zeroAreaEnd; + m_data->m_dirtyStart = m_start; + m_data->m_dirtyEnd = m_end; + NS_ASSERT (CheckInternalState ()); +} + +Buffer::Buffer (Buffer const&o) + : m_data (o.m_data), +#ifdef BUFFER_HEURISTICS + m_maxZeroAreaStart (o.m_zeroAreaStart), +#endif + m_zeroAreaStart (o.m_zeroAreaStart), + m_zeroAreaEnd (o.m_zeroAreaEnd), + m_start (o.m_start), + m_end (o.m_end) +{ + m_data->m_count++; + NS_ASSERT (CheckInternalState ()); +} + +Buffer & +Buffer::operator = (Buffer const&o) +{ + NS_ASSERT (CheckInternalState ()); + if (m_data != o.m_data) + { + // not assignment to self. + m_data->m_count--; + if (m_data->m_count == 0) + { + Recycle (m_data); + } + m_data = o.m_data; + m_data->m_count++; + } + HEURISTICS ( + g_recommendedStart = std::max (g_recommendedStart, m_maxZeroAreaStart); + m_maxZeroAreaStart = o.m_maxZeroAreaStart; + ); + m_zeroAreaStart = o.m_zeroAreaStart; + m_zeroAreaEnd = o.m_zeroAreaEnd; + m_start = o.m_start; + m_end = o.m_end; + NS_ASSERT (CheckInternalState ()); + return *this; +} + +Buffer::~Buffer () +{ + HEURISTICS (g_recommendedStart = std::max (g_recommendedStart, m_maxZeroAreaStart)); + m_data->m_count--; + if (m_data->m_count == 0) + { + Recycle (m_data); + } +} + +uint32_t +Buffer::GetSize (void) const +{ + NS_ASSERT (CheckInternalState ()); + return m_end - m_start; +} + +Buffer::Iterator +Buffer::Begin (void) const +{ + NS_ASSERT (CheckInternalState ()); + return Buffer::Iterator (this); +} +Buffer::Iterator +Buffer::End (void) const +{ + NS_ASSERT (CheckInternalState ()); + return Buffer::Iterator (this, false); +} + +uint32_t +Buffer::GetInternalSize (void) const +{ + return m_zeroAreaStart - m_start + m_end - m_zeroAreaEnd; +} +uint32_t +Buffer::GetInternalEnd (void) const +{ + return m_end - (m_zeroAreaEnd - m_zeroAreaStart); +} void Buffer::AddAtStart (uint32_t start) { - NS_ASSERT (m_start <= m_data->m_initialStart); + NS_ASSERT (CheckInternalState ()); bool isDirty = m_data->m_count > 1 && m_start > m_data->m_dirtyStart; - if (m_start >= start && !isDirty) + if (m_start >= start && !isDirty) { - /* enough space in the buffer and not dirty. */ + /* enough space in the buffer and not dirty. + * To add: |..| + * Before: |*****---------***| + * After: |***..---------***| + */ + NS_ASSERT (m_data->m_count == 1 || m_start == m_data->m_dirtyStart); m_start -= start; - m_size += start; + HEURISTICS (g_nAddNoRealloc++); } - else if (m_size + start <= m_data->m_size && !isDirty) +#if 0 + // the following is an optimization + else if (m_start >= start) { - /* enough space but need to move data around to fit new data */ - memmove (m_data->m_data + start, GetStart (), m_size); - NS_ASSERT (start > m_start); - m_data->m_initialStart += start - m_start; - m_start = 0; - m_size += start; - } - else if (m_start < start) - { - /* not enough space in buffer */ - uint32_t newSize = m_size + start; - struct Buffer::BufferData *newData = Buffer::Allocate (newSize, 0); - memcpy (newData->m_data + start, GetStart (), m_size); - newData->m_initialStart = m_data->m_initialStart + start; + struct BufferData *newData = Buffer::Create (m_data->m_size); + memcpy (newData->m_data + m_start, m_data->m_data + m_start, GetInternalSize ()); m_data->m_count--; - if (m_data->m_count == 0) + if (m_data->m_count == 0) { - Buffer::Deallocate (m_data); + Buffer::Recycle (m_data); } m_data = newData; - m_start = 0; - m_size = newSize; - } - else + + m_start -= start; + HEURISTICS (g_nAddRealloc++); + } + else { - /* enough space in the buffer but it is dirty ! */ - NS_ASSERT (isDirty); - struct Buffer::BufferData *newData = Buffer::Create (); - memcpy (newData->m_data + m_start, GetStart (), m_size); - newData->m_initialStart = m_data->m_initialStart; + NS_ASSERT (m_start < start); +#else + else + { +#endif + uint32_t newSize = GetInternalSize () + start; + struct BufferData *newData = Buffer::Create (newSize); + memcpy (newData->m_data + start, m_data->m_data + m_start, GetInternalSize ()); m_data->m_count--; - if (m_data->m_count == 0) + if (m_data->m_count == 0) { - Recycle (m_data); + Buffer::Recycle (m_data); } m_data = newData; - m_start -= start; - m_size += start; - } + + int32_t delta = start - m_start; + m_start = 0; + m_zeroAreaStart += delta; + m_zeroAreaEnd += delta; + m_end += delta; + + HEURISTICS (g_nAddRealloc++); + } + HEURISTICS (m_maxZeroAreaStart = std::max (m_maxZeroAreaStart, m_zeroAreaStart)); // update dirty area m_data->m_dirtyStart = m_start; - m_data->m_dirtySize = m_size; - // update m_maxTotalAddStart - uint32_t addedAtStart; - if (m_data->m_initialStart > m_start) - { - addedAtStart = m_data->m_initialStart - m_start; - } - else - { - addedAtStart = 0; - } - if (addedAtStart > m_maxTotalAddStart) - { - m_maxTotalAddStart = addedAtStart; - } - TRACE ("start add="<m_initialStart); - bool isDirty = m_data->m_count > 1 && - m_start + m_size < m_data->m_dirtyStart + m_data->m_dirtySize; - if (m_start + m_size + end <= m_data->m_size && !isDirty) + NS_ASSERT (CheckInternalState ()); + bool isDirty = m_data->m_count > 1 && m_end < m_data->m_dirtyEnd; + if (GetInternalEnd () + end <= m_data->m_size && !isDirty) { - /* enough space in buffer and not dirty */ - m_size += end; + /* enough space in buffer and not dirty + * Add: |...| + * Before: |**----*****| + * After: |**----...**| + */ + NS_ASSERT (m_data->m_count == 1 || m_end == m_data->m_dirtyEnd); + m_end += end; + + HEURISTICS (g_nAddNoRealloc++); } - else if (m_size + end <= m_data->m_size && !isDirty) +#if 0 + // this is an optimization + else if (GetInternalEnd () + end > m_data->m_size) { - /* enough space but need to move data around to fit the extra data */ - uint32_t newStart = m_data->m_size - (m_size + end); - memmove (m_data->m_data + newStart, GetStart (), m_size); - NS_ASSERT (newStart < m_start); - m_data->m_initialStart -= m_start - newStart; - m_start = newStart; - m_size += end; - } - else if (m_start + m_size + end > m_data->m_size) - { - /* not enough space in buffer */ - uint32_t newSize = m_size + end; - struct Buffer::BufferData *newData = Buffer::Allocate (newSize, 0); - memcpy (newData->m_data, GetStart (), m_size); - newData->m_initialStart = m_data->m_initialStart - m_start; + struct BufferData *newData = Buffer::Create (newSize); + memcpy (newData->m_data + m_start, m_data->m_data + m_start, GetInternalSize ()); m_data->m_count--; if (m_data->m_count == 0) { - Buffer::Deallocate (m_data); + Buffer::Recycle (m_data); } m_data = newData; - m_size = newSize; + + m_end += end; + HEURISTICS (g_nAddRealloc++); + } +#endif + else + { + uint32_t newSize = GetInternalSize () + end; + struct BufferData *newData = Buffer::Create (newSize); + memcpy (newData->m_data, m_data->m_data + m_start, GetInternalSize ()); + m_data->m_count--; + if (m_data->m_count == 0) + { + Buffer::Recycle (m_data); + } + m_data = newData; + + + m_zeroAreaStart -= m_start; + m_zeroAreaEnd -= m_start; + m_end -= m_start; m_start = 0; + + m_end += end; + + HEURISTICS (g_nAddRealloc++); } - else - { - /* enough space in the buffer but it is dirty ! */ - NS_ASSERT (isDirty); - struct Buffer::BufferData *newData = Buffer::Create (); - memcpy (newData->m_data + m_start, GetStart (), m_size); - newData->m_initialStart = m_data->m_initialStart; - m_data->m_count--; - if (m_data->m_count == 0) - { - Recycle (m_data); - } - m_data = newData; - m_size += end; - } + HEURISTICS (m_maxZeroAreaStart = std::max (m_maxZeroAreaStart, m_zeroAreaStart)); // update dirty area m_data->m_dirtyStart = m_start; - m_data->m_dirtySize = m_size; - // update m_maxTotalAddEnd - uint32_t endLoc = m_start + m_size; - uint32_t addedAtEnd; - if (m_data->m_initialStart < endLoc) - { - addedAtEnd = endLoc - m_data->m_initialStart; - } - else - { - addedAtEnd = 0; - } - if (addedAtEnd > m_maxTotalAddEnd) - { - m_maxTotalAddEnd = addedAtEnd; - } - TRACE ("end add="<= start); + uint32_t zeroSize = m_zeroAreaEnd - m_zeroAreaStart; + m_start = newStart - zeroSize; + m_end -= zeroSize; + m_zeroAreaStart = m_start; + m_zeroAreaEnd = m_start; + } else { - NS_ASSERT (m_data->m_initialStart >= m_start); - uint32_t zeroStart = m_data->m_initialStart - m_start; - uint32_t zeroEnd = zeroStart + m_zeroAreaSize; - uint32_t dataEnd = m_size + m_zeroAreaSize; - if (start <= zeroStart) - { - /* only remove start of buffer */ - m_start += start; - m_size -= start; - } - else if (start <= zeroEnd) - { - /* remove start of buffer _and_ start of zero area */ - m_start += zeroStart; - uint32_t zeroDelta = start - zeroStart; - m_zeroAreaSize -= zeroDelta; - NS_ASSERT (zeroDelta <= start); - m_size -= zeroStart; - } - else if (start <= dataEnd) - { - /* remove start of buffer, complete zero area, and part - * of end of buffer */ - m_start += start - m_zeroAreaSize; - m_size -= start - m_zeroAreaSize; - m_zeroAreaSize = 0; - } - else - { - /* remove all buffer */ - m_start += m_size; - m_size = 0; - m_zeroAreaSize = 0; - } + /* remove all buffer */ + m_end -= m_zeroAreaEnd - m_zeroAreaStart; + m_start = m_end; + m_zeroAreaEnd = m_end; + m_zeroAreaStart = m_end; } - TRACE ("start remove="< m_zeroAreaEnd) { - if (m_size <= end) - { - m_size = 0; - } - else - { - m_size -= end; - } - } - else - { - NS_ASSERT (m_data->m_initialStart >= m_start); - uint32_t zeroStart = m_data->m_initialStart - m_start; - uint32_t zeroEnd = zeroStart + m_zeroAreaSize; - uint32_t dataEnd = m_size + m_zeroAreaSize; - NS_ASSERT (zeroStart <= m_size); - NS_ASSERT (zeroEnd <= m_size + m_zeroAreaSize); - if (dataEnd <= end) - { - /* remove all buffer */ - m_zeroAreaSize = 0; - m_start += m_size; - m_size = 0; - } - else if (dataEnd - zeroStart <= end) - { - /* remove end of buffer, zero area, part of start of buffer */ - NS_ASSERT (end >= m_zeroAreaSize); - m_size -= end - m_zeroAreaSize; - m_zeroAreaSize = 0; - } - else if (dataEnd - zeroEnd <= end) - { - /* remove end of buffer, part of zero area */ - uint32_t zeroDelta = end - (dataEnd - zeroEnd); - m_zeroAreaSize -= zeroDelta; - m_size -= end - zeroDelta; - } - else - { - /* remove part of end of buffer */ - m_size -= end; - } + /* remove part of end of buffer */ + m_end = newEnd; } - TRACE ("end remove="<m_initialStart - m_start; - uint32_t zeroEnd = zeroStart + m_zeroAreaSize; - if (m_zeroAreaSize != 0 && + NS_ASSERT (CheckInternalState ()); + uint32_t zeroStart = m_zeroAreaStart - m_start; + uint32_t zeroEnd = zeroStart + m_zeroAreaEnd; + if (m_zeroAreaEnd != 0 && start + length > zeroStart && start <= zeroEnd) { @@ -407,51 +555,433 @@ Buffer::CreateFragment (uint32_t start, uint32_t length) const Buffer tmp = *this; tmp.RemoveAtStart (start); tmp.RemoveAtEnd (GetSize () - (start + length)); + NS_ASSERT (CheckInternalState ()); return tmp; } Buffer Buffer::CreateFullCopy (void) const { - if (m_zeroAreaSize != 0) + NS_ASSERT (CheckInternalState ()); + if (m_zeroAreaEnd != 0) { - NS_ASSERT (m_data->m_initialStart >= m_start); - NS_ASSERT (m_size >= (m_data->m_initialStart - m_start)); Buffer tmp; - tmp.AddAtStart (m_zeroAreaSize); - tmp.Begin ().WriteU8 (0, m_zeroAreaSize); - uint32_t dataStart = m_data->m_initialStart - m_start; + tmp.AddAtStart (m_zeroAreaEnd - m_zeroAreaStart); + tmp.Begin ().WriteU8 (0, m_zeroAreaEnd - m_zeroAreaStart); + uint32_t dataStart = m_zeroAreaStart - m_start; tmp.AddAtStart (dataStart); tmp.Begin ().Write (m_data->m_data+m_start, dataStart); - uint32_t dataEnd = m_size - (m_data->m_initialStart - m_start); + uint32_t dataEnd = m_end - m_zeroAreaEnd; tmp.AddAtEnd (dataEnd); Buffer::Iterator i = tmp.End (); i.Prev (dataEnd); - i.Write (m_data->m_data+m_data->m_initialStart,dataEnd); + i.Write (m_data->m_data+m_zeroAreaStart,dataEnd); return tmp; } + NS_ASSERT (CheckInternalState ()); return *this; } void Buffer::TransformIntoRealBuffer (void) const { + NS_ASSERT (CheckInternalState ()); Buffer tmp = CreateFullCopy (); *const_cast (this) = tmp; + NS_ASSERT (CheckInternalState ()); } uint8_t const* Buffer::PeekData (void) const { + NS_ASSERT (CheckInternalState ()); TransformIntoRealBuffer (); + NS_ASSERT (CheckInternalState ()); return m_data->m_data + m_start; } +/****************************************************** + * The buffer iterator below. + ******************************************************/ +Buffer::Iterator::Iterator () + : m_zeroStart (0), + m_zeroEnd (0), + m_dataStart (0), + m_dataEnd (0), + m_current (0), + m_data (0) +{} +Buffer::Iterator::Iterator (Buffer const*buffer) +{ + Construct (buffer); + m_current = m_dataStart; +} +Buffer::Iterator::Iterator (Buffer const*buffer, bool dummy) +{ + Construct (buffer); + m_current = m_dataEnd; +} -}; // namespace ns3 +void +Buffer::Iterator::Construct (const Buffer *buffer) +{ + m_zeroStart = buffer->m_zeroAreaStart; + m_zeroEnd = buffer->m_zeroAreaEnd; + m_dataStart = buffer->m_start; + m_dataEnd = buffer->m_end; + m_data = buffer->m_data->m_data; +} + +void +Buffer::Iterator::Next (void) +{ + NS_ASSERT (m_current + 1 <= m_dataEnd); + m_current++; +} +void +Buffer::Iterator::Prev (void) +{ + NS_ASSERT (m_current >= 1); + m_current--; +} +void +Buffer::Iterator::Next (uint32_t delta) +{ + NS_ASSERT (m_current + delta <= m_dataEnd); + m_current += delta; +} +void +Buffer::Iterator::Prev (uint32_t delta) +{ + NS_ASSERT (m_current >= delta); + m_current -= delta; +} +uint32_t +Buffer::Iterator::GetDistanceFrom (Iterator const &o) const +{ + NS_ASSERT (m_data == o.m_data); + int32_t diff = m_current - o.m_current; + if (diff < 0) + { + return -diff; + } + else + { + return diff; + } +} + +bool +Buffer::Iterator::IsEnd (void) const +{ + return m_current == m_dataEnd; +} +bool +Buffer::Iterator::IsStart (void) const +{ + return m_current == m_dataStart; +} + +bool +Buffer::Iterator::CheckNoZero (uint32_t start, uint32_t end) const +{ + bool ok = true; + for (uint32_t i = start; i < end; i++) + { + if (!Check (i)) + { + ok = false; + } + } + return ok; +} +bool +Buffer::Iterator::Check (uint32_t i) const +{ + return i >= m_dataStart && + !(i >= m_zeroStart && i < m_zeroEnd) && + i <= m_dataEnd; +} + + +void +Buffer::Iterator::Write (Iterator start, Iterator end) +{ + NS_ASSERT (start.m_data == end.m_data); + NS_ASSERT (start.m_current <= end.m_current); + NS_ASSERT (start.m_zeroStart == end.m_zeroStart); + NS_ASSERT (start.m_zeroEnd == end.m_zeroEnd); + NS_ASSERT (m_data != start.m_data); + uint32_t size = end.m_current - start.m_current; + Iterator cur = start; + for (uint32_t i = 0; i < size; i++) + { + uint8_t data = cur.ReadU8 (); + WriteU8 (data); + } +} + +void +Buffer::Iterator::WriteU16 (uint16_t data) +{ + WriteU8 (data & 0xff); + data >>= 8; + WriteU8 (data & 0xff); +} +void +Buffer::Iterator::WriteU32 (uint32_t data) +{ + WriteU8 (data & 0xff); + data >>= 8; + WriteU8 (data & 0xff); + data >>= 8; + WriteU8 (data & 0xff); + data >>= 8; + WriteU8 (data & 0xff); +} +void +Buffer::Iterator::WriteU64 (uint64_t data) +{ + WriteU8 (data & 0xff); + data >>= 8; + WriteU8 (data & 0xff); + data >>= 8; + WriteU8 (data & 0xff); + data >>= 8; + WriteU8 (data & 0xff); + data >>= 8; + WriteU8 (data & 0xff); + data >>= 8; + WriteU8 (data & 0xff); + data >>= 8; + WriteU8 (data & 0xff); + data >>= 8; + WriteU8 (data & 0xff); +} +void +Buffer::Iterator::WriteHtonU16 (uint16_t data) +{ + WriteU8 ((data >> 8) & 0xff); + WriteU8 ((data >> 0) & 0xff); +} +void +Buffer::Iterator::WriteHtonU32 (uint32_t data) +{ + WriteU8 ((data >> 24) & 0xff); + WriteU8 ((data >> 16) & 0xff); + WriteU8 ((data >> 8) & 0xff); + WriteU8 ((data >> 0) & 0xff); +} +void +Buffer::Iterator::WriteHtonU64 (uint64_t data) +{ + WriteU8 ((data >> 56) & 0xff); + WriteU8 ((data >> 48) & 0xff); + WriteU8 ((data >> 40) & 0xff); + WriteU8 ((data >> 32) & 0xff); + WriteU8 ((data >> 24) & 0xff); + WriteU8 ((data >> 16) & 0xff); + WriteU8 ((data >> 8) & 0xff); + WriteU8 ((data >> 0) & 0xff); +} +void +Buffer::Iterator::Write (uint8_t const*buffer, uint32_t size) +{ + for (uint32_t i = 0; i < size; i++) + { + WriteU8 (buffer[i]); + } +} + +uint16_t +Buffer::Iterator::ReadU16 (void) +{ + uint8_t byte0 = ReadU8 (); + uint8_t byte1 = ReadU8 (); + uint16_t data = byte1; + data <<= 8; + data |= byte0; + + return data; +} +uint32_t +Buffer::Iterator::ReadU32 (void) +{ + uint8_t byte0 = ReadU8 (); + uint8_t byte1 = ReadU8 (); + uint8_t byte2 = ReadU8 (); + uint8_t byte3 = ReadU8 (); + uint32_t data = byte3; + data <<= 8; + data |= byte2; + data <<= 8; + data |= byte1; + data <<= 8; + data |= byte0; + return data; +} +uint64_t +Buffer::Iterator::ReadU64 (void) +{ + uint8_t byte0 = ReadU8 (); + uint8_t byte1 = ReadU8 (); + uint8_t byte2 = ReadU8 (); + uint8_t byte3 = ReadU8 (); + uint8_t byte4 = ReadU8 (); + uint8_t byte5 = ReadU8 (); + uint8_t byte6 = ReadU8 (); + uint8_t byte7 = ReadU8 (); + uint32_t data = byte7; + data <<= 8; + data |= byte6; + data <<= 8; + data |= byte5; + data <<= 8; + data |= byte4; + data <<= 8; + data |= byte3; + data <<= 8; + data |= byte2; + data <<= 8; + data |= byte1; + data <<= 8; + data |= byte0; + + return data; +} +uint16_t +Buffer::Iterator::ReadNtohU16 (void) +{ + uint16_t retval = 0; + retval |= ReadU8 (); + retval <<= 8; + retval |= ReadU8 (); + return retval; +} +uint32_t +Buffer::Iterator::ReadNtohU32 (void) +{ + uint32_t retval = 0; + retval |= ReadU8 (); + retval <<= 8; + retval |= ReadU8 (); + retval <<= 8; + retval |= ReadU8 (); + retval <<= 8; + retval |= ReadU8 (); + return retval; +} +uint64_t +Buffer::Iterator::ReadNtohU64 (void) +{ + uint64_t retval = 0; + retval |= ReadU8 (); + retval <<= 8; + retval |= ReadU8 (); + retval <<= 8; + retval |= ReadU8 (); + retval <<= 8; + retval |= ReadU8 (); + retval <<= 8; + retval |= ReadU8 (); + retval <<= 8; + retval |= ReadU8 (); + retval <<= 8; + retval |= ReadU8 (); + retval <<= 8; + retval |= ReadU8 (); + return retval; +} +void +Buffer::Iterator::Read (uint8_t *buffer, uint32_t size) +{ + for (uint32_t i = 0; i < size; i++) + { + buffer[i] = ReadU8 (); + } +} + +#ifndef BUFFER_USE_INLINE + +void +Buffer::Iterator::WriteU8 (uint8_t data) +{ + if (m_current < m_dataStart) + { + // XXX trying to write outside of data area + NS_ASSERT (false); + } + else if (m_current < m_zeroStart) + { + m_data[m_current] = data; + m_current++; + } + else if (m_current < m_zeroEnd) + { + // XXX trying to write in zero area + NS_ASSERT (false); + } + else if (m_current < m_dataEnd) + { + m_data[m_current - (m_zeroEnd-m_zeroStart)] = data; + m_current++; + } + else + { + // XXX trying to write outside of data area + NS_ASSERT (false); + } +} + +void +Buffer::Iterator::WriteU8 (uint8_t data, uint32_t len) +{ + for (uint32_t i = 0; i < len; i++) + { + WriteU8 (data); + } +} + +uint8_t +Buffer::Iterator::ReadU8 (void) +{ + if (m_current < m_dataStart) + { + // XXX trying to read from outside of data area + NS_ASSERT (false); + } + else if (m_current < m_zeroStart) + { + uint8_t data = m_data[m_current]; + m_current++; + return data; + } + else if (m_current < m_zeroEnd) + { + m_current++; + return 0; + } + else if (m_current < m_dataEnd) + { + uint8_t data = m_data[m_current - (m_zeroEnd-m_zeroStart)]; + m_current++; + return data; + } + else + { + // XXX trying to read from outside of data area + NS_ASSERT (false); + } + // to quiet compiler. + return 0; +} + +#endif /* BUFFER_USE_INLINE */ + +} // namespace ns3 #ifdef RUN_SELF_TESTS @@ -460,6 +990,7 @@ Buffer::PeekData (void) const #include "ns3/random-variable.h" #include + namespace ns3 { class BufferTest: public Test { @@ -687,6 +1218,13 @@ BufferTest::RunTests (void) i.Prev (100); i.WriteU8 (1, 100); +#if 0 + buffer = Buffer (10); + ENSURE_WRITTEN_BYTES (buffer, 10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + buffer.Begin ().WriteU8 (1); + ENSURE_WRITTEN_BYTES (buffer, 10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); +#endif + // Bug #54 { const uint32_t actualSize = 72602; @@ -718,7 +1256,7 @@ BufferTest::RunTests (void) static BufferTest gBufferTest; -}; // namespace ns3 +} // namespace ns3 #endif /* RUN_SELF_TESTS */ diff --git a/src/common/buffer.h b/src/common/buffer.h index f412a419c..a6a8f51db 100644 --- a/src/common/buffer.h +++ b/src/common/buffer.h @@ -1,7 +1,6 @@ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* - * Copyright (c) 2005,2006 INRIA - * All rights reserved. + * Copyright (c) 2005,2006,2007 INRIA * * 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 @@ -24,6 +23,16 @@ #include #include +#define BUFFER_HEURISTICS 1 +#define BUFFER_USE_INLINE 1 + + +#ifdef BUFFER_USE_INLINE +#define BUFFER_INLINE inline +#else +#define BUFFER_INLINE +#endif + namespace ns3 { /** @@ -36,6 +45,51 @@ namespace ns3 { * by creating new Buffers of the maximum size ever used. * The correct maximum size is learned at runtime during use by * recording the maximum size of each packet. + * + * \internal + * The implementation of the Buffer class uses a COW (Copy On Write) + * technique to ensure that the underlying data buffer which holds + * the data bytes is shared among a lot of Buffer instances despite + * data being added or removed from them. + * + * When multiple Buffer instances hold a reference to the same + * underlying BufferData object, they must be able to detect when + * the operation they want to perform should trigger a copy of the + * BufferData. If the BufferData::m_count field is one, it means that + * there exist only one instance of Buffer which references the + * BufferData instance so, it is safe to modify it. It is also + * safe to modify the content of a BufferData if the modification + * falls outside of the "dirty area" defined by the BufferData. + * In every other case, the BufferData must be copied before + * being modified. + * + * To understand the way the Buffer::Add and Buffer::Remove methods + * work, you first need to understand the "virtual offsets" used to + * keep track of the content of buffers. Each Buffer instance + * contains real data bytes in its BufferData instance but it also + * contains "virtual zero data" which typically is used to represent + * application-level payload. No memory is allocated to store the + * zero bytes of application-level payload unless the user fragments + * a Buffer: this application-level payload is kept track of with + * a pair of integers which describe where in the buffer content + * the "virtual zero area" starts and ends. + * + * ***: unused bytes + * xxx: bytes "added" at the front of the zero area + * ...: bytes "added" at the back of the zero area + * 000: virtual zero bytes + * + * Real byte buffer: |********xxxxxxxxxxxx.........*****| + * |--------^ m_start + * |-------------------^ m_zeroAreaStart + * |-----------------------------^ m_end - (m_zeroAreaEnd - m_zeroAreaStart) + * virtual byte buffer: |xxxxxxxxxxxx0000000000000.........| + * |--------^ m_start + * |--------------------^ m_zeroAreaStart + * |---------------------------------^ m_zeroAreaEnd + * |------------------------------------------^ m_end + * + * A simple state invariant is that m_start <= m_zeroStart <= m_zeroEnd <= m_end */ class Buffer { public: @@ -44,23 +98,23 @@ public: */ class Iterator { public: - inline Iterator (); + Iterator (); /** * go forward by one byte */ - inline void Next (void); + void Next (void); /** * go backward by one byte */ - inline void Prev (void); + void Prev (void); /** * \param delta number of bytes to go forward */ - inline void Next (uint32_t delta); + void Next (uint32_t delta); /** * \param delta number of bytes to go backward */ - inline void Prev (uint32_t delta); + void Prev (uint32_t delta); /** * \param o the second iterator * \return number of bytes included between the two iterators @@ -69,18 +123,18 @@ public: * to the same underlying buffer. Debug builds ensure * this with an assert. */ - inline uint32_t GetDistanceFrom (Iterator const &o) const; + uint32_t GetDistanceFrom (Iterator const &o) const; /** * \return true if this iterator points to the end of the byte array. * false otherwise. */ - inline bool IsEnd (void) const; + bool IsEnd (void) const; /** * \return true if this iterator points to the start of the byte array. * false otherwise. */ - inline bool IsStart (void) const; + bool IsStart (void) const; /** * \param data data to write in buffer @@ -88,7 +142,7 @@ public: * Write the data in buffer and avance the iterator position * by one byte. */ - inline void WriteU8 (uint8_t data); + BUFFER_INLINE void WriteU8 (uint8_t data); /** * \param data data to write in buffer * \param len number of times data must be written in buffer @@ -96,7 +150,7 @@ public: * Write the data in buffer len times and avance the iterator position * by len byte. */ - inline void WriteU8 (uint8_t data, uint32_t len); + BUFFER_INLINE void WriteU8 (uint8_t data, uint32_t len); /** * \param data data to write in buffer * @@ -106,7 +160,7 @@ public: * return exactly what we wrote with writeU16 if the program * is run on the same machine. */ - inline void WriteU16 (uint16_t data); + void WriteU16 (uint16_t data); /** * \param data data to write in buffer * @@ -116,7 +170,7 @@ public: * return exactly what we wrote with writeU32 if the program * is run on the same machine. */ - inline void WriteU32 (uint32_t data); + void WriteU32 (uint32_t data); /** * \param data data to write in buffer * @@ -126,7 +180,7 @@ public: * return exactly what we wrote with writeU64 if the program * is run on the same machine. */ - inline void WriteU64 (uint64_t data); + void WriteU64 (uint64_t data); /** * \param data data to write in buffer * @@ -134,7 +188,7 @@ public: * by two bytes. The data is written in network order and the * input data is expected to be in host order. */ - inline void WriteHtonU16 (uint16_t data); + void WriteHtonU16 (uint16_t data); /** * \param data data to write in buffer * @@ -142,7 +196,7 @@ public: * by four bytes. The data is written in network order and the * input data is expected to be in host order. */ - inline void WriteHtonU32 (uint32_t data); + void WriteHtonU32 (uint32_t data); /** * \param data data to write in buffer * @@ -150,7 +204,7 @@ public: * by eight bytes. The data is written in network order and the * input data is expected to be in host order. */ - inline void WriteHtonU64 (uint64_t data); + void WriteHtonU64 (uint64_t data); /** * \param buffer a byte buffer to copy in the internal buffer. * \param size number of bytes to copy. @@ -158,7 +212,7 @@ public: * Write the data in buffer and avance the iterator position * by size bytes. */ - inline void Write (uint8_t const*buffer, uint32_t size); + void Write (uint8_t const*buffer, uint32_t size); /** * \param start the start of the data to copy * \param end the end of the data to copy @@ -170,7 +224,7 @@ public: * we do to avoid overlapping copies. This is enforced * in debug builds by asserts. */ - inline void Write (Iterator start, Iterator end); + void Write (Iterator start, Iterator end); /** * \return the byte read in the buffer. @@ -178,7 +232,7 @@ public: * Read data and advance the Iterator by the number of bytes * read. */ - inline uint8_t ReadU8 (void); + BUFFER_INLINE uint8_t ReadU8 (void); /** * \return the two bytes read in the buffer. * @@ -186,7 +240,7 @@ public: * read. * The data is read in the format written by writeU16. */ - inline uint16_t ReadU16 (void); + uint16_t ReadU16 (void); /** * \return the four bytes read in the buffer. * @@ -194,7 +248,7 @@ public: * read. * The data is read in the format written by writeU32. */ - inline uint32_t ReadU32 (void); + uint32_t ReadU32 (void); /** * \return the eight bytes read in the buffer. * @@ -202,7 +256,7 @@ public: * read. * The data is read in the format written by writeU64. */ - inline uint64_t ReadU64 (void); + uint64_t ReadU64 (void); /** * \return the two bytes read in the buffer. * @@ -210,7 +264,7 @@ public: * read. * The data is read in network format and return in host format. */ - inline uint16_t ReadNtohU16 (void); + uint16_t ReadNtohU16 (void); /** * \return the four bytes read in the buffer. * @@ -218,7 +272,7 @@ public: * read. * The data is read in network format and return in host format. */ - inline uint32_t ReadNtohU32 (void); + uint32_t ReadNtohU32 (void); /** * \return the eight bytes read in the buffer. * @@ -226,7 +280,7 @@ public: * read. * The data is read in network format and return in host format. */ - inline uint64_t ReadNtohU64 (void); + uint64_t ReadNtohU64 (void); /** * \param buffer buffer to copy data into * \param size number of bytes to copy @@ -235,22 +289,45 @@ public: * input buffer and avance the Iterator by the number of * bytes read. */ - inline void Read (uint8_t *buffer, uint16_t size); + void Read (uint8_t *buffer, uint32_t size); private: friend class Buffer; - inline Iterator (Buffer const*buffer, uint32_t m_current); - inline uint32_t GetIndex (uint32_t n); + Iterator (Buffer const*buffer); + Iterator (Buffer const*buffer, bool); + void Construct (const Buffer *buffer); + bool CheckNoZero (uint32_t start, uint32_t end) const; + bool Check (uint32_t i) const; + + /* offset in virtual bytes from the start of the data buffer to the + * start of the "virtual zero area". + */ uint32_t m_zeroStart; + /* offset in virtual bytes from the start of the data buffer to the + * end of the "virtual zero area". + */ uint32_t m_zeroEnd; + /* offset in virtual bytes from the start of the data buffer to the + * start of the data which can be read by this iterator + */ + uint32_t m_dataStart; + /* offset in virtual bytes from the start of the data buffer to the + * end of the data which can be read by this iterator + */ uint32_t m_dataEnd; + /* offset in virtual bytes from the start of the data buffer to the + * current position represented by this iterator. + */ uint32_t m_current; + /* a pointer to the underlying byte buffer. All offsets are relative + * to this pointer. + */ uint8_t *m_data; }; /** * \return the number of bytes stored in this buffer. */ - inline uint32_t GetSize (void) const; + uint32_t GetSize (void) const; /** * \return a pointer to the start of the internal @@ -313,409 +390,135 @@ public: * \return an Iterator which points to the * start of this Buffer. */ - inline Buffer::Iterator Begin (void) const; + Buffer::Iterator Begin (void) const; /** * \return an Iterator which points to the * end of this Buffer. */ - inline Buffer::Iterator End (void) const; + Buffer::Iterator End (void) const; Buffer CreateFullCopy (void) const; - inline Buffer (Buffer const &o); - inline Buffer &operator = (Buffer const &o); - inline Buffer (); - inline Buffer (uint32_t dataSize); - inline ~Buffer (); + Buffer (Buffer const &o); + Buffer &operator = (Buffer const &o); + Buffer (); + Buffer (uint32_t dataSize); + ~Buffer (); private: - struct BufferData { - uint32_t m_count; - uint32_t m_size; - uint32_t m_initialStart; - uint32_t m_dirtyStart; - uint32_t m_dirtySize; - uint8_t m_data[1]; - }; - class BufferDataList : public std::vector - { - public: - ~BufferDataList (); - }; - inline uint8_t *GetStart (void) const; void TransformIntoRealBuffer (void) const; - static void Recycle (struct Buffer::BufferData *data); - static struct Buffer::BufferData *Create (void); - static struct Buffer::BufferData *Allocate (uint32_t size, uint32_t start); - static void Deallocate (struct Buffer::BufferData *data); - - static BufferDataList m_freeList; - static uint32_t m_maxTotalAddStart; - static uint32_t m_maxTotalAddEnd; + bool CheckInternalState (void) const; + void Initialize (uint32_t zeroSize); + uint32_t GetInternalSize (void) const; + uint32_t GetInternalEnd (void) const; + static void Recycle (struct BufferData *data); + static struct BufferData *Create (uint32_t size); + /* This structure is described in the buffer.cc file. + */ struct BufferData *m_data; - uint32_t m_zeroAreaSize; +#ifdef BUFFER_HEURISTICS + /* keep track of the maximum value of m_zeroAreaStart across + * the lifetime of a Buffer instance. This variable is used + * purely as a source of information for the heuristics which + * decide on the position of the zero area in new buffers. + * It is read from the Buffer destructor to update the global + * heuristic data and these global heuristic data are used from + * the Buffer constructor to choose an initial value for + * m_zeroAreaStart. + * It is possible to disable all these heuristics by undefining the + * BUFFER_HEURISTICS macro at the top of buffer.h + */ + uint32_t m_maxZeroAreaStart; +#endif /* BUFFER_HEURISTICS */ + /* offset to the start of the virtual zero area from the start + * of m_data->m_data + */ + uint32_t m_zeroAreaStart; + /* offset to the end of the virtual zero area from the start + * of m_data->m_data + */ + uint32_t m_zeroAreaEnd; + /* offset to the start of the data referenced by this Buffer + * instance from the start of m_data->m_data + */ uint32_t m_start; - uint32_t m_size; + /* offset to the end of the data referenced by this Buffer + * instance from the start of m_data->m_data + */ + uint32_t m_end; }; -}; // namespace ns3 +} // namespace ns3 - -/************************************************** - Start of implementation of methods which - need to be inline for performance reasons. - *************************************************/ +#ifdef BUFFER_USE_INLINE #include "ns3/assert.h" namespace ns3 { -Buffer::Buffer () - : m_data (Buffer::Create ()), - m_zeroAreaSize (0), - m_start (m_maxTotalAddStart), - m_size (0) +void +Buffer::Iterator::WriteU8 (uint8_t data) { - if (m_start > m_data->m_size) + NS_ASSERT (Check (m_current)); + + if (m_current < m_zeroStart) { - m_start = 0; - } - NS_ASSERT (m_start <= m_data->m_size); -} - -Buffer::Buffer (uint32_t dataSize) - : m_data (Buffer::Create ()), - m_zeroAreaSize (dataSize), - m_start (m_maxTotalAddStart), - m_size (0) -{ - if (m_start > m_data->m_size) - { - m_start = 0; - } - NS_ASSERT (m_start <= m_data->m_size); -} - - -Buffer::Buffer (Buffer const&o) - : m_data (o.m_data), - m_zeroAreaSize (o.m_zeroAreaSize), - m_start (o.m_start), - m_size (o.m_size) -{ - m_data->m_count++; - NS_ASSERT (m_start <= m_data->m_size); -} - -Buffer & -Buffer::operator = (Buffer const&o) -{ - if (m_data != o.m_data) - { - // not assignment to self. - m_data->m_count--; - if (m_data->m_count == 0) - { - Recycle (m_data); - } - m_data = o.m_data; - m_data->m_count++; - } - m_zeroAreaSize = o.m_zeroAreaSize; - m_start = o.m_start; - m_size = o.m_size; - NS_ASSERT (m_start <= m_data->m_size); - return *this; -} - -Buffer::~Buffer () -{ - m_data->m_count--; - if (m_data->m_count == 0) - { - Recycle (m_data); - } -} - - -uint8_t * -Buffer::GetStart (void) const -{ - return m_data->m_data + m_start; -} - -uint32_t -Buffer::GetSize (void) const -{ - return m_size + m_zeroAreaSize; -} - -Buffer::Iterator -Buffer::Begin (void) const -{ - return Buffer::Iterator (this, 0); -} -Buffer::Iterator -Buffer::End (void) const -{ - return Buffer::Iterator (this, GetSize ()); -} - - -Buffer::Iterator::Iterator () - : m_zeroStart (0), - m_zeroEnd (0), - m_dataEnd (0), - m_current (0), - m_data (0) -{} -Buffer::Iterator::Iterator (Buffer const*buffer, uint32_t current) - : m_zeroStart (buffer->m_data->m_initialStart-buffer->m_start), - m_zeroEnd (m_zeroStart+buffer->m_zeroAreaSize), - m_dataEnd (buffer->GetSize ()), - m_current (current), - m_data (buffer->m_data->m_data+buffer->m_start) -{} - -void -Buffer::Iterator::Next (void) -{ - NS_ASSERT (m_current + 1 <= m_dataEnd); - m_current++; -} -void -Buffer::Iterator::Prev (void) -{ - NS_ASSERT (m_current >= 1); - m_current--; -} -void -Buffer::Iterator::Next (uint32_t delta) -{ - NS_ASSERT (m_current + delta <= m_dataEnd); - m_current += delta; -} -void -Buffer::Iterator::Prev (uint32_t delta) -{ - NS_ASSERT (m_current >= delta); - m_current -= delta; -} -uint32_t -Buffer::Iterator::GetDistanceFrom (Iterator const &o) const -{ - NS_ASSERT (m_data == o.m_data); - int32_t start = m_current; - int32_t end = o.m_current; - int32_t diff = end - start; - if (diff < 0) - { - return -diff; + m_data[m_current] = data; + m_current++; } else { - return diff; + m_data[m_current - (m_zeroEnd-m_zeroStart)] = data; + m_current++; } } -bool -Buffer::Iterator::IsEnd (void) const -{ - return m_current == m_dataEnd; -} -bool -Buffer::Iterator::IsStart (void) const -{ - return m_current == 0; -} - -uint32_t -Buffer::Iterator::GetIndex (uint32_t n) -{ - NS_ASSERT ( - (m_current + n <= m_dataEnd) && - ((m_current + n <= m_zeroStart) || - (m_current >= m_zeroEnd) || - m_zeroStart == m_zeroEnd) - ); - uint32_t index; - if (m_current < m_zeroStart) - { - index = m_current; - } - else - { - index = m_current - (m_zeroEnd-m_zeroStart); - } - return index; -} - - -void -Buffer::Iterator::Write (Iterator start, Iterator end) -{ - NS_ASSERT (start.m_data == end.m_data); - NS_ASSERT (start.m_current <= end.m_current); - NS_ASSERT (start.m_zeroStart == end.m_zeroStart); - NS_ASSERT (start.m_zeroEnd == end.m_zeroEnd); - NS_ASSERT (m_data != start.m_data); - uint32_t size = end.m_current - start.m_current; - uint8_t *src = start.m_data + start.GetIndex (size); - uint8_t *dest = m_data + GetIndex (size); - memcpy (dest, src, size); - m_current += size; -} - void Buffer::Iterator::WriteU8 (uint8_t data, uint32_t len) { - uint8_t *current = m_data + GetIndex (len); - memset (current, data, len); - m_current += len; -} -void -Buffer::Iterator::WriteU8 (uint8_t data) -{ - m_data[GetIndex (1)] = data; - m_current++; -} -void -Buffer::Iterator::WriteU16 (uint16_t data) -{ - uint16_t *buffer = (uint16_t *)(m_data + GetIndex (2)); - *buffer = data; - m_current += 2; -} -void -Buffer::Iterator::WriteU32 (uint32_t data) -{ - uint32_t *buffer = (uint32_t *)(m_data + GetIndex (4)); - *buffer = data; - m_current += 4; -} -void -Buffer::Iterator::WriteU64 (uint64_t data) -{ - uint64_t *buffer = (uint64_t *)(m_data + GetIndex (8)); - *buffer = data; - m_current += 8; -} -void -Buffer::Iterator::WriteHtonU16 (uint16_t data) -{ - uint8_t *current = m_data + GetIndex (2); - *(current+0) = (data >> 8) & 0xff; - *(current+1) = (data >> 0) & 0xff; - m_current += 2; -} -void -Buffer::Iterator::WriteHtonU32 (uint32_t data) -{ - uint8_t *current = m_data + GetIndex (4); - *(current+0) = (data >> 24) & 0xff; - *(current+1) = (data >> 16) & 0xff; - *(current+2) = (data >> 8) & 0xff; - *(current+3) = (data >> 0) & 0xff; - m_current += 4; -} -void -Buffer::Iterator::WriteHtonU64 (uint64_t data) -{ - uint8_t *current = m_data + GetIndex (8); - *(current+0) = (data >> 56) & 0xff; - *(current+1) = (data >> 48) & 0xff; - *(current+2) = (data >> 40) & 0xff; - *(current+3) = (data >> 32) & 0xff; - *(current+4) = (data >> 24) & 0xff; - *(current+5) = (data >> 16) & 0xff; - *(current+6) = (data >> 8) & 0xff; - *(current+7) = (data >> 0) & 0xff; - m_current += 8; -} -void -Buffer::Iterator::Write (uint8_t const*buffer, uint32_t size) -{ - uint8_t *current = m_data + GetIndex (size); - memcpy (current, buffer, size); - m_current += size; + NS_ASSERT (CheckNoZero (m_current, m_current + len)); + if (m_current <= m_zeroStart) + { + memset (&(m_data[m_current]), data, len); + m_current += len; + } + else + { + uint8_t *buffer = &m_data[m_current - (m_zeroEnd-m_zeroStart)]; + memset (buffer, data, len); + m_current += len; + } } uint8_t Buffer::Iterator::ReadU8 (void) { - uint8_t data = m_data[GetIndex(1)]; - m_current++; - return data; -} -uint16_t -Buffer::Iterator::ReadU16 (void) -{ - uint16_t *buffer = reinterpret_cast(m_data + GetIndex (2)); - m_current += 2; - return *buffer; -} -uint32_t -Buffer::Iterator::ReadU32 (void) -{ - uint32_t *buffer = reinterpret_cast(m_data + GetIndex (4)); - m_current += 4; - return *buffer; -} -uint64_t -Buffer::Iterator::ReadU64 (void) -{ - uint64_t *buffer = reinterpret_cast(m_data + GetIndex (8)); - m_current += 8; - return *buffer; -} -uint16_t -Buffer::Iterator::ReadNtohU16 (void) -{ - uint8_t *current = m_data + GetIndex (2); - uint16_t retval = 0; - retval |= static_cast (current[0]) << 8; - retval |= static_cast (current[1]) << 0; - m_current += 2; - return retval; -} -uint32_t -Buffer::Iterator::ReadNtohU32 (void) -{ - uint8_t *current = m_data + GetIndex (4); - uint32_t retval = 0; - retval |= static_cast (current[0]) << 24; - retval |= static_cast (current[1]) << 16; - retval |= static_cast (current[2]) << 8; - retval |= static_cast (current[3]) << 0; - m_current += 4; - return retval; -} -uint64_t -Buffer::Iterator::ReadNtohU64 (void) -{ - uint8_t *current = m_data + GetIndex (8); - uint64_t retval = 0; - retval |= static_cast (current[0]) << 56; - retval |= static_cast (current[1]) << 48; - retval |= static_cast (current[2]) << 40; - retval |= static_cast (current[3]) << 32; - retval |= static_cast (current[4]) << 24; - retval |= static_cast (current[5]) << 16; - retval |= static_cast (current[6]) << 8; - retval |= static_cast (current[7]) << 0; - m_current += 8; - return retval; -} -void -Buffer::Iterator::Read (uint8_t *buffer, uint16_t size) -{ - uint8_t *current = m_data + GetIndex (size); - memcpy (buffer, current, size); - m_current += size; + NS_ASSERT (m_current >= m_dataStart && + m_current <= m_dataEnd); + + if (m_current < m_zeroStart) + { + uint8_t data = m_data[m_current]; + m_current++; + return data; + } + else if (m_current < m_zeroEnd) + { + m_current++; + return 0; + } + else + { + uint8_t data = m_data[m_current - (m_zeroEnd-m_zeroStart)]; + m_current++; + return data; + } } -}; // namespace ns3 +} // namespace ns3 + +#endif /* BUFFER_USE_INLINE */ #endif /* BUFFER_H */ diff --git a/src/common/packet-metadata-test.cc b/src/common/packet-metadata-test.cc index edca62626..ac4d1f994 100644 --- a/src/common/packet-metadata-test.cc +++ b/src/common/packet-metadata-test.cc @@ -673,6 +673,13 @@ PacketMetadataTest::RunTests (void) p = DoAddHeader (p); CHECK_HISTORY (p, 2, 10, 10); + p = Packet (10); + ADD_HEADER (p, 8); + ADD_TRAILER (p, 8); + ADD_TRAILER (p, 8); + p.RemoveAtStart (8+10+8); + CHECK_HISTORY (p, 1, 8); + return ok; } diff --git a/src/common/packet.cc b/src/common/packet.cc index 0de766dba..372dee8d3 100644 --- a/src/common/packet.cc +++ b/src/common/packet.cc @@ -249,7 +249,7 @@ PacketTest::RunTests (void) packet.GetSize ()); if (msg != "hello world") { - Failure () << "expected size 'hello world', got " << msg << std::endl; + Failure () << "expected 'hello world', got '" << msg << "'" << std::endl; ok = false; } diff --git a/src/devices/csma/csma-channel.cc b/src/devices/csma/csma-channel.cc index 9ba42d854..f9bb9fe48 100644 --- a/src/devices/csma/csma-channel.cc +++ b/src/devices/csma/csma-channel.cc @@ -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 --git a/src/devices/csma/csma-ipv4-topology.cc b/src/devices/csma/csma-ipv4-topology.cc index 02cd0e487..80aa1c10a 100644 --- a/src/devices/csma/csma-ipv4-topology.cc +++ b/src/devices/csma/csma-ipv4-topology.cc @@ -35,82 +35,79 @@ 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 (); } void CsmaIpv4Topology::AddIpv4LlcCsmaNode(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) +uint32_t +CsmaIpv4Topology::AddIpv4Address( + Ptr node, + uint32_t netDeviceNumber, + const Ipv4Address address, + const Ipv4Mask mask) { + Ptr nd = node->GetDevice(netDeviceNumber); - // Duplex link is assumed to be subnetted as a /30 - // May run this unnumbered in the future? - Ipv4Mask netmask(netmask1); - - Ptr nd1 = n1->GetDevice(ndNum); - - Ptr ip1 = n1->QueryInterface (Ipv4::iid); - uint32_t index1 = ip1->AddInterface (nd1); - - ip1->SetAddress (index1, addr1); - ip1->SetNetworkMask (index1, netmask); - ip1->SetUp (index1); + Ptr ipv4 = node->QueryInterface (Ipv4::iid); + uint32_t ifIndex = ipv4->AddInterface (nd); + ipv4->SetAddress (ifIndex, address); + ipv4->SetNetworkMask (ifIndex, mask); + ipv4->SetUp (ifIndex); + return ifIndex; } void @@ -133,7 +130,7 @@ CsmaIpv4Topology::AddIpv4Routes ( found = true; } } - NS_ASSERT(found); + NS_ASSERT (found); uint32_t index2 = 0; found = false; @@ -145,7 +142,7 @@ CsmaIpv4Topology::AddIpv4Routes ( found = true; } } - NS_ASSERT(found); + NS_ASSERT (found); ip1->AddHostRouteTo (ip2-> GetAddress (index2), index1); ip2->AddHostRouteTo (ip1-> GetAddress (index1), index2); diff --git a/src/devices/csma/csma-ipv4-topology.h b/src/devices/csma/csma-ipv4-topology.h index 86be99d7a..8ee60a9df 100644 --- a/src/devices/csma/csma-ipv4-topology.h +++ b/src/devices/csma/csma-ipv4-topology.h @@ -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 @@ -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 netmask1 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 --git a/src/devices/csma/csma-net-device.cc b/src/devices/csma/csma-net-device.cc index 6b5747581..015b69913 100644 --- a/src/devices/csma/csma-net-device.cc +++ b/src/devices/csma/csma-net-device.cc @@ -19,8 +19,6 @@ * Author: Emmanuelle Laprise */ -#include -#include #include "ns3/debug.h" #include "ns3/queue.h" #include "ns3/simulator.h" @@ -70,7 +68,6 @@ CsmaTraceType::Get (void) const return m_type; } - CsmaNetDevice::CsmaNetDevice (Ptr node) : NetDevice (node, Eui48Address::Allocate ()), m_bps (DataRate (0xffffffff)) @@ -81,7 +78,7 @@ CsmaNetDevice::CsmaNetDevice (Ptr node) } CsmaNetDevice::CsmaNetDevice (Ptr node, Eui48Address addr, - CsmaEncapsulationMode encapMode) + CsmaEncapsulationMode encapMode) : NetDevice(node, addr), m_bps (DataRate (0xffffffff)) { @@ -92,8 +89,8 @@ CsmaNetDevice::CsmaNetDevice (Ptr node, Eui48Address addr, } 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)) { @@ -142,7 +139,7 @@ CsmaNetDevice::Init(bool sendEnable, bool receiveEnable) m_queue = 0; EnableBroadcast (Eui48Address ("ff:ff:ff:ff:ff:ff")); - EnableMulticast(); + EnableMulticast (Eui48Address ("01:00:5e:00:00:00")); SetSendEnable (sendEnable); SetReceiveEnable (receiveEnable); @@ -513,10 +510,11 @@ CsmaNetDevice::Receive (const Packet& packet) 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()) @@ -535,12 +533,34 @@ CsmaNetDevice::Receive (const Packet& packet) trailer.CheckFcs(p); p.RemoveHeader(header); + NS_DEBUG ("CsmaNetDevice::Receive (): Pkt destination is " << + header.GetDestination ()); +// +// 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). +// +// 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() != destination)) + + if ((header.GetDestination () != broadcast) && + (mcDest != multicast) && + (header.GetDestination () != destination)) { - // not for us. + NS_DEBUG ("CsmaNetDevice::Receive (): Dropping pkt "); m_dropTrace (p); return; } @@ -572,6 +592,61 @@ CsmaNetDevice::Receive (const Packet& packet) 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 --git a/src/devices/csma/csma-net-device.h b/src/devices/csma/csma-net-device.h index 713611a2a..3c161cbf7 100644 --- a/src/devices/csma/csma-net-device.h +++ b/src/devices/csma/csma-net-device.h @@ -205,6 +205,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 --git a/src/devices/point-to-point/point-to-point-net-device.cc b/src/devices/point-to-point/point-to-point-net-device.cc index 71853b84c..be7153074 100644 --- a/src/devices/point-to-point/point-to-point-net-device.cc +++ b/src/devices/point-to-point/point-to-point-net-device.cc @@ -20,8 +20,6 @@ * Revised: George Riley */ -#include -#include #include "ns3/debug.h" #include "ns3/queue.h" #include "ns3/simulator.h" @@ -73,11 +71,14 @@ PointToPointNetDevice::PointToPointNetDevice (Ptr node, { 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(); +// +// We want to allow multicast packets to flow across this link +// + EnableMulticast (Eui48Address ("01:00:5e:00:00:00")); EnablePointToPoint(); } @@ -218,6 +219,8 @@ bool PointToPointNetDevice::Attach (Ptr ch) 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 --git a/src/internet-node/arp-ipv4-interface.cc b/src/internet-node/arp-ipv4-interface.cc index cd81a1058..ed8ef584c 100644 --- a/src/internet-node/arp-ipv4-interface.cc +++ b/src/internet-node/arp-ipv4-interface.cc @@ -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 ()"); +} Ptr ArpIpv4Interface::GetTraceResolver (void) const { + NS_DEBUG ("ArpIpv4Interface::DoCreateTraceResolver ()"); Ptr resolver = Create (); if (GetDevice () != 0) { @@ -55,32 +63,52 @@ ArpIpv4Interface::GetTraceResolver (void) const 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 () || dest.IsSubnetDirectedBroadcast (GetNetworkMask ()) ) { + NS_DEBUG ("ArpIpv4Interface::SendTo (): IsBroadcast"); hardwareDestination = GetDevice ()->GetBroadcast (); found = true; } + else if (dest.IsMulticast ()) + { + NS_DEBUG ("ArpIpv4Interface::SendTo (): IsMulticast"); + NS_ASSERT_MSG(GetDevice ()->IsMulticast (), + "ArpIpv4Interface::SendTo (): Sending multicast packet over " + "non-multicast device"); + + hardwareDestination = GetDevice ()->MakeMulticastAddress(dest); + 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 --git a/src/internet-node/arp-ipv4-interface.h b/src/internet-node/arp-ipv4-interface.h index c5d36a29f..ac4fc0e30 100644 --- a/src/internet-node/arp-ipv4-interface.h +++ b/src/internet-node/arp-ipv4-interface.h @@ -24,6 +24,7 @@ #include "ipv4-interface.h" #include "ns3/ptr.h" +#include "ns3/eui48-address.h" namespace ns3 { diff --git a/src/internet-node/ipv4-impl.cc b/src/internet-node/ipv4-impl.cc index 307425114..a67c6a4e8 100644 --- a/src/internet-node/ipv4-impl.cc +++ b/src/internet-node/ipv4-impl.cc @@ -95,22 +95,90 @@ 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); +} + +void +Ipv4Impl::SetDefaultMulticastRoute (uint32_t outputInterface) +{ + m_ipv4->SetDefaultMulticastRoute (outputInterface); +} + +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) { 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) { return m_ipv4->GetInterface (i)-> GetDevice (); } +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) { @@ -126,11 +194,39 @@ Ipv4Impl::GetNetworkMask (uint32_t i) const { return m_ipv4->GetNetworkMask (i); } + Ipv4Address Ipv4Impl::GetAddress (uint32_t i) const { return m_ipv4->GetAddress (i); } + +bool +Ipv4Impl::GetIfIndexForDestination (Ipv4Address dest, uint32_t &ifIndex) const +{ + return m_ipv4->GetIfIndexForDestination (dest, ifIndex); +} + +Ipv4Address +Ipv4Impl::GetSourceAddress (Ipv4Address destination) const +{ + uint32_t ifIndex = 0xffffffff; + + bool result = m_ipv4->GetIfIndexForDestination (destination, ifIndex); + + if (result) + { + return m_ipv4->GetAddress (ifIndex); + } + else + { +// +// If we can't find any address, just leave it 0.0.0.0 +// + return Ipv4Address::GetAny (); + } +} + uint16_t Ipv4Impl::GetMtu (uint32_t i) const { diff --git a/src/internet-node/ipv4-impl.h b/src/internet-node/ipv4-impl.h index 445c10454..1f4a79f5c 100644 --- a/src/internet-node/ipv4-impl.h +++ b/src/internet-node/ipv4-impl.h @@ -55,14 +55,43 @@ 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 void SetDefaultMulticastRoute (uint32_t outputInterface); + + 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 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); + virtual void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group); + virtual void SetAddress (uint32_t i, Ipv4Address address); 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 bool GetIfIndexForDestination (Ipv4Address dest, + uint32_t &ifIndex) const; + virtual uint16_t GetMtu (uint32_t i) const; virtual bool IsUp (uint32_t i) const; virtual void SetUp (uint32_t i); diff --git a/src/internet-node/ipv4-interface.cc b/src/internet-node/ipv4-interface.cc index 3ea9120d2..3c66ba7c4 100644 --- a/src/internet-node/ipv4-interface.cc +++ b/src/internet-node/ipv4-interface.cc @@ -23,6 +23,9 @@ #include "ns3/ipv4-address.h" #include "ns3/net-device.h" #include "ns3/trace-resolver.h" +#include "ns3/debug.h" + +NS_DEBUG_COMPONENT_DEFINE ("Ipv4Interface"); namespace ns3 { @@ -35,10 +38,14 @@ namespace ns3 { Ipv4Interface::Ipv4Interface (Ptr nd) : m_netdevice (nd), m_ifup(false) -{} +{ + NS_DEBUG ("Ipv4Interface::Ipv4Interface (" << &nd << ")"); +} Ipv4Interface::~Ipv4Interface () -{} +{ + NS_DEBUG ("Ipv4Interface::~Ipv4Interface ()"); +} void Ipv4Interface::DoDispose (void) @@ -50,42 +57,53 @@ Ipv4Interface::DoDispose (void) Ptr Ipv4Interface::GetDevice (void) const { + NS_DEBUG ("Ipv4Interface::GetDevice ()"); return m_netdevice; } 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; @@ -94,32 +112,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; } @@ -127,7 +149,10 @@ Ipv4Interface::SetDown (void) void Ipv4Interface::Send(Packet p, Ipv4Address dest) { + NS_DEBUG ("Ipv4Interface::Send ()"); + if (IsUp()) { + NS_DEBUG ("Ipv4Interface::Send (): SendTo ()"); SendTo(p, dest); } } diff --git a/src/internet-node/ipv4-l3-protocol.cc b/src/internet-node/ipv4-l3-protocol.cc index 05200f6c2..1c211edf1 100644 --- a/src/internet-node/ipv4-l3-protocol.cc +++ b/src/internet-node/ipv4-l3-protocol.cc @@ -129,17 +129,24 @@ Ipv4L3Protocol::Ipv4L3Protocol(Ptr node) 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 ()"); + m_interfaces.clear (); m_node = 0; m_staticRouting->Dispose (); @@ -150,6 +157,8 @@ Ipv4L3Protocol::DoDispose (void) void Ipv4L3Protocol::SetupLoopback (void) { + NS_DEBUG("Ipv4L3Protocol::SetupLoopback ()"); + Ptr interface = Create (m_node); interface->SetAddress (Ipv4Address::GetLoopback ()); interface->SetNetworkMask (Ipv4Mask::GetLoopback ()); @@ -161,6 +170,8 @@ Ipv4L3Protocol::SetupLoopback (void) Ptr Ipv4L3Protocol::GetTraceResolver (void) const { + NS_DEBUG("Ipv4L3Protocol::GetTraceResolver ()"); + Ptr resolver = Create (); resolver->AddSource ("tx", TraceDoc ("send ipv4 packet to outgoing interface", @@ -185,6 +196,7 @@ Ipv4L3Protocol::GetTraceResolver (void) const void Ipv4L3Protocol::SetDefaultTtl (uint8_t ttl) { + NS_DEBUG("Ipv4L3Protocol::SetDefaultTtl ()"); m_defaultTtl = ttl; } @@ -194,20 +206,28 @@ Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest, 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 @@ -215,28 +235,81 @@ Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network, 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 << ")"); + + Lookup (Ipv4RoutingProtocol::IF_INDEX_ANY, ipHeader, packet, routeReply); +} void -Ipv4L3Protocol::Lookup (Ipv4Header const &ipHeader, - Packet packet, - Ipv4RoutingProtocol::RouteReplyCallback routeReply) +Ipv4L3Protocol::Lookup ( + uint32_t ifIndex, + Ipv4Header const &ipHeader, + Packet packet, + Ipv4RoutingProtocol::RouteReplyCallback routeReply) { - for (Ipv4RoutingProtocolList::const_iterator rprotoIter = m_routingProtocols.begin (); - rprotoIter != m_routingProtocols.end (); rprotoIter++) + NS_DEBUG("Ipv4L3Protocol::Lookup (" << ifIndex << ", " << &ipHeader << + ", " << &packet << &routeReply << ")"); + + for (Ipv4RoutingProtocolList::const_iterator rprotoIter = + m_routingProtocols.begin (); + rprotoIter != m_routingProtocols.end (); + rprotoIter++) { - if ((*rprotoIter).second->RequestRoute (ipHeader, packet, routeReply)) + NS_DEBUG("Ipv4L3Protocol::Lookup (): Requesting route"); + if ((*rprotoIter).second->RequestRoute (ifIndex, ipHeader, packet, + routeReply)) return; } - // No route found + + 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 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 (): " + "Local source. Using unicast default route for multicast packet"); + + routeReply (true, *route, packet, ipHeader); + return; + } + } +// +// No route found +// routeReply (false, Ipv4Route (), packet, ipHeader); } @@ -244,6 +317,8 @@ void Ipv4L3Protocol::AddRoutingProtocol (Ptr routingProtocol, int priority) { + NS_DEBUG("Ipv4L3Protocol::AddRoutingProtocol (" << &routingProtocol << + ", " << priority << ")"); m_routingProtocols.push_back (std::pair > (-priority, routingProtocol)); m_routingProtocols.sort (); @@ -252,39 +327,99 @@ Ipv4L3Protocol::AddRoutingProtocol (Ptr routingProtocol, 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); } +void +Ipv4L3Protocol::AddMulticastRoute (Ipv4Address origin, + Ipv4Address group, + uint32_t inputInterface, + std::vector outputInterfaces) +{ + NS_DEBUG("Ipv4L3Protocol::AddMulticastRoute (" << origin << ", " << + group << ", " << inputInterface << ", " << &outputInterfaces << ")"); + + m_staticRouting->AddMulticastRoute (origin, group, inputInterface, + outputInterfaces); +} + +void +Ipv4L3Protocol::SetDefaultMulticastRoute (uint32_t outputInterface) +{ + NS_DEBUG("Ipv4L3Protocol::SetDefaultMulticastRoute (" << outputInterface << + ")"); + + m_staticRouting->SetDefaultMulticastRoute (outputInterface); +} + +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); +} + +void +Ipv4L3Protocol::RemoveMulticastRoute (Ipv4Address origin, + 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 << ")"); Ptr interface = Create (m_node, device); return AddIpv4Interface (interface); } + uint32_t Ipv4L3Protocol::AddIpv4Interface (Ptrinterface) { + NS_DEBUG("Ipv4L3Protocol::AddIpv4Interface (" << interface << ")"); uint32_t index = m_nInterfaces; m_interfaces.push_back (interface); m_nInterfaces++; return index; } + Ptr 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++) { @@ -296,15 +431,61 @@ Ipv4L3Protocol::GetInterface (uint32_t index) const } return 0; } + uint32_t Ipv4L3Protocol::GetNInterfaces (void) const { + 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; +} + Ptr 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) @@ -318,8 +499,15 @@ Ipv4L3Protocol::FindInterfaceForDevice (Ptr device) void Ipv4L3Protocol::Receive( Ptr device, const Packet& p, uint16_t protocol, const Address &from) { + 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 (); i != m_interfaces.end (); i++) + for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); + i != m_interfaces.end (); + i++) { if ((*i)->GetDevice () == device) { @@ -337,7 +525,7 @@ Ipv4L3Protocol::Receive( Ptr device, const Packet& p, uint16_t protoc return; } - if (Forwarding (packet, ipHeader, device)) + if (Forwarding (index, packet, ipHeader, device)) { return; } @@ -352,6 +540,9 @@ Ipv4L3Protocol::Send (Packet const &packet, Ipv4Address destination, uint8_t protocol) { + NS_DEBUG("Ipv4L3Protocol::Send (" << &packet << ", " << source << ", " << + ", " << destination << ", " << protocol << ")"); + Ipv4Header ipHeader; ipHeader.SetSource (source); @@ -400,36 +591,54 @@ 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."); + 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); Ptr 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) +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++) { if ((*i)->GetAddress ().IsEqual (ipHeader.GetDestination ())) { - NS_DEBUG ("for me 1"); + NS_DEBUG("Ipv4L3Protocol::Forwarding (): " + "For me (destination match)"); return false; } } @@ -442,7 +651,8 @@ Ipv4L3Protocol::Forwarding (Packet const &packet, Ipv4Header &ipHeader, PtrGetBroadcast ())) { - NS_DEBUG ("for me 2"); + NS_DEBUG("Ipv4L3Protocol::Forwarding (): " + "For me (interface broadcast address)"); return false; } break; @@ -451,78 +661,213 @@ Ipv4L3Protocol::Forwarding (Packet const &packet, Ipv4Header &ipHeader, 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) +{ + NS_DEBUG("Ipv4L3Protocol::JoinMulticastGroup (" << origin << ", " << + group << ")"); + m_multicastGroups.push_back( + std::pair (origin, group)); +} + +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++) + { + if ((*i).first.IsEqual(origin) && (*i).second.IsEqual(group)) + { + m_multicastGroups.erase (i); + return; + } + } +} + void Ipv4L3Protocol::SetAddress (uint32_t i, Ipv4Address address) { + NS_DEBUG("Ipv4L3Protocol::SetAddress (" << i << ", " << address << ")"); Ptr interface = GetInterface (i); interface->SetAddress (address); } + void Ipv4L3Protocol::SetNetworkMask (uint32_t i, Ipv4Mask mask) { + NS_DEBUG("Ipv4L3Protocol::SetNetworkMask (" << i << ", " << mask << ")"); Ptr interface = GetInterface (i); interface->SetNetworkMask (mask); } + Ipv4Mask Ipv4L3Protocol::GetNetworkMask (uint32_t i) const { + NS_DEBUG("Ipv4L3Protocol::GetNetworkMask (" << i << ")"); Ptr interface = GetInterface (i); return interface->GetNetworkMask (); } + Ipv4Address Ipv4L3Protocol::GetAddress (uint32_t i) const { + NS_DEBUG("Ipv4L3Protocol::GetAddress (" << i << ")"); Ptr interface = GetInterface (i); return interface->GetAddress (); } + +bool +Ipv4L3Protocol::GetIfIndexForDestination ( + Ipv4Address destination, uint32_t& ifIndex) const +{ + 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++) + { + NS_DEBUG("Ipv4L3Protocol::Lookup (): Requesting Source Address"); + uint32_t ifIndexTmp; + + if ((*i).second->RequestIfIndex (destination, ifIndexTmp)) + { + NS_DEBUG("Ipv4L3Protocol::GetIfIndexForDestination (): " + "Found ifIndex " << ifIndexTmp); + ifIndex = ifIndexTmp; + return true; + } + } +// +// 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 connected to the outside world. +// + 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. 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 unicast 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 Ipv4L3Protocol::GetMtu (uint32_t i) const { + NS_DEBUG("Ipv4L3Protocol::GetMtu (" << i << ")"); Ptr interface = GetInterface (i); return interface->GetMtu (); } + bool Ipv4L3Protocol::IsUp (uint32_t i) const { + NS_DEBUG("Ipv4L3Protocol::IsUp (" << i << ")"); Ptr interface = GetInterface (i); return interface->IsUp (); } + void Ipv4L3Protocol::SetUp (uint32_t i) { + NS_DEBUG("Ipv4L3Protocol::SetUp (" << i << ")"); Ptr interface = GetInterface (i); interface->SetUp (); @@ -536,9 +881,11 @@ Ipv4L3Protocol::SetUp (uint32_t i) interface->GetNetworkMask (), i); } } + void Ipv4L3Protocol::SetDown (uint32_t ifaceIndex) { + NS_DEBUG("Ipv4L3Protocol::SetDown (" << ifaceIndex << ")"); Ptr interface = GetInterface (ifaceIndex); interface->SetDown (); diff --git a/src/internet-node/ipv4-l3-protocol.h b/src/internet-node/ipv4-l3-protocol.h index 8eb6dbe10..001852571 100644 --- a/src/internet-node/ipv4-l3-protocol.h +++ b/src/internet-node/ipv4-l3-protocol.h @@ -169,15 +169,37 @@ public: Ipv4Route *GetRoute (uint32_t i); void RemoveRoute (uint32_t i); + void AddMulticastRoute (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; + + void RemoveMulticastRoute (Ipv4Address origin, + Ipv4Address group, + uint32_t inputInterface); + void RemoveMulticastRoute (uint32_t i); + uint32_t AddInterface (Ptr device); Ptr GetInterface (uint32_t i) const; uint32_t GetNInterfaces (void) const; + uint32_t FindInterfaceForAddr (Ipv4Address addr) const; + uint32_t FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const; + 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); 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); @@ -192,17 +214,26 @@ protected: virtual Ptr GetTraceResolver (void) const; 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 (Ptr interface); void SetupLoopback (void); typedef std::list > Ipv4InterfaceList; + typedef std::list > + Ipv4MulticastGroupList; typedef std::list< std::pair< int, Ptr > > Ipv4RoutingProtocolList; Ipv4InterfaceList m_interfaces; @@ -217,6 +248,7 @@ private: Ipv4RoutingProtocolList m_routingProtocols; Ptr m_staticRouting; + Ipv4MulticastGroupList m_multicastGroups; }; } // Namespace ns3 diff --git a/src/internet-node/ipv4-loopback-interface.cc b/src/internet-node/ipv4-loopback-interface.cc index 1ac8094e9..a4e8b6bfb 100644 --- a/src/internet-node/ipv4-loopback-interface.cc +++ b/src/internet-node/ipv4-loopback-interface.cc @@ -19,25 +19,41 @@ * Authors: * Mathieu Lacage , */ + +#include "ns3/debug.h" #include "ns3/net-device.h" #include "ns3/node.h" #include "ns3/eui48-address.h" #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 ()"); +} + 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 --git a/src/internet-node/ipv4-static-routing.cc b/src/internet-node/ipv4-static-routing.cc index b70c1c1af..c181dde29 100644 --- a/src/internet-node/ipv4-static-routing.cc +++ b/src/internet-node/ipv4-static-routing.cc @@ -19,22 +19,30 @@ // Author: George F. Riley // Gustavo Carneiro +#include "ns3/debug.h" #include "ipv4-static-routing.h" #include "ns3/packet.h" +NS_DEBUG_COMPONENT_DEFINE ("Ipv4StaticRouting"); namespace ns3 { +Ipv4StaticRouting::Ipv4StaticRouting () +: m_defaultRoute (0), m_defaultMulticastRoute (0) +{ +} void Ipv4StaticRouting::AddHostRouteTo (Ipv4Address dest, 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 +51,7 @@ Ipv4StaticRouting::AddHostRouteTo (Ipv4Address dest, *route = Ipv4Route::CreateHostRouteTo (dest, interface); m_hostRoutes.push_back (route); } + void Ipv4StaticRouting::AddNetworkRouteTo (Ipv4Address network, Ipv4Mask networkMask, @@ -56,6 +65,7 @@ Ipv4StaticRouting::AddNetworkRouteTo (Ipv4Address network, interface); m_networkRoutes.push_back (route); } + void Ipv4StaticRouting::AddNetworkRouteTo (Ipv4Address network, Ipv4Mask networkMask, @@ -67,6 +77,7 @@ Ipv4StaticRouting::AddNetworkRouteTo (Ipv4Address network, interface); m_networkRoutes.push_back (route); } + void Ipv4StaticRouting::SetDefaultRoute (Ipv4Address nextHop, uint32_t interface) @@ -77,6 +88,168 @@ Ipv4StaticRouting::SetDefaultRoute (Ipv4Address nextHop, 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); +} + +void +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; +} + +uint32_t +Ipv4StaticRouting::GetNMulticastRoutes (void) const +{ + return m_multicastRoutes.size () + m_defaultMulticastRoute ? 1 : 0; +} + +Ipv4MulticastRoute * +Ipv4StaticRouting::GetMulticastRoute (uint32_t index) const +{ + NS_ASSERT_MSG(index < m_multicastRoutes.size (), + "Ipv4StaticRouting::GetMulticastRoute (): Index out of range"); +// +// 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; +} + +bool +Ipv4StaticRouting::RemoveMulticastRoute(Ipv4Address origin, + 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++) + { + Ipv4MulticastRoute *route = *i; + if (origin == route->GetOrigin () && + group == route->GetGroup () && + inputInterface == route->GetInputInterface ()) + { + delete *i; + m_multicastRoutes.erase (i); + return true; + } + } + return false; +} + +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 (); + i++) + { + if (tmp == index) + { + delete *i; + m_multicastRoutes.erase (i); + return; + } + tmp++; + } +} + Ipv4Route * Ipv4StaticRouting::LookupStatic (Ipv4Address dest) { @@ -110,6 +283,110 @@ Ipv4StaticRouting::LookupStatic (Ipv4Address dest) return 0; } +Ipv4MulticastRoute * +Ipv4StaticRouting::LookupStatic ( + Ipv4Address origin, + 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; +// +// 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 ()) + { + return *i; + } + } + } +// +// 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; + } + + return 0; +} + uint32_t Ipv4StaticRouting::GetNRoutes (void) { @@ -122,6 +399,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) { @@ -209,10 +500,52 @@ Ipv4StaticRouting::RemoveRoute (uint32_t index) } 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 << ")"); + + NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): source = " << + ipHeader.GetSource ()); + + NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): destination = " << + ipHeader.GetDestination ()); + + if (ipHeader.GetDestination ().IsMulticast ()) + { + NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): Multicast destination"); + + Ipv4MulticastRoute *mRoute = LookupStatic(ipHeader.GetSource (), + ipHeader.GetDestination (), ifIndex); + + if (mRoute) + { + NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): " + "Multicast route found"); + + for (uint32_t i = 0; i < mRoute->GetNOutputInterfaces (); ++i) + { + Packet p = packet; + Ipv4Header h = ipHeader; + Ipv4Route route = + Ipv4Route::CreateHostRouteTo(h.GetDestination (), + mRoute->GetOutputInterface(i)); + NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): " + "Send via interface " << mRoute->GetOutputInterface(i)); + routeReply (true, route, p, h); + } + return true; + } + return false; // Let other routing protocols try to handle this + } +// +// 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 ()); if (route != 0) { @@ -226,6 +559,57 @@ Ipv4StaticRouting::RequestRoute (Ipv4Header const &ipHeader, } } +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); + NS_DEBUG ("Ipv4StaticRouting::RequestIfIndex (): " + "Found ifIndex " << ifIndex); + 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) { @@ -246,8 +630,18 @@ 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); + } + if (m_defaultMulticastRoute != 0) + { + delete m_defaultMulticastRoute; + m_defaultMulticastRoute = 0; + } Ipv4RoutingProtocol::DoDispose (); } - }//namespace ns3 diff --git a/src/internet-node/ipv4-static-routing.h b/src/internet-node/ipv4-static-routing.h index 8462f55a7..764d0016b 100644 --- a/src/internet-node/ipv4-static-routing.h +++ b/src/internet-node/ipv4-static-routing.h @@ -45,36 +45,441 @@ class TraceResolver; 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: - Ipv4StaticRouting () : m_defaultRoute (0) {} +/** + * @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 (); - virtual bool RequestRoute (Ipv4Header const &ipHeader, +/** + * @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, 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 + */ + void AddMulticastRoute (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. 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 + */ + 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; + +/** + * @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 + */ + 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: void DoDispose (void); @@ -86,15 +491,21 @@ 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, + uint32_t ifIndex); HostRoutes m_hostRoutes; NetworkRoutes m_networkRoutes; Ipv4Route *m_defaultRoute; + Ipv4MulticastRoute *m_defaultMulticastRoute; + MulticastRoutes m_multicastRoutes; }; - - } // Namespace ns3 #endif /* IPV4_STATIC_ROUTING_H */ diff --git a/src/internet-node/udp-l4-protocol.cc b/src/internet-node/udp-l4-protocol.cc index fc2a54dc9..adf462f05 100644 --- a/src/internet-node/udp-l4-protocol.cc +++ b/src/internet-node/udp-l4-protocol.cc @@ -19,6 +19,7 @@ * Author: Mathieu Lacage */ +#include "ns3/debug.h" #include "ns3/assert.h" #include "ns3/packet.h" #include "ns3/node.h" @@ -30,6 +31,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 */ @@ -39,14 +42,19 @@ UdpL4Protocol::UdpL4Protocol (Ptr node) : Ipv4L4Protocol (PROT_NUMBER, 2), m_node (node), m_endPoints (new Ipv4EndPointDemux ()) -{} +{ + NS_DEBUG("UdpL4Protocol::UdpL4Protocol ()"); +} UdpL4Protocol::~UdpL4Protocol () -{} +{ + NS_DEBUG("UdpL4Protocol::~UdpL4Protocol ()"); +} void UdpL4Protocol::DoDispose (void) { + NS_DEBUG("UdpL4Protocol::DoDispose ()"); if (m_endPoints != 0) { delete m_endPoints; @@ -59,6 +67,7 @@ UdpL4Protocol::DoDispose (void) Ptr UdpL4Protocol::CreateSocket (void) { + NS_DEBUG("UdpL4Protocol::CreateSocket ()"); Ptr socket = Create (m_node, this); return socket; } @@ -66,27 +75,36 @@ UdpL4Protocol::CreateSocket (void) 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); } @@ -94,6 +112,7 @@ UdpL4Protocol::Allocate (Ipv4Address localAddress, uint16_t localPort, void UdpL4Protocol::DeAllocate (Ipv4EndPoint *endPoint) { + NS_DEBUG("UdpL4Protocol::Deallocate (" << endPoint << ")"); m_endPoints->DeAllocate (endPoint); } @@ -102,6 +121,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 = @@ -119,6 +141,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); @@ -132,6 +157,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 --git a/src/internet-node/udp-socket.cc b/src/internet-node/udp-socket.cc index 39fd39ddb..6f123bed5 100644 --- a/src/internet-node/udp-socket.cc +++ b/src/internet-node/udp-socket.cc @@ -18,6 +18,8 @@ * * Author: Mathieu Lacage */ + +#include "ns3/debug.h" #include "ns3/node.h" #include "ns3/inet-socket-address.h" #include "ns3/ipv4-route.h" @@ -26,6 +28,9 @@ #include "udp-l4-protocol.h" #include "ipv4-end-point.h" #include "ipv4-l4-demux.h" +#include "ns3/ipv4.h" + +NS_DEBUG_COMPONENT_DEFINE ("UdpSocket"); namespace ns3 { @@ -37,9 +42,14 @@ UdpSocket::UdpSocket (Ptr node, Ptr udp) 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) { @@ -62,25 +72,32 @@ UdpSocket::~UdpSocket () 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; @@ -93,14 +110,20 @@ UdpSocket::FinishBind (void) 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); @@ -129,12 +152,15 @@ UdpSocket::Bind (const Address &address) 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; } @@ -142,6 +168,7 @@ UdpSocket::ShutdownRecv (void) int UdpSocket::Close(void) { + NS_DEBUG("UdpSocket::Close ()"); NotifyCloseCompleted (); return 0; } @@ -149,24 +176,36 @@ UdpSocket::Close(void) int UdpSocket::Connect(const Address & address) { + NS_DEBUG ("UdpSocket::Connect (" << address << ")"); Ipv4Route routeToDest; InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); m_defaultAddress = transport.GetIpv4 (); m_defaultPort = transport.GetPort (); NotifyConnectionSucceeded (); m_connected = true; - if (GetIpv4RouteToDestination (m_node, routeToDest, m_defaultAddress) ) + + NS_DEBUG ("UdpSocket::Connect (): Updating local address"); + + uint32_t localIfIndex; + + Ptr ipv4 = m_node->QueryInterface (Ipv4::iid); + + if (ipv4->GetIfIndexForDestination (m_defaultAddress, localIfIndex)) { - uint32_t localIfIndex = routeToDest.GetInterface (); - Ptr ipv4 = m_node->QueryInterface (Ipv4::iid); - m_endPoint->SetLocalAddress (ipv4->GetAddress(localIfIndex) ); + m_endPoint->SetLocalAddress (ipv4->GetAddress(localIfIndex)); } + + NS_DEBUG ("UdpSocket::Connect (): Local address is " << + m_endPoint->GetLocalAddress()); + return 0; } int UdpSocket::Send (const Packet &p) { + NS_DEBUG("UdpSocket::Send (" << &p << ")"); + if (!m_connected) { m_errno = ERROR_NOTCONN; @@ -196,12 +235,14 @@ UdpSocket::DoSend (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 << ")"); + if (!m_connected) { + NS_DEBUG("UdpSocket::DoSendTo (): Not connected"); InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); Ipv4Address ipv4 = transport.GetIpv4 (); uint16_t port = transport.GetPort (); @@ -210,13 +251,19 @@ UdpSocket::DoSendTo (const Packet &p, const Address &address) else { // connected UDP socket must use default addresses + NS_DEBUG("UdpSocket::DoSendTo (): Connected"); return DoSendTo (p, m_defaultAddress, m_defaultPort); } } + int UdpSocket::DoSendTo (const Packet &p, Ipv4Address dest, uint16_t port) { + NS_DEBUG("UdpSocket::DoSendTo (" << &p << ", " << dest << ", " << + port << ")"); + Ipv4Route routeToDest; + if (m_endPoint == 0) { if (Bind () == -1) @@ -231,13 +278,17 @@ UdpSocket::DoSendTo (const Packet &p, Ipv4Address dest, uint16_t port) m_errno = ERROR_SHUTDOWN; return -1; } + + uint32_t localIfIndex; + Ptr ipv4 = m_node->QueryInterface (Ipv4::iid); + // // If dest is sent to the limited broadcast address (all ones), // convert it to send a copy of the packet out of every interface // if (dest.IsBroadcast ()) { - Ptr ipv4 = m_node->QueryInterface (Ipv4::iid); + NS_DEBUG("UdpSocket::DoSendTo (): Limited broadcast"); for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i++ ) { Ipv4Address addri = ipv4->GetAddress (i); @@ -247,10 +298,9 @@ UdpSocket::DoSendTo (const Packet &p, Ipv4Address dest, uint16_t port) NotifyDataSent (p.GetSize ()); } } - else if (GetIpv4RouteToDestination (m_node, routeToDest, dest) ) + else if (ipv4->GetIfIndexForDestination(dest, localIfIndex)) { - uint32_t localIfIndex = routeToDest.GetInterface (); - Ptr ipv4 = m_node->QueryInterface (Ipv4::iid); + NS_DEBUG("UdpSocket::DoSendTo (): Route exists"); m_udp->Send (p, ipv4->GetAddress (localIfIndex), dest, m_endPoint->GetLocalPort (), port); NotifyDataSent (p.GetSize ()); @@ -258,15 +308,18 @@ UdpSocket::DoSendTo (const Packet &p, Ipv4Address dest, uint16_t port) } else { + NS_DEBUG("UdpSocket::DoSendTo (): ERROR_NOROUTETOHOST"); m_errno = ERROR_NOROUTETOHOST; return -1; } + return 0; } int UdpSocket::SendTo(const Address &address, const Packet &p) { + NS_DEBUG("UdpSocket::SendTo (" << address << ", " << &p << ")"); InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); Ipv4Address ipv4 = transport.GetIpv4 (); uint16_t port = transport.GetPort (); @@ -276,6 +329,9 @@ UdpSocket::SendTo(const Address &address, const Packet &p) void UdpSocket::ForwardUp (const Packet &packet, Ipv4Address ipv4, uint16_t port) { + NS_DEBUG("UdpSocket::ForwardUp (" << &packet << ", " << ipv4 << ", " << + port << ")"); + if (m_shutdownRecv) { return; @@ -286,4 +342,4 @@ UdpSocket::ForwardUp (const Packet &packet, Ipv4Address ipv4, uint16_t port) NotifyDataReceived (p, address); } -}//namespace ns3 +} //namespace ns3 diff --git a/src/mobility/grid-topology.cc b/src/mobility/grid-topology.cc index fbf7d2511..625cb49ae 100644 --- a/src/mobility/grid-topology.cc +++ b/src/mobility/grid-topology.cc @@ -1,7 +1,6 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2007 INRIA - * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mobility/grid-topology.h b/src/mobility/grid-topology.h index 93457503d..75ea42535 100644 --- a/src/mobility/grid-topology.h +++ b/src/mobility/grid-topology.h @@ -1,7 +1,6 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2007 INRIA - * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mobility/hierarchical-mobility-model.cc b/src/mobility/hierarchical-mobility-model.cc index 046f98056..00f4643c2 100644 --- a/src/mobility/hierarchical-mobility-model.cc +++ b/src/mobility/hierarchical-mobility-model.cc @@ -1,7 +1,6 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2007 INRIA - * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mobility/hierarchical-mobility-model.h b/src/mobility/hierarchical-mobility-model.h index 16be7820b..44623244d 100644 --- a/src/mobility/hierarchical-mobility-model.h +++ b/src/mobility/hierarchical-mobility-model.h @@ -1,7 +1,6 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2007 INRIA - * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mobility/mobility-model-notifier.cc b/src/mobility/mobility-model-notifier.cc index ebe64f3df..4b87dd066 100644 --- a/src/mobility/mobility-model-notifier.cc +++ b/src/mobility/mobility-model-notifier.cc @@ -1,7 +1,6 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2007 INRIA - * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mobility/mobility-model-notifier.h b/src/mobility/mobility-model-notifier.h index 1d2409f8e..e3616b904 100644 --- a/src/mobility/mobility-model-notifier.h +++ b/src/mobility/mobility-model-notifier.h @@ -1,7 +1,6 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2007 INRIA - * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mobility/mobility-model.cc b/src/mobility/mobility-model.cc index 808c5f4dd..50965d800 100644 --- a/src/mobility/mobility-model.cc +++ b/src/mobility/mobility-model.cc @@ -1,7 +1,6 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2006,2007 INRIA - * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mobility/mobility-model.h b/src/mobility/mobility-model.h index 5d0e6ee4a..07fd171ea 100644 --- a/src/mobility/mobility-model.h +++ b/src/mobility/mobility-model.h @@ -1,7 +1,6 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2006,2007 INRIA - * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mobility/position.cc b/src/mobility/position.cc index 802fe3bb7..2418cb61e 100644 --- a/src/mobility/position.cc +++ b/src/mobility/position.cc @@ -1,3 +1,22 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 INRIA + * + * 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 "position.h" #include diff --git a/src/mobility/position.h b/src/mobility/position.h index d34fadfb2..08ab9a134 100644 --- a/src/mobility/position.h +++ b/src/mobility/position.h @@ -1,4 +1,22 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 INRIA + * + * 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 POSITION_H #define POSITION_H diff --git a/src/mobility/random-position.cc b/src/mobility/random-position.cc index 93a3d825e..5e821cfc0 100644 --- a/src/mobility/random-position.cc +++ b/src/mobility/random-position.cc @@ -1,3 +1,22 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 INRIA + * + * 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 "random-position.h" #include "ns3/random-variable.h" #include "ns3/default-value.h" diff --git a/src/mobility/random-position.h b/src/mobility/random-position.h index 8fcc54a6d..04a5b6890 100644 --- a/src/mobility/random-position.h +++ b/src/mobility/random-position.h @@ -1,4 +1,22 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 INRIA + * + * 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 RANDOM_POSITION_H #define RANDOM_POSITION_H diff --git a/src/mobility/rectangle-default-value.cc b/src/mobility/rectangle-default-value.cc index 1526f5a8e..389a696d0 100644 --- a/src/mobility/rectangle-default-value.cc +++ b/src/mobility/rectangle-default-value.cc @@ -1,7 +1,6 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2007 INRIA - * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mobility/rectangle-default-value.h b/src/mobility/rectangle-default-value.h index 047e7bbb6..bc35b7440 100644 --- a/src/mobility/rectangle-default-value.h +++ b/src/mobility/rectangle-default-value.h @@ -1,7 +1,6 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2007 INRIA - * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mobility/rectangle.cc b/src/mobility/rectangle.cc index 34e23e58b..5ae589b8c 100644 --- a/src/mobility/rectangle.cc +++ b/src/mobility/rectangle.cc @@ -1,7 +1,6 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2007 INRIA - * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mobility/rectangle.h b/src/mobility/rectangle.h index a53f641d6..df519b545 100644 --- a/src/mobility/rectangle.h +++ b/src/mobility/rectangle.h @@ -1,7 +1,6 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2007 INRIA - * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mobility/speed.cc b/src/mobility/speed.cc index 3f97ded7c..c6abd0c1d 100644 --- a/src/mobility/speed.cc +++ b/src/mobility/speed.cc @@ -1,3 +1,22 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 INRIA + * + * 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 "speed.h" namespace ns3 { diff --git a/src/mobility/speed.h b/src/mobility/speed.h index 317fc4333..d64b1e63b 100644 --- a/src/mobility/speed.h +++ b/src/mobility/speed.h @@ -1,4 +1,22 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 INRIA + * + * 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 SPEED_H #define SPEED_H diff --git a/src/mobility/static-mobility-model.cc b/src/mobility/static-mobility-model.cc index e6d68f5c3..5142b8178 100644 --- a/src/mobility/static-mobility-model.cc +++ b/src/mobility/static-mobility-model.cc @@ -1,7 +1,6 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* - * Copyright (c) 2006 INRIA - * All rights reserved. + * Copyright (c) 2006,2007 INRIA * * 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 diff --git a/src/mobility/static-mobility-model.h b/src/mobility/static-mobility-model.h index d70890cc0..a1215c08a 100644 --- a/src/mobility/static-mobility-model.h +++ b/src/mobility/static-mobility-model.h @@ -1,7 +1,6 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2006,2007 INRIA - * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mobility/static-speed-helper.cc b/src/mobility/static-speed-helper.cc index b46f88721..82a3dd029 100644 --- a/src/mobility/static-speed-helper.cc +++ b/src/mobility/static-speed-helper.cc @@ -1,3 +1,22 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2006,2007 INRIA + * + * 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 "ns3/simulator.h" #include "ns3/rectangle.h" #include "static-speed-helper.h" diff --git a/src/mobility/static-speed-helper.h b/src/mobility/static-speed-helper.h index 8737f2edd..24e1c6237 100644 --- a/src/mobility/static-speed-helper.h +++ b/src/mobility/static-speed-helper.h @@ -1,4 +1,22 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2006,2007 INRIA + * + * 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 STATIC_SPEED_HELPER_H #define STATIC_SPEED_HELPER_H diff --git a/src/mobility/static-speed-mobility-model.cc b/src/mobility/static-speed-mobility-model.cc index d4cfc9873..3f0dd3229 100644 --- a/src/mobility/static-speed-mobility-model.cc +++ b/src/mobility/static-speed-mobility-model.cc @@ -1,7 +1,6 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2006, 2007 INRIA - * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mobility/static-speed-mobility-model.h b/src/mobility/static-speed-mobility-model.h index 74f5b51f9..85d4793d7 100644 --- a/src/mobility/static-speed-mobility-model.h +++ b/src/mobility/static-speed-mobility-model.h @@ -1,7 +1,6 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2006, 2007 INRIA - * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/node/ipv4-route.cc b/src/node/ipv4-route.cc index bcc556894..1c56c972e 100644 --- a/src/node/ipv4-route.cc +++ b/src/node/ipv4-route.cc @@ -30,6 +30,7 @@ namespace ns3 { Ipv4Route::Ipv4Route () {} + Ipv4Route::Ipv4Route (Ipv4Route const &route) : m_dest (route.m_dest), m_destNetworkMask (route.m_destNetworkMask), @@ -37,6 +38,13 @@ Ipv4Route::Ipv4Route (Ipv4Route const &route) 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, Ipv4Address gateway, uint32_t interface) @@ -137,7 +145,6 @@ Ipv4Route::GetInterface (void) const return m_interface; } - Ipv4Route Ipv4Route::CreateHostRouteTo (Ipv4Address dest, Ipv4Address nextHop, @@ -220,4 +227,108 @@ std::ostream& operator<< (std::ostream& os, Ipv4Route const& route) 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 (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 --git a/src/node/ipv4-route.h b/src/node/ipv4-route.h index efe9b52e2..933e3534e 100644 --- a/src/node/ipv4-route.h +++ b/src/node/ipv4-route.h @@ -22,6 +22,7 @@ #define IPV4_ROUTE_H #include +#include #include #include "ipv4-address.h" @@ -36,12 +37,19 @@ 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; /** * \return The IPv4 address of the destination of this route @@ -98,6 +106,74 @@ 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); + + /** + * \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 --git a/src/node/ipv4.cc b/src/node/ipv4.cc index d7c83d42a..f8a852149 100644 --- a/src/node/ipv4.cc +++ b/src/node/ipv4.cc @@ -36,10 +36,10 @@ Ipv4::~Ipv4 () {} uint32_t -GetIfIndexByIpv4Address (Ptr node, Ipv4Address a, Ipv4Mask amask) +Ipv4::GetIfIndexByAddress (Ptr node, Ipv4Address a, Ipv4Mask amask) { Ptr ipv4 = node->QueryInterface (Ipv4::iid); - NS_ASSERT_MSG (ipv4, "GetIfIndexByIpv4Address: No Ipv4 interface"); + NS_ASSERT_MSG (ipv4, "Ipv4::GetIfIndexByAddress: No Ipv4 interface"); for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i++) { if (ipv4->GetAddress (i).CombineMask(amask) == a.CombineMask(amask) ) @@ -48,17 +48,26 @@ GetIfIndexByIpv4Address (Ptr node, Ipv4Address a, Ipv4Mask amask) } } // Mapping not found - NS_ASSERT_MSG (false, "GetIfIndexByIpv4Address failed"); + NS_ASSERT_MSG (false, "Ipv4::GetIfIndexByAddress failed"); return 0; } +// +// XXX BUGBUG I don't think this is really the right approach here. The call +// to GetRoute () filters down into Ipv4L3Protocol where it translates into +// a call into the Ipv4 static routing package. This bypasses any other +// routing packages. At a minimum, the name is misleading. +// bool -GetIpv4RouteToDestination (Ptr node, Ipv4Route& route, - Ipv4Address a, Ipv4Mask amask) +Ipv4::GetRouteToDestination ( + Ptr node, + Ipv4Route& route, + Ipv4Address a, + Ipv4Mask amask) { Ipv4Route tempRoute; Ptr ipv4 = node->QueryInterface (Ipv4::iid); - NS_ASSERT_MSG (ipv4, "GetIpv4RouteToDestination: No Ipv4 interface"); + NS_ASSERT_MSG (ipv4, "Ipv4::GetRouteToDestination: No Ipv4 interface"); for (uint32_t i = 0; i < ipv4->GetNRoutes (); i++) { tempRoute = ipv4->GetRoute (i); @@ -83,5 +92,4 @@ GetIpv4RouteToDestination (Ptr node, Ipv4Route& route, return false; } - } // namespace ns3 diff --git a/src/node/ipv4.h b/src/node/ipv4.h index dc5e146bd..ba4868a4a 100644 --- a/src/node/ipv4.h +++ b/src/node/ipv4.h @@ -71,6 +71,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 @@ -100,9 +101,47 @@ 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; + +/** + * \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; + + static const uint32_t IF_INDEX_ANY = 0xffffffff; }; /** @@ -194,16 +233,68 @@ 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. */ 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; + /** + * \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. + */ + 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. @@ -214,49 +305,120 @@ 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. */ 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 */ 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 */ 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 destination The IP address of a hypothetical destination. + * \param ifIndex filled in with the interface index that will be used to + * send a packet to the hypothetical destination. + * \returns True if a single interface can be identified, false otherwise. + */ + virtual bool GetIfIndexForDestination (Ipv4Address dest, + uint32_t &ifIndex) 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 * @@ -264,6 +426,7 @@ public: * considered valid during ipv4 forwarding. */ virtual void SetUp (uint32_t i) = 0; + /** * \param i index of ipv4 interface * @@ -271,21 +434,18 @@ public: * ignored during ipv4 forwarding. */ virtual void SetDown (uint32_t i) = 0; - -}; /** * Convenience functions (Doxygen still needed) * * Return the ifIndex corresponding to the Ipv4Address provided. */ -uint32_t GetIfIndexByIpv4Address (Ptr node, - Ipv4Address a, - Ipv4Mask amask = Ipv4Mask("255.255.255.255")); + static uint32_t GetIfIndexByAddress (Ptr node, Ipv4Address a, + Ipv4Mask amask = Ipv4Mask("255.255.255.255")); -bool GetIpv4RouteToDestination (Ptr node, Ipv4Route& route, - Ipv4Address a, - Ipv4Mask amask = Ipv4Mask("255.255.255.255")); + static bool GetRouteToDestination (Ptr node, Ipv4Route& route, + Ipv4Address a, Ipv4Mask amask = Ipv4Mask("255.255.255.255")); +}; } // namespace ns3 diff --git a/src/node/net-device.cc b/src/node/net-device.cc index b47ce58a7..0e8223f60 100644 --- a/src/node/net-device.cc +++ b/src/node/net-device.cc @@ -114,6 +114,7 @@ NetDevice::IsBroadcast (void) const { return m_isBroadcast; } + Address const & NetDevice::GetBroadcast (void) const { @@ -140,10 +141,27 @@ NetDevice::IsMulticast (void) const return m_isMulticast; } +Address +NetDevice::GetMulticast (void) const +{ + 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; +} + void -NetDevice::EnableMulticast (void) +NetDevice::EnableMulticast (Address multicast) { m_isMulticast = true; + m_multicast = multicast; } void diff --git a/src/node/net-device.h b/src/node/net-device.h index 91f999d99..7c95d5b84 100644 --- a/src/node/net-device.h +++ b/src/node/net-device.h @@ -29,6 +29,7 @@ #include "ns3/object.h" #include "ns3/ptr.h" #include "address.h" +#include "ipv4-address.h" namespace ns3 { @@ -130,10 +131,69 @@ public: * not true. */ Address const &GetBroadcast (void) const; + /** * \return value of m_isMulticast flag */ bool IsMulticast (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 */ @@ -204,9 +264,10 @@ public: */ void DisableBroadcast (void); /** - * Set m_isMulticast flag to true + * Enable multicast support. This method should be + * called by subclasses from their constructor */ - void EnableMulticast (void); + void EnableMulticast (Address multicast); /** * Set m_isMulticast flag to false */ @@ -286,6 +347,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; diff --git a/src/routing/global-routing/candidate-queue.cc b/src/routing/global-routing/candidate-queue.cc index 67bec63b1..ffade0a31 100644 --- a/src/routing/global-routing/candidate-queue.cc +++ b/src/routing/global-routing/candidate-queue.cc @@ -1,5 +1,7 @@ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* + * Copyright 2007 University of Washington + * * 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; @@ -12,6 +14,8 @@ * 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: Craig Dowell (craigdo@ee.washington.edu) */ #include "ns3/debug.h" diff --git a/src/routing/global-routing/candidate-queue.h b/src/routing/global-routing/candidate-queue.h index 09b3a5c22..605ca40b2 100644 --- a/src/routing/global-routing/candidate-queue.h +++ b/src/routing/global-routing/candidate-queue.h @@ -1,5 +1,7 @@ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* + * Copyright 2007 University of Washington + * * 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; @@ -12,6 +14,8 @@ * 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: Craig Dowell (craigdo@ee.washington.edu) */ #ifndef CANDIDATE_QUEUE_H diff --git a/src/routing/global-routing/global-route-manager-impl.cc b/src/routing/global-routing/global-route-manager-impl.cc index 10f07ca85..951ead2aa 100644 --- a/src/routing/global-routing/global-route-manager-impl.cc +++ b/src/routing/global-routing/global-route-manager-impl.cc @@ -1,5 +1,8 @@ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* + * Copyright 2007 University of Washington + * Copyright (C) 1999, 2000 Kunihiro Ishiguro, Toshiaki Takada + * * 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; @@ -12,6 +15,12 @@ * 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 + * + * Authors: Craig Dowell (craigdo@ee.washington.edu) + * Tom Henderson (tomhend@u.washington.edu) + * + * Kunihiro Ishigura, Toshiaki Takada (GNU Zebra) are attributed authors + * of the quagga 0.99.7/src/ospfd/ospf_spf.c code which was ported here */ #include @@ -1143,7 +1152,7 @@ GlobalRouteManagerImpl::FindOutgoingInterfaceId (Ipv4Address a, Ipv4Mask amask) // we're looking for. If we find one, return the corresponding interface // index. // - return (GetIfIndexByIpv4Address (node, a, amask) ); + return (Ipv4::GetIfIndexByAddress (node, a, amask) ); } } // diff --git a/src/routing/global-routing/global-route-manager-impl.h b/src/routing/global-routing/global-route-manager-impl.h index 923caf400..55d4099f6 100644 --- a/src/routing/global-routing/global-route-manager-impl.h +++ b/src/routing/global-routing/global-route-manager-impl.h @@ -1,5 +1,7 @@ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* + * Copyright 2007 University of Washington + * * 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; @@ -12,6 +14,9 @@ * 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 + * + * Authors: Craig Dowell (craigdo@ee.washington.edu) + * Tom Henderson (tomhend@u.washington.edu) */ #ifndef GLOBAL_ROUTE_MANAGER_IMPL_H diff --git a/src/routing/global-routing/global-route-manager.cc b/src/routing/global-routing/global-route-manager.cc index c166da015..ed2d0bfef 100644 --- a/src/routing/global-routing/global-route-manager.cc +++ b/src/routing/global-routing/global-route-manager.cc @@ -1,5 +1,7 @@ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* + * Copyright 2007 University of Washington + * * 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; @@ -12,6 +14,9 @@ * 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 + * + * Authors: Craig Dowell (craigdo@ee.washington.edu) + * Tom Henderson (tomhend@u.washington.edu) */ #include "ns3/assert.h" diff --git a/src/routing/global-routing/global-route-manager.h b/src/routing/global-routing/global-route-manager.h index 7562da67d..333aff78c 100644 --- a/src/routing/global-routing/global-route-manager.h +++ b/src/routing/global-routing/global-route-manager.h @@ -1,5 +1,7 @@ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* + * Copyright 2007 University of Washington + * * 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; @@ -12,6 +14,9 @@ * 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 + * + * Authors: Craig Dowell (craigdo@ee.washington.edu) + * Tom Henderson (tomhend@u.washington.edu) */ #ifndef GLOBAL_ROUTE_MANAGER_H diff --git a/src/routing/global-routing/global-router-interface.cc b/src/routing/global-routing/global-router-interface.cc index c057f9ddf..bf1b68a29 100644 --- a/src/routing/global-routing/global-router-interface.cc +++ b/src/routing/global-routing/global-router-interface.cc @@ -1,5 +1,7 @@ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* + * Copyright 2007 University of Washington + * * 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; @@ -12,6 +14,9 @@ * 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 + * + * Authors: Craig Dowell (craigdo@ee.washington.edu) + * Tom Henderson (tomhend@u.washington.edu) */ #include "ns3/debug.h" diff --git a/src/routing/global-routing/global-router-interface.h b/src/routing/global-routing/global-router-interface.h index b6558eb20..cf3f94166 100644 --- a/src/routing/global-routing/global-router-interface.h +++ b/src/routing/global-routing/global-router-interface.h @@ -1,5 +1,7 @@ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* + * Copyright 2007 University of Washington + * * 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; @@ -12,6 +14,9 @@ * 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 + * + * Authors: Craig Dowell (craigdo@ee.washington.edu) + * Tom Henderson (tomhend@u.washington.edu) */ #ifndef GLOBAL_ROUTER_INTERFACE_H