untested multicast support
authorCraig Dowell <craigdo@ee.washington.edu>
Sun, 12 Aug 2007 13:59:49 -0700
changeset 1428 a8f3d01d4a2c
parent 1277 c26bf0511078
child 1429 31cb0668defd
untested multicast support
examples/csma-multicast.cc
examples/wscript
src/internet-node/ipv4-impl.cc
src/internet-node/ipv4-impl.h
src/internet-node/ipv4-l3-protocol.cc
src/internet-node/ipv4-l3-protocol.h
src/internet-node/ipv4-static-routing.cc
src/internet-node/ipv4-static-routing.h
src/node/ipv4-route.cc
src/node/ipv4-route.h
src/node/ipv4.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/csma-multicast.cc	Sun Aug 12 13:59:49 2007 -0700
@@ -0,0 +1,173 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+// Network topology
+//
+//       n0    n1   n2   n3
+//       |     |    |    |
+//     =====================
+//
+// - CBR/UDP flows from n0 to n1, and from n3 to n0
+// - UDP packet size of 210 bytes, with per-packet interval 0.00375 sec.
+//   (i.e., DataRate of 448,000 bps)
+// - DropTail queues 
+// - Tracing of queues and packet receptions to file "csma-one-subnet.tr"
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cassert>
+
+#include "ns3/command-line.h"
+#include "ns3/default-value.h"
+#include "ns3/ptr.h"
+#include "ns3/random-variable.h"
+#include "ns3/debug.h"
+
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/data-rate.h"
+
+#include "ns3/ascii-trace.h"
+#include "ns3/pcap-trace.h"
+#include "ns3/internet-node.h"
+#include "ns3/csma-channel.h"
+#include "ns3/csma-net-device.h"
+#include "ns3/csma-topology.h"
+#include "ns3/csma-ipv4-topology.h"
+#include "ns3/eui48-address.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/ipv4.h"
+#include "ns3/socket.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/onoff-application.h"
+
+using namespace ns3;
+
+int 
+main (int argc, char *argv[])
+{
+  // Users may find it convenient to turn on explicit debugging
+  // for selected modules; the below lines suggest how to do this
+#if 0 
+  DebugComponentEnable("CsmaNetDevice");
+  DebugComponentEnable("Ipv4L3Protocol");
+  DebugComponentEnable("NetDevice");
+  DebugComponentEnable("Channel");
+  DebugComponentEnable("CsmaChannel");
+  DebugComponentEnable("PacketSocket");
+#endif
+
+  // Set up some default values for the simulation.  Use the Bind()
+  // technique to tell the system what subclass of Queue to use,
+  // and what the queue limit is
+
+  // The below Bind command tells the queue factory which class to
+  // instantiate, when the queue factory is invoked in the topology code
+  DefaultValue::Bind ("Queue", "DropTailQueue");
+
+  // Allow the user to override any of the defaults and the above
+  // Bind()s at run-time, via command-line arguments
+  CommandLine::Parse (argc, argv);
+
+  // Here, we will explicitly create four nodes.  In more sophisticated
+  // topologies, we could configure a node factory.
+  Ptr<Node> n0 = Create<InternetNode> ();
+  Ptr<Node> n1 = Create<InternetNode> (); 
+  Ptr<Node> n2 = Create<InternetNode> (); 
+  Ptr<Node> n3 = Create<InternetNode> ();
+
+  // We create the channels first without any IP addressing information
+  Ptr<CsmaChannel> channel0 = 
+    CsmaTopology::CreateCsmaChannel(
+      DataRate(5000000), MilliSeconds(2));
+
+  uint32_t n0ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n0, channel0, 
+                                         Eui48Address("10:54:23:54:23:50"));
+  uint32_t n1ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n1, channel0,
+                                         Eui48Address("10:54:23:54:23:51"));
+  uint32_t n2ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n2, channel0,
+                                         Eui48Address("10:54:23:54:23:52"));
+  uint32_t n3ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n3, channel0,
+                                         Eui48Address("10:54:23:54:23:53"));
+
+  // Later, we add IP addresses.  
+  CsmaIpv4Topology::AddIpv4Address (
+      n0, n0ifIndex, Ipv4Address("10.1.1.1"), Ipv4Mask("255.255.255.0"));
+
+  CsmaIpv4Topology::AddIpv4Address (
+      n1, n1ifIndex, Ipv4Address("10.1.1.2"), Ipv4Mask("255.255.255.0"));
+
+  CsmaIpv4Topology::AddIpv4Address (
+      n2, n2ifIndex, Ipv4Address("10.1.1.3"), Ipv4Mask("255.255.255.0"));
+  
+  CsmaIpv4Topology::AddIpv4Address (
+      n3, n3ifIndex, Ipv4Address("10.1.1.4"), Ipv4Mask("255.255.255.0"));
+
+  // Configure multicasting
+  Ipv4Address multicastSource ("10.1.1.1");
+  Ipv4Address multicastGroup ("225.0.0.0");
+
+  Ptr<Ipv4> ipv4;
+  ipv4 = n0->QueryInterface<Ipv4> (Ipv4::iid);
+
+  std::vector<uint32_t> outputInterfaces (1);
+  outputInterfaces[0] = n0ifIndex;
+
+  ipv4->AddMulticastRoute (multicastSource, multicastGroup, 0, 
+    outputInterfaces);
+
+  ipv4 = n1->QueryInterface<Ipv4> (Ipv4::iid);
+  ipv4->JoinMulticastGroup (multicastSource, multicastGroup);
+
+  ipv4 = n2->QueryInterface<Ipv4> (Ipv4::iid);
+  ipv4->JoinMulticastGroup (multicastSource, multicastGroup);
+
+  ipv4 = n3->QueryInterface<Ipv4> (Ipv4::iid);
+  ipv4->JoinMulticastGroup (multicastSource, multicastGroup);
+
+  // Create the OnOff application to send UDP datagrams of size
+  // 210 bytes at a rate of 448 Kb/s
+  // from n0 to n1
+  Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
+    n0, 
+    InetSocketAddress (multicastGroup, 80), 
+    "Udp",
+    ConstantVariable(1), 
+    ConstantVariable(0));
+  // Start the application
+  ooff->Start(Seconds(1.0));
+  ooff->Stop (Seconds(10.0));
+
+  // Configure tracing of all enqueue, dequeue, and NetDevice receive events
+  // Trace output will be sent to the csma-one-subnet.tr file
+  AsciiTrace asciitrace ("csma-one-subnet.tr");
+  asciitrace.TraceAllNetDeviceRx ();
+  asciitrace.TraceAllQueues ();
+
+  // Also configure some tcpdump traces; each interface will be traced
+  // The output files will be named 
+  // simple-point-to-point.pcap-<nodeId>-<interfaceId>
+  // and can be read by the "tcpdump -r" command (use "-tt" option to
+  // display timestamps correctly)
+  PcapTrace pcaptrace ("csma-one-subnet.pcap");
+  pcaptrace.TraceAllIp ();
+
+  Simulator::Run ();
+    
+  Simulator::Destroy ();
+}
--- a/examples/wscript	Fri Aug 10 13:49:41 2007 -0700
+++ b/examples/wscript	Sun Aug 12 13:59:49 2007 -0700
@@ -17,3 +17,8 @@
     obj = bld.create_ns3_program('csma-packet-socket',
         ['csma', 'internet-node'])
     obj.source = 'csma-packet-socket.cc'
