clarify use of wildcards in multicast routes versus default mulicast routes.
authorCraig Dowell <craigdo@ee.washington.edu>
Tue, 04 Sep 2007 18:06:06 -0700
changeset 1446 f9bc98cbe5fe
parent 1445 3fba36666488
child 1447 f136fc719267
clarify use of wildcards in multicast routes versus default mulicast routes.
examples/csma-multicast.cc
src/internet-node/ipv4-static-routing.cc
src/internet-node/ipv4-static-routing.h
--- a/examples/csma-multicast.cc	Tue Sep 04 15:10:47 2007 -0700
+++ b/examples/csma-multicast.cc	Tue Sep 04 18:06:06 2007 -0700
@@ -221,8 +221,8 @@
   Ptr<Ipv4> ipv4;
   ipv4 = n2->QueryInterface<Ipv4> (Ipv4::iid);
 
-  uint32_t ifIndexLan0 = ipv4->FindInterfaceForAddr(n2Lan0Addr);
-  uint32_t ifIndexLan1 = ipv4->FindInterfaceForAddr(n2Lan1Addr);
+  uint32_t ifIndexLan0 = ipv4->FindInterfaceForAddr (n2Lan0Addr);
+  uint32_t ifIndexLan1 = ipv4->FindInterfaceForAddr (n2Lan1Addr);
 //
 // Now, we need to do is to call the AddMulticastRoute () method on node 
 // two's Ipv4 interface and tell it that whenever it receives a packet on
@@ -238,6 +238,41 @@
   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> (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.
--- a/src/internet-node/ipv4-static-routing.cc	Tue Sep 04 15:10:47 2007 -0700
+++ b/src/internet-node/ipv4-static-routing.cc	Tue Sep 04 18:06:06 2007 -0700
@@ -289,14 +289,27 @@
   Ipv4Address group,
   uint32_t    ifIndex)
 {
+//
+// We treat the "any" address (typically 0.0.0.0) as a wildcard in our matching
+// scheme.
+//
+  Ipv4Address wildcard = Ipv4Address::GetAny ();
+
   for (MulticastRoutesI i = m_multicastRoutes.begin (); 
        i != m_multicastRoutes.end (); 
        i++) 
     {
       Ipv4MulticastRoute *route = *i;
-      if (  (origin == route->GetOrigin () || 
-             origin == Ipv4Address::GetAny ()) &&
-          group == route->GetGroup ())
+//
+// We've been passed an origin address, a multicast group address and an 
+// interface index.  We have to decide if the current route in the list is
+// a match.
+//
+// The first case is the restrictive case where the origin, group and index
+// matches.  This picks up exact routes during forwarded and exact routes from
+// the local node (in which case the ifIndex is a wildcard).
+//
+      if (origin == route->GetOrigin () && group == route->GetGroup ())
         {
           if (ifIndex == Ipv4RoutingProtocol::IF_INDEX_ANY || 
               ifIndex == route->GetInputInterface ())
@@ -305,7 +318,67 @@
             }
         }
     }
+//
+// If the input interface index is not a wildcard (that means that the packet 
+// did not originally come from this node), we're done.  We don't
+// just happily forward packets we don't really know what to do with.  
+// Multicast storms are not generally considered a good thing.
+//
+  if (ifIndex != Ipv4RoutingProtocol::IF_INDEX_ANY)
+    {
+      return 0;
+    }
+//
+// Now, we're going to get a litle less restricive.  This only applies in the
+// case where the packet in question is coming from the local node.  In order
+// to avoid dependencies on the order in which routes were added, we will 
+// actually walk the list two more times, the first time looking for routes
+// with a single wildcard, and the last time looking for the first route
+// with two wildcards.
+//
+  for (MulticastRoutesI i = m_multicastRoutes.begin (); 
+       i != m_multicastRoutes.end (); 
+       i++) 
+    {
+      Ipv4MulticastRoute *route = *i;
+//
+// Here we will ignore the origin.  We know that a single source address must
+// be picked for a packet, but we may want to send multicast packets out
+// multiple interfaces.  To support this case, a user would need to add
+// a Multicast route with the route's origin set to wildcard.  N.B As a
+// result, packets sourced from a node with multiple interface may have a
+// source IP address different from that of the interface actually used to
+// send the packet.
+//
+      if (route->GetOrigin () == wildcard && group == route->GetGroup ())
+        {
+          return *i;
+        }
+    }
+//
+// Finally we want to allow users to specify a default route that specifies
+// sending all multicast packets out multiple interfaces.  The standard
+// default multicast route is patterned after other systems and limits the 
+// number of outputs to one.  If, however a client manually adds a multicast
+// route with the origin, the multicast group and the input interface index
+// all set to wildcard, she has created a default route with multiple output
+// interfaces.
+//
+  for (MulticastRoutesI i = m_multicastRoutes.begin (); 
+       i != m_multicastRoutes.end (); 
+       i++) 
+    {
+      Ipv4MulticastRoute *route = *i;
 
+      if (route->GetOrigin () == wildcard && route->GetGroup () == wildcard)
+        {
+          return *i;
+        }
+    }
+//
+// We also allow users to specify a typical default multicast route.  This
+// default route is limited to specifying a single output interface.
+//
   if (m_defaultMulticastRoute != 0) 
     {
       return m_defaultMulticastRoute;
@@ -445,33 +518,7 @@
   if (ipHeader.GetDestination ().IsMulticast ())
     {
       NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): Multicast destination");
-//
-// We have a multicast packet we're going to send.  There are two distinct
-// cases we need to support.  The first is if the current node is the source
-// of the packet.  In that case, we don't want to have to consult multicast
-// routing tables (nor build them) in order to send multicasts.  The interface
-// index (ifIndex) is Ipv4RoutingProtocol::IF_INDEX_ANY if we're the source.
-//
-// The second case is if the current packet has gotten to us by being
-// received over one of our interfaces.  In this case, ifIndex is set to the
-// index over which we received the packet.  For these packets, we need to
-// consult the multicast routing table for a disposition.
-//
-// So, first let's see if we're the source.  In this case, we don't consult
-// the routing tables, but just return false and let the caller (up in 
-// ipv4-l3-protocol) flood the multicast packet out of all of its interfaces.
-// We can't really do it here even if we wanted to since we have no easy way
-// to get to the Ipv4 interface which we would need.
-//
-      if (ifIndex == Ipv4RoutingProtocol::IF_INDEX_ANY)
-        {
-          return false;
-        }
-//
-// If we fall through to this point, we have a multicast packet that has
-// not originated at this node.  We need to deal with forwarding.  Let's
-// see if we have a route, and if so go ahead and forward this puppy.
-//
+
       Ipv4MulticastRoute *mRoute = LookupStatic(ipHeader.GetSource (),
         ipHeader.GetDestination (), ifIndex);
 
@@ -479,6 +526,7 @@
         {
           NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): "
             "Multicast route found");
