src/internet-stack/ipv4-list-routing-impl.cc
changeset 4472 e20a31541404
child 4528 49927f942aea
equal deleted inserted replaced
4471:ef1730710767 4472:e20a31541404
       
     1 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
       
     2 /*
       
     3  * Copyright (c) 2009 University of Washington
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or modify
       
     6  * it under the terms of the GNU General Public License version 2 as
       
     7  * published by the Free Software Foundation;
       
     8  *
       
     9  * This program is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12  * GNU General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU General Public License
       
    15  * along with this program; if not, write to the Free Software
       
    16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    17  *
       
    18  */
       
    19 
       
    20 #include "ns3/log.h"
       
    21 #include "ns3/ipv4.h"
       
    22 #include "ns3/ipv4-route.h"
       
    23 #include "ns3/node.h"
       
    24 #include "ns3/ipv4-static-routing.h"
       
    25 #include "ipv4-list-routing-impl.h"
       
    26 
       
    27 NS_LOG_COMPONENT_DEFINE ("Ipv4ListRoutingImpl");
       
    28 
       
    29 namespace ns3 {
       
    30 
       
    31 NS_OBJECT_ENSURE_REGISTERED (Ipv4ListRoutingImpl);
       
    32 
       
    33 TypeId
       
    34 Ipv4ListRoutingImpl::GetTypeId (void)
       
    35 {
       
    36   static TypeId tid = TypeId ("ns3::Ipv4ListRoutingImpl")
       
    37     .SetParent<Ipv4ListRouting> ()
       
    38     ;
       
    39   return tid;
       
    40 }
       
    41 
       
    42 
       
    43 Ipv4ListRoutingImpl::Ipv4ListRoutingImpl () 
       
    44  : m_node (0)
       
    45 {
       
    46   NS_LOG_FUNCTION_NOARGS ();
       
    47 }
       
    48 
       
    49 Ipv4ListRoutingImpl::~Ipv4ListRoutingImpl () 
       
    50 {
       
    51   NS_LOG_FUNCTION_NOARGS ();
       
    52 }
       
    53 
       
    54 void
       
    55 Ipv4ListRoutingImpl::DoDispose (void)
       
    56 {
       
    57   NS_LOG_FUNCTION_NOARGS ();
       
    58   for (Ipv4RoutingProtocolList::iterator rprotoIter = m_routingProtocols.begin ();
       
    59        rprotoIter != m_routingProtocols.end (); rprotoIter++)
       
    60     {
       
    61       // Note:  Calling dispose on these protocols causes memory leak
       
    62       //        The routing protocols should not maintain a pointer to
       
    63       //        this object, so Dispose() shouldn't be necessary.
       
    64       (*rprotoIter).second = 0;
       
    65     }
       
    66   m_routingProtocols.clear ();
       
    67   m_node = 0;
       
    68 }
       
    69 
       
    70 Ptr<Ipv4Route>
       
    71 Ipv4ListRoutingImpl::RouteOutput (const Ipv4Header &header, uint32_t oif, enum Socket::SocketErrno &sockerr)
       
    72 {
       
    73   NS_LOG_FUNCTION (this << header.GetDestination () << " " << header.GetSource () << " " << oif);
       
    74   Ptr<Ipv4Route> route;
       
    75 
       
    76   for (Ipv4RoutingProtocolList::const_iterator i = m_routingProtocols.begin ();
       
    77        i != m_routingProtocols.end ();
       
    78        i++)
       
    79     {
       
    80       NS_LOG_LOGIC ("Checking protocol " << (*i).second->GetInstanceTypeId () << " with priority " << (*i).first);
       
    81       NS_LOG_LOGIC ("Requesting source address for destination " << header.GetDestination ());
       
    82       route = (*i).second->RouteOutput (header, oif, sockerr);
       
    83       if (route)
       
    84         {
       
    85           NS_LOG_LOGIC ("Found route " << route);
       
    86           sockerr = Socket::ERROR_NOTERROR;
       
    87           return route;
       
    88         }
       
    89     }
       
    90   NS_LOG_LOGIC ("Done checking " << GetTypeId ());
       
    91   NS_LOG_LOGIC ("");
       
    92   sockerr = Socket::ERROR_NOROUTETOHOST;
       
    93   return 0;
       
    94 }
       
    95 
       
    96 // Patterned after Linux ip_route_input and ip_route_input_slow
       
    97 bool 
       
    98 Ipv4ListRoutingImpl::RouteInput (Ptr<const Packet> p, const Ipv4Header &header, Ptr<const NetDevice> idev, 
       
    99                              UnicastForwardCallback ucb, MulticastForwardCallback mcb, 
       
   100                              LocalDeliverCallback lcb, ErrorCallback ecb)
       
   101 {
       
   102   bool retVal = false;
       
   103   NS_LOG_FUNCTION (p << header << idev);
       
   104   NS_LOG_LOGIC ("RouteInput logic for node: " << m_node->GetId ());
       
   105 
       
   106   Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
       
   107   NS_ASSERT (ipv4);
       
   108   uint32_t iif = ipv4->GetInterfaceForDevice (idev); 
       
   109 
       
   110   // Multicast recognition; handle local delivery here
       
   111   //
       
   112   if (header.GetDestination().IsMulticast ())
       
   113     {
       
   114 #ifdef NOTYET
       
   115       if (ipv4->MulticastCheckGroup (iif, header.GetDestination ()))
       
   116 #endif
       
   117       if (true)
       
   118         {
       
   119           NS_LOG_LOGIC ("Multicast packet for me-- local deliver");
       
   120           Ptr<Packet> packetCopy = p->Copy();
       
   121           // Here may want to disable lcb callback in recursive RouteInput
       
   122           // call below
       
   123           lcb (packetCopy, header, iif);
       
   124           // Fall through-- we may also need to forward this
       
   125           retVal = true;
       
   126         }
       
   127       for (Ipv4RoutingProtocolList::const_iterator rprotoIter =
       
   128          m_routingProtocols.begin ();
       
   129            rprotoIter != m_routingProtocols.end ();
       
   130            rprotoIter++)
       
   131         {
       
   132           NS_LOG_LOGIC ("Multicast packet for me-- trying to forward");
       
   133           if ((*rprotoIter).second->RouteInput (p, header, idev, ucb, mcb, lcb, ecb))
       
   134             {
       
   135               retVal = true;
       
   136             }
       
   137         }
       
   138       return retVal;
       
   139     }
       
   140 
       
   141   if (header.GetDestination ().IsBroadcast ())
       
   142     {
       
   143       NS_LOG_LOGIC ("For me (Ipv4Addr broadcast address)");
       
   144       // TODO:  Local Deliver for broadcast
       
   145       // TODO:  Forward broadcast
       
   146     }
       
   147 
       
   148  // TODO:  Configurable option to enable RFC 1222 Strong End System Model
       
   149  // Right now, we will be permissive and allow a source to send us
       
   150  // a packet to one of our other interface addresses; that is, the
       
   151  // destination unicast address does not match one of the iif addresses,
       
   152  // but we check our other interfaces.  This could be an option
       
   153  // (to remove the outer loop immediately below and just check iif).
       
   154   for (uint32_t j = 0; j < ipv4->GetNInterfaces (); j++)
       
   155     {
       
   156       for (uint32_t i = 0; i < ipv4->GetNAddresses (j); i++)
       
   157         {
       
   158           Ipv4InterfaceAddress iaddr = ipv4->GetAddress (j, i);
       
   159           Ipv4Address addr = iaddr.GetLocal ();
       
   160           if (addr.IsEqual (header.GetDestination ()))
       
   161             {
       
   162               if (j == iif)
       
   163                 {
       
   164                   NS_LOG_LOGIC ("For me (destination " << addr << " match)");
       
   165                 }
       
   166               else
       
   167                 {
       
   168                   NS_LOG_LOGIC ("For me (destination " << addr << " match) on another interface " << header.GetDestination ());
       
   169                 }
       
   170               lcb (p, header, iif);
       
   171               return true;
       
   172             }
       
   173           if (header.GetDestination ().IsEqual (iaddr.GetBroadcast ()))
       
   174             {
       
   175               NS_LOG_LOGIC ("For me (interface broadcast address)");
       
   176               lcb (p, header, iif);
       
   177               return true;
       
   178             }
       
   179           NS_LOG_LOGIC ("Address "<< addr << " not a match");
       
   180         }
       
   181     }
       
   182  // Next, try to find a route
       
   183   for (Ipv4RoutingProtocolList::const_iterator rprotoIter =
       
   184          m_routingProtocols.begin ();
       
   185        rprotoIter != m_routingProtocols.end ();
       
   186        rprotoIter++)
       
   187     {
       
   188       if ((*rprotoIter).second->RouteInput (p, header, idev, ucb, mcb, lcb, ecb))
       
   189         {
       
   190           return true;
       
   191         }
       
   192     }
       
   193   // No routing protocol has found a route.  
       
   194   return retVal;
       
   195 }
       
   196 
       
   197 void
       
   198 Ipv4ListRoutingImpl::AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol, int16_t priority)
       
   199 {
       
   200   NS_LOG_FUNCTION (this << routingProtocol->GetInstanceTypeId () << priority);
       
   201   m_routingProtocols.push_back
       
   202     (std::pair<int, Ptr<Ipv4RoutingProtocol> > (-priority, routingProtocol));
       
   203   m_routingProtocols.sort ();
       
   204 }
       
   205 
       
   206 uint32_t 
       
   207 Ipv4ListRoutingImpl::GetNRoutingProtocols (void) const
       
   208 {
       
   209   NS_LOG_FUNCTION (this);
       
   210   return m_routingProtocols.size (); 
       
   211 }
       
   212 
       
   213 Ptr<Ipv4RoutingProtocol> 
       
   214 Ipv4ListRoutingImpl::GetRoutingProtocol (uint32_t index, int16_t& priority) const
       
   215 {
       
   216   NS_LOG_FUNCTION (index);
       
   217   if (index > m_routingProtocols.size ())
       
   218     {
       
   219       NS_FATAL_ERROR ("Ipv4ListRoutingImpl::GetRoutingProtocol():  index " << index << " out of range");
       
   220     }
       
   221   uint32_t i = 0;
       
   222   for (Ipv4RoutingProtocolList::const_iterator rprotoIter = m_routingProtocols.begin ();
       
   223        rprotoIter != m_routingProtocols.end (); rprotoIter++, i++)
       
   224     {
       
   225       if (i == index)
       
   226         {
       
   227           priority = (*rprotoIter).first;
       
   228           return (*rprotoIter).second;
       
   229         }
       
   230     }
       
   231   return 0;
       
   232 }
       
   233 
       
   234 Ptr<Ipv4StaticRouting>
       
   235 Ipv4ListRoutingImpl::GetStaticRouting (void) const
       
   236 {
       
   237   NS_LOG_FUNCTION (this);
       
   238   Ipv4StaticRouting* srp;
       
   239   for (Ipv4RoutingProtocolList::const_iterator rprotoIter = m_routingProtocols.begin ();
       
   240        rprotoIter != m_routingProtocols.end (); rprotoIter++)
       
   241     {
       
   242       NS_LOG_LOGIC ("Searching for static routing");
       
   243       srp = dynamic_cast<Ipv4StaticRouting*> (PeekPointer((*rprotoIter).second));
       
   244       if (srp)
       
   245         {
       
   246           NS_LOG_LOGIC ("Found static routing");
       
   247           return Ptr<Ipv4StaticRouting> (srp);
       
   248         }
       
   249     }
       
   250   NS_LOG_LOGIC ("Static routing not found");
       
   251   return 0;
       
   252 
       
   253 }
       
   254 
       
   255 void
       
   256 Ipv4ListRoutingImpl::SetNode (Ptr<Node> node)
       
   257 {
       
   258   NS_LOG_FUNCTION_NOARGS ();
       
   259   m_node = node;
       
   260 }
       
   261 
       
   262 Ptr<Node> 
       
   263 Ipv4ListRoutingImpl::GetNode (void) const
       
   264 {
       
   265   NS_LOG_FUNCTION_NOARGS ();
       
   266   return m_node;
       
   267 }
       
   268 
       
   269 
       
   270 }//namespace ns3