+
+    obj = bld.create_ns3_program('csma-multicast',
+        ['csma', 'internet-node'])
+    obj.source = 'csma-multicast.cc'
+
--- a/src/internet-node/ipv4-impl.cc	Fri Aug 10 13:49:41 2007 -0700
+++ b/src/internet-node/ipv4-impl.cc	Sun Aug 12 13:59:49 2007 -0700
@@ -95,6 +95,42 @@
 {
   return m_ipv4->RemoveRoute (i);
 }
+
+void
+Ipv4Impl::AddMulticastRoute (Ipv4Address origin,
+                             Ipv4Address group,
+                             uint32_t inputInterface,
+                             std::vector<uint32_t> outputInterfaces)
+{
+  m_ipv4->AddMulticastRoute (origin, group, inputInterface, outputInterfaces);
+}
+
+uint32_t 
+Ipv4Impl::GetNMulticastRoutes (void) const
+{
+  return m_ipv4->GetNMulticastRoutes ();
+}
+
+Ipv4MulticastRoute 
+Ipv4Impl::GetMulticastRoute (uint32_t i) const
+{
+  return *m_ipv4->GetMulticastRoute (i);
+}
+
+void
+Ipv4Impl::RemoveMulticastRoute (Ipv4Address origin,
+                                Ipv4Address group,
+                                uint32_t inputInterface)
+{
+  m_ipv4->RemoveMulticastRoute (origin, group, inputInterface);
+}
+
+void 
+Ipv4Impl::RemoveMulticastRoute (uint32_t i)
+{
+  return m_ipv4->RemoveMulticastRoute (i);
+}
+
 uint32_t 
 Ipv4Impl::AddInterface (Ptr<NetDevice> device)
 {
@@ -112,6 +148,18 @@
 }
 
 void 