+
           for (uint32_t i = 0; i < mRoute->GetNOutputInterfaces (); ++i)
             {
               Packet p = packet;
@@ -495,7 +543,7 @@
       return false; // Let other routing protocols try to handle this
     }
 //
-// See if this is a unicast packet we have a route for.
+// This is a unicast packet.  Check to see if we have a route for it.
 //
   NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): Unicast destination");
   Ipv4Route *route = LookupStatic (ipHeader.GetDestination ());
--- a/src/internet-node/ipv4-static-routing.h	Tue Sep 04 15:10:47 2007 -0700
+++ b/src/internet-node/ipv4-static-routing.h	Tue Sep 04 18:06:06 2007 -0700
@@ -317,21 +317,34 @@
 /**
  * @brief Add a multicast route to the static routing table.
  *
- * A multicast route must specify an origin IP address -- the address of the
- * node that originates packets destined for a given multicast group.  This
- * address may be Ipv4Address::GetAny (typically 0.0.0.0) if the multicast
- * group is open, or it may specify a single IP address if the multicast
- * group is closed.  The route must also specify the multicast group address.
+ * 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 each route, the input nework interface must be specified.  For 
- * forwarding operations, this is the interface index that you expect multicast
- * packets to arrive over.  If you want to specify routes off of a local node
- * for given multicast groups, this index may be set to 
- * Ipv4RoutingProtocol::IF_INDEX_ANY.
+ * For 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 each route, a vector of output network interfaces must also be 
- * specified.  When the RequestRoute operation is performed, copies of a 
- * packet are sent out all of the specified interfaces.
+ * For example, making the origin address a wildcard, but leaving the 
+ * multicast group specific allows one (in the case of a node with multiple
+ * interfaces) to create different routes using different output interfaces
+ * for each multicast group.
+ *
+ * If the origin and multicast addresses are made wildcards, you have created
+ * essentially a default multicast address that can forward to multiple 
+ * interfaces.  Compare this to the actual default multicast address that is
+ * limited to specifying a single output interface for compatibility with
+ * existing functionality in other systems.
  * 
  * @param origin The Ipv4Address of the origin of packets for this route.  May
  * be Ipv4Address:GetAny for open groups.
@@ -425,6 +438,12 @@
  * This method causes the multicast routing table to be searched for the first
  * route that matches the parameters and removes it.
  *
+ * Wildcards may be provided to this function, but the wildcards are used to
+ * exacly match wildcards in the routes (see AddMulticastRoute).  That is,
+ * calling RemoveMulticastRoute with the origin set to "0.0.0.0" will not
+ * remove routes with any address in the origin, but will only remove routes
+ * with "0.0.0.0" set as the the origin.
+ *
  * @param origin The IP address specified as the origin of packets for the
  * route.
  * @param origin The IP address specified as the multicast group addres of
@@ -433,9 +452,8 @@
  * input interface for the route.
  * @returns True if a route was found and removed, false otherwise.
  *
- * @see Ipv4Route
- * @see Ipv4StaticRouting::GetRoute
- * @see Ipv4StaticRouting::AddRoute
+ * @see Ipv4MulticastRoute
+ * @see Ipv4StaticRouting::AddMulticastRoute
  */
   bool RemoveMulticastRoute (Ipv4Address origin,
                              Ipv4Address group,