+Ipv4Impl::JoinMulticastGroup (Ipv4Address origin, Ipv4Address group)
+{
+  m_ipv4->JoinMulticastGroup(origin, group);
+}
+
+void
+Ipv4Impl::LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group)
+{
+  m_ipv4->LeaveMulticastGroup(origin, group);
+}
+
+void 
 Ipv4Impl::SetAddress (uint32_t i, Ipv4Address address)
 {
   m_ipv4->SetAddress (i, address);
--- a/src/internet-node/ipv4-impl.h	Fri Aug 10 13:49:41 2007 -0700
+++ b/src/internet-node/ipv4-impl.h	Sun Aug 12 13:59:49 2007 -0700
@@ -55,10 +55,28 @@
   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<uint32_t> outputInterfaces);
+
+  virtual uint32_t GetNMulticastRoutes (void) const;
+  virtual Ipv4MulticastRoute GetMulticastRoute (uint32_t i) const;
+
+  virtual void RemoveMulticastRoute (Ipv4Address origin,
+                                     Ipv4Address group,
+                                     uint32_t inputInterface);
+  virtual void RemoveMulticastRoute (uint32_t i);
+
   virtual uint32_t AddInterface (Ptr<NetDevice> device);
   virtual uint32_t GetNInterfaces (void);  
   virtual Ptr<NetDevice> 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;
--- a/src/internet-node/ipv4-l3-protocol.cc	Fri Aug 10 13:49:41 2007 -0700
+++ b/src/internet-node/ipv4-l3-protocol.cc	Sun Aug 12 13:59:49 2007 -0700
@@ -17,6 +17,7 @@
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 //
 // Author: George F. Riley<riley@ece.gatech.edu>
+//         Craig Dowell <craigdo@ee.washington.edu>
 //
 
 #include "ns3/packet.h"
@@ -131,7 +132,8 @@
 void 
 Ipv4L3Protocol::DoDispose (void)
 {
-  for (Ipv4InterfaceList::iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
+  for (Ipv4InterfaceList::iterator i = m_interfaces.begin (); 
+       i != m_interfaces.end (); i++)
     {
       delete (*i);
     }
@@ -224,12 +226,15 @@
                         Packet packet,
                         Ipv4RoutingProtocol::RouteReplyCallback routeReply)
 {
-  for (Ipv4RoutingProtocolList::const_iterator rprotoIter = m_routingProtocols.begin ();
-       rprotoIter != m_routingProtocols.end (); rprotoIter++)
+  for (Ipv4RoutingProtocolList::const_iterator rprotoIter = 
+         m_routingProtocols.begin ();
+       rprotoIter != m_routingProtocols.end (); 
+       rprotoIter++)
     {
       if ((*rprotoIter).second->RequestRoute (ipHeader, packet, routeReply))
         return;
     }
+
   // No route found
   routeReply (false, Ipv4Route (), packet, ipHeader);
 }
@@ -261,6 +266,41 @@
   m_staticRouting->RemoveRoute (index);
 }
 
+void 
+Ipv4L3Protocol::AddMulticastRoute (Ipv4Address origin,
+                                   Ipv4Address group,
+                                   uint32_t inputInterface,
+                                   std::vector<uint32_t> outputInterfaces)
+{
+  m_staticRouting->AddMulticastRoute (origin, group, inputInterface,
+    outputInterfaces);
+}
+
+uint32_t 
+Ipv4L3Protocol::GetNMulticastRoutes (void) const
+{
+  return m_staticRouting->GetNMulticastRoutes ();
+}
+
+Ipv4MulticastRoute *
+Ipv4L3Protocol::GetMulticastRoute (uint32_t index) const
+{
+  return m_staticRouting->GetMulticastRoute (index);
+}
+
+void 
+Ipv4L3Protocol::RemoveMulticastRoute (Ipv4Address origin,
+                                       Ipv4Address group,
+                                       uint32_t inputInterface)
+{
+  m_staticRouting->RemoveMulticastRoute (origin, group, inputInterface);
+}
+
+void 
+Ipv4L3Protocol::RemoveMulticastRoute (uint32_t index)
+{
+  m_staticRouting->RemoveMulticastRoute (index);
+}
 
 uint32_t 
 Ipv4L3Protocol::AddInterface (Ptr<NetDevice> device)
@@ -463,13 +503,29 @@
     }
   ipHeader.SetTtl (ipHeader.GetTtl () - 1);
 
-  NS_DEBUG ("not for me -- forwarding.");
+  NS_DEBUG ("forwarding.");
   Lookup (ipHeader, packet,
           MakeCallback (&Ipv4L3Protocol::SendRealOut, this));
+//
+// If this is a to a multicast address and this node is a member of the 
+// indicated group we need to return false so the multicast is forwarded up.
+// Note that we may have just forwarded this packet too.
+//
+  for (Ipv4MulticastGroupList::const_iterator i = m_multicastGroups.begin ();
+       i != m_multicastGroups.end (); i++) 
+    {
+      if ((*i).first.IsEqual (ipHeader.GetSource ()) &&
+          (*i).second.IsEqual (ipHeader.GetDestination ()))
+        {
+          NS_DEBUG ("for me 5");
+          return false;
+        }
+    }
+  
+  NS_DEBUG ("not for me.");
   return true;
 }
 
-
 void
 Ipv4L3Protocol::ForwardUp (Packet p, Ipv4Header const&ip)
 {
@@ -479,6 +535,28 @@
 }
 
 void 
+Ipv4L3Protocol::JoinMulticastGroup (Ipv4Address origin, Ipv4Address group)
+{
+  m_multicastGroups.push_back(
+    std::pair<Ipv4Address, Ipv4Address> (origin, group));
+}
+
+void
+Ipv4L3Protocol::LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group)
+{
+  for (Ipv4MulticastGroupList::iterator i = m_multicastGroups.begin ();
+       i != m_multicastGroups.end (); 
+       i++)
+    {
+      if ((*i).first.IsEqual(origin) && (*i).second.IsEqual(group))
+        {
+          m_multicastGroups.erase (i);
+          return;
+        }
+    }
+}
+
+void 
 Ipv4L3Protocol::SetAddress (uint32_t i, Ipv4Address address)
 {
   Ipv4Interface *interface = GetInterface (i);
--- a/src/internet-node/ipv4-l3-protocol.h	Fri Aug 10 13:49:41 2007 -0700
+++ b/src/internet-node/ipv4-l3-protocol.h	Sun Aug 12 13:59:49 2007 -0700
@@ -158,11 +158,26 @@
   Ipv4Route *GetRoute (uint32_t i);
   void RemoveRoute (uint32_t i);
 
+  void AddMulticastRoute (Ipv4Address origin,
+                          Ipv4Address group,
+                          uint32_t inputInterface,
+                          std::vector<uint32_t> outputInterfaces);
+
+  uint32_t GetNMulticastRoutes (void) const;
+  Ipv4MulticastRoute *GetMulticastRoute (uint32_t i) const;
+
+  void RemoveMulticastRoute (Ipv4Address origin,
+                             Ipv4Address group,
+                             uint32_t inputInterface);
+  void RemoveMulticastRoute (uint32_t i);
+
   uint32_t AddInterface (Ptr<NetDevice> device);
   Ipv4Interface * GetInterface (uint32_t i) const;
   uint32_t GetNInterfaces (void) const;
+  
+  virtual void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group);
+  virtual void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group);
 
-  
   void SetAddress (uint32_t i, Ipv4Address address);
   void SetNetworkMask (uint32_t i, Ipv4Mask mask);
   Ipv4Mask GetNetworkMask (uint32_t t) const;
@@ -192,7 +207,10 @@
   TraceResolver *InterfacesCreateTraceResolver (TraceContext const &context) const;
 
   typedef std::list<Ipv4Interface*> Ipv4InterfaceList;
-  typedef std::list< std::pair< int, Ptr<Ipv4RoutingProtocol> > > Ipv4RoutingProtocolList;
+  typedef std::list<std::pair<Ipv4Address, Ipv4Address> > 
+    Ipv4MulticastGroupList;
+  typedef std::list<std::pair< int, Ptr<Ipv4RoutingProtocol> > > 
+    Ipv4RoutingProtocolList;
 
   Ipv4InterfaceList m_interfaces;
   uint32_t m_nInterfaces;
@@ -206,6 +224,7 @@
   Ipv4RoutingProtocolList m_routingProtocols;
 
   Ptr<Ipv4StaticRouting> m_staticRouting;
+  Ipv4MulticastGroupList m_multicastGroups;
 };
 
 } // Namespace ns3
--- a/src/internet-node/ipv4-static-routing.cc	Fri Aug 10 13:49:41 2007 -0700
+++ b/src/internet-node/ipv4-static-routing.cc	Sun Aug 12 13:59:49 2007 -0700
@@ -18,11 +18,11 @@
 //
 // Author: George F. Riley<riley@ece.gatech.edu>
 //         Gustavo Carneiro <gjc@inescporto.pt>
+//         Craig Dowell <craigdo@ee.washington.edu>
 
 #include "ipv4-static-routing.h"
 #include "ns3/packet.h"
 
-
 namespace ns3 {
 
 
@@ -77,6 +77,83 @@
   m_defaultRoute = route;
 }
 
+void 
+Ipv4StaticRouting::AddMulticastRoute(Ipv4Address origin,
+                                     Ipv4Address group,
+                                     uint32_t inputInterface,
+                                     std::vector<uint32_t> outputInterfaces)
+{
+  Ipv4MulticastRoute *route = new Ipv4MulticastRoute ();
+  *route = Ipv4MulticastRoute::CreateMulticastRoute (origin, group, 
+    inputInterface, outputInterfaces);
+  m_multicastRoutes.push_back (route);
+}
+
+uint32_t 
+Ipv4StaticRouting::GetNMulticastRoutes (void) const
+{
+  return m_multicastRoutes.size ();
+}
+
+Ipv4MulticastRoute *
+Ipv4StaticRouting::GetMulticastRoute (uint32_t index) const
+{
+  NS_ASSERT_MSG(index < m_multicastRoutes.size (),
+    "Ipv4StaticRouting::GetMulticastRoute ():  Index out of range");
+
+  uint32_t tmp = 0;
+  for (MulticastRoutesCI i = m_multicastRoutes.begin (); 
+       i != m_multicastRoutes.end (); 
+       i++) 
+    {
+      if (tmp  == index)
+        {
+          return *i;
+        }
+      tmp++;
+    }
+  return 0;
+}
+
+void 
+Ipv4StaticRouting::RemoveMulticastRoute(Ipv4Address origin,
+                                        Ipv4Address group,
+                                        uint32_t inputInterface)
+{
+  for (MulticastRoutesI i = m_multicastRoutes.begin (); 
+       i != m_multicastRoutes.end (); 
+       i++) 
+    {
+      Ipv4MulticastRoute *route = *i;
+      if (origin == route->GetOrigin () &&
+          group == route->GetGroup () &&
+          inputInterface == route->GetInputInterface ())
+        {
+          delete *i;
+          m_multicastRoutes.erase (i);
+          return;
+        }
+    }
+}
+
+void 
+Ipv4StaticRouting::RemoveMulticastRoute(uint32_t index)
+{
+  uint32_t tmp = 0;
+  for (MulticastRoutesI i = m_multicastRoutes.begin (); 
+       i != m_multicastRoutes.end (); 
+       i++) 
+    {
+      if (tmp  == index)
+        {
+          delete *i;
+          m_multicastRoutes.erase (i);
+          return;
+        }
+      tmp++;
+    }
+}
+
 Ipv4Route *
 Ipv4StaticRouting::LookupStatic (Ipv4Address dest)
 {
@@ -110,6 +187,25 @@
   return 0;
 }
 
+Ipv4MulticastRoute *
+Ipv4StaticRouting::LookupStatic (
+  Ipv4Address origin, 
+  Ipv4Address group)
+{
+  for (MulticastRoutesI i = m_multicastRoutes.begin (); 
+       i != m_multicastRoutes.end (); 
+       i++) 
+    {
+      Ipv4MulticastRoute *route = *i;
+      if (origin == route->GetOrigin () &&
+          group == route->GetGroup ())
+        {
+          return *i;
+        }
+    }
+  return 0;
+}
+
 uint32_t 
 Ipv4StaticRouting::GetNRoutes (void)
 {
@@ -213,6 +309,27 @@
                                  Packet packet,
                                  RouteReplyCallback routeReply)
 {
+//
+// First, see if this is a multicast packet we have a route for.  If we
+// have a route, then send the packet down each of the specified interfaces.
+//
+  Ipv4MulticastRoute *mRoute = LookupStatic(ipHeader.GetSource (),
+                                            ipHeader.GetDestination ());
+  if (mRoute)
+    {
+      for (uint32_t i = 0; i < mRoute->GetNOutputInterfaces (); ++i)
+        {
+          Packet p = packet;
+          Ipv4Route route = 
+            Ipv4Route::CreateHostRouteTo(ipHeader.GetDestination (), 
+              mRoute->GetOutputInterface(i));
+          routeReply (true, route, p, ipHeader);
+          return true;
+        }
+    }
+//
+// See if this is a unicast packet we have a route for.
+//
   Ipv4Route *route = LookupStatic (ipHeader.GetDestination ());
   if (route != 0)
     {
@@ -246,8 +363,13 @@
       delete m_defaultRoute;
       m_defaultRoute = 0;
     }
+  for (MulticastRoutesI i = m_multicastRoutes.begin (); 
+       i != m_multicastRoutes.end (); 
+       i = m_multicastRoutes.erase (i)) 
+    {
+      delete (*i);
+    }
   Ipv4RoutingProtocol::DoDispose ();
 }
 
-
 }//namespace ns3
--- a/src/internet-node/ipv4-static-routing.h	Fri Aug 10 13:49:41 2007 -0700
+++ b/src/internet-node/ipv4-static-routing.h	Sun Aug 12 13:59:49 2007 -0700
@@ -75,6 +75,20 @@
   Ipv4Route *GetRoute (uint32_t i);
   void RemoveRoute (uint32_t i);
 
+  void AddMulticastRoute (Ipv4Address origin,
+                          Ipv4Address group,
+                          uint32_t inputInterface,
+                          std::vector<uint32_t> outputInterfaces);
+
+  uint32_t GetNMulticastRoutes (void) const;
+  Ipv4MulticastRoute *GetMulticastRoute (uint32_t i) const;
+
+  void RemoveMulticastRoute (Ipv4Address origin,
+                             Ipv4Address group,
+                             uint32_t inputInterface);
+
+  void RemoveMulticastRoute (uint32_t index);
+
 protected:
   void DoDispose (void);
 
@@ -86,15 +100,19 @@
   typedef std::list<Ipv4Route *>::const_iterator NetworkRoutesCI;
   typedef std::list<Ipv4Route *>::iterator NetworkRoutesI;
 
+  typedef std::list<Ipv4MulticastRoute *> MulticastRoutes;
+  typedef std::list<Ipv4MulticastRoute *>::const_iterator MulticastRoutesCI;
+  typedef std::list<Ipv4MulticastRoute *>::iterator MulticastRoutesI;
+
   Ipv4Route *LookupStatic (Ipv4Address dest);
+  Ipv4MulticastRoute *LookupStatic (Ipv4Address origin, Ipv4Address group);
 
   HostRoutes m_hostRoutes;
   NetworkRoutes m_networkRoutes;
   Ipv4Route *m_defaultRoute;
+  MulticastRoutes m_multicastRoutes;
 };
 
-
-
 } // Namespace ns3
 
 #endif /* IPV4_STATIC_ROUTING_H */
--- a/src/node/ipv4-route.cc	Fri Aug 10 13:49:41 2007 -0700
+++ b/src/node/ipv4-route.cc	Sun Aug 12 13:59:49 2007 -0700
@@ -137,7 +137,6 @@
   return m_interface;
 }
 
-
 Ipv4Route 
 Ipv4Route::CreateHostRouteTo (Ipv4Address dest, 
 			      Ipv4Address nextHop, 
@@ -220,4 +219,99 @@
   return os;
 }
 
+/*****************************************************
+ *     Ipv4MulticastRoute
+ *****************************************************/
+
+Ipv4MulticastRoute::Ipv4MulticastRoute ()
+{
+}
+
+Ipv4MulticastRoute::Ipv4MulticastRoute (Ipv4MulticastRoute const &route)
+: 
+  m_origin (route.m_origin),
+  m_group (route.m_group),
+  m_inputInterface (route.m_inputInterface),
+  m_outputInterfaces (route.m_outputInterfaces)
+{
+}
+
+Ipv4MulticastRoute::Ipv4MulticastRoute (
+  Ipv4Address origin, 
+  Ipv4Address group, 
+  uint32_t inputInterface, 
+  std::vector<uint32_t> 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<uint32_t>
+Ipv4MulticastRoute::GetOutputInterfaces (void) const
+{
+  return m_outputInterfaces;
+}
+
+Ipv4MulticastRoute 
+Ipv4MulticastRoute::CreateMulticastRoute (
+  Ipv4Address origin, 
+  Ipv4Address group, 
+  uint32_t inputInterface,
+  std::vector<uint32_t> 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
--- a/src/node/ipv4-route.h	Fri Aug 10 13:49:41 2007 -0700
+++ b/src/node/ipv4-route.h	Sun Aug 12 13:59:49 2007 -0700
@@ -22,6 +22,7 @@
 #define IPV4_ROUTE_H
 
 #include <list>
+#include <vector>
 #include <ostream>
 
 #include "ipv4-address.h"
@@ -98,6 +99,67 @@
 
 std::ostream& operator<< (std::ostream& os, Ipv4Route const& route);
 
+/**
+ * \brief A record of an IPv4 multicast route
+ */
+class Ipv4MulticastRoute {
+public:
+  /**
+   * \brief This constructor does nothing
+   */
+  Ipv4MulticastRoute ();
+  /**
+   * \brief Copy Constructor
+   * \param route The route to copy
+   */
+  Ipv4MulticastRoute (Ipv4MulticastRoute const &route);
+
+  /**
+   * \return The IPv4 address of the source of this route
+   */
+  Ipv4Address GetOrigin (void) const;
+
+  /**
+   * \return The IPv4 address of the multicast group of this route
+   */
+  Ipv4Address GetGroup (void) const;
+
+  /**
+   * \return The IPv4 address of the input interface of this route
+   */
+  uint32_t GetInputInterface (void) const;
+
+  /**
+   * \return The number of output interfaces of this route
+   */
+  uint32_t GetNOutputInterfaces (void) const;
+
+  /**
+   * \return A specified output interface.
+   */
+  uint32_t GetOutputInterface (uint32_t n) const;
+
+  /**
+   * \return A vector of all of the output interfaces of this route.
+   */
+  std::vector<uint32_t> GetOutputInterfaces (void) const;
+
+  static Ipv4MulticastRoute CreateMulticastRoute (Ipv4Address origin, 
+    Ipv4Address group, uint32_t inputInterface,
+    std::vector<uint32_t> outputInterfaces);
+
+private:
+  Ipv4MulticastRoute (Ipv4Address origin, Ipv4Address group, 
+    uint32_t inputInterface, std::vector<uint32_t> outputInterfaces);
+
+  Ipv4Address m_origin;
+  Ipv4Address m_group;
+  uint32_t m_inputInterface;
+  std::vector<uint32_t> m_outputInterfaces;
+};
+
+std::ostream& operator<< (std::ostream& os, Ipv4MulticastRoute const& route);
+
 }//namespace ns3
 
 #endif /* IPV4_ROUTE_H */
--- a/src/node/ipv4.h	Fri Aug 10 13:49:41 2007 -0700
+++ b/src/node/ipv4.h	Sun Aug 12 13:59:49 2007 -0700
@@ -202,8 +202,50 @@
    * \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<uint32_t> outputInterfaces) = 0;
+  /**
+   * \brief Remove a static multicast route for a given multicast source and
+   *        group.
+   *
+   * \param origin The Ipv4 address of the multicast source.
+   * \param group The multicast group address.
+   * \param inputInterface The interface index over which the packet arrived.
+   */
+  virtual void RemoveMulticastRoute (Ipv4Address origin,
+                                     Ipv4Address group,
+                                     uint32_t inputInterface) = 0;
   
   /**
+   * \returns the number of entries in the multicast routing table.
+   */
+  virtual uint32_t GetNMulticastRoutes (void) const = 0;
+
+  /**
+   * \param i index of route to return
+   * \returns the route whose index is i
+   */
+  virtual Ipv4MulticastRoute GetMulticastRoute (uint32_t i) const = 0;
+
+  /**
+   * \param i index of route to remove from routing table.
+   */
+  virtual void RemoveMulticastRoute (uint32_t i) = 0;
+
+  /**
    * \param device device to add to the list of ipv4 interfaces
    *        which can be used as output interfaces during packet forwarding.
    * \returns the index of the ipv4 interface added.
@@ -225,6 +267,24 @@
   virtual Ptr<NetDevice> 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
    */