A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
ipv4-list-routing.cc
Go to the documentation of this file.
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.h"
26 
27 NS_LOG_COMPONENT_DEFINE ("Ipv4ListRouting");
28 
29 namespace ns3 {
30 
31 NS_OBJECT_ENSURE_REGISTERED (Ipv4ListRouting);
32 
33 TypeId
35 {
36  static TypeId tid = TypeId ("ns3::Ipv4ListRouting")
38  .AddConstructor<Ipv4ListRouting> ()
39  ;
40  return tid;
41 }
42 
43 
45  : m_ipv4 (0)
46 {
48 }
49 
51 {
53 }
54 
55 void
57 {
59  for (Ipv4RoutingProtocolList::iterator rprotoIter = m_routingProtocols.begin ();
60  rprotoIter != m_routingProtocols.end (); rprotoIter++)
61  {
62  // Note: Calling dispose on these protocols causes memory leak
63  // The routing protocols should not maintain a pointer to
64  // this object, so Dispose() shouldn't be necessary.
65  (*rprotoIter).second = 0;
66  }
67  m_routingProtocols.clear ();
68  m_ipv4 = 0;
69 }
70 
71 void
73 {
74  *stream->GetStream () << "Node: " << m_ipv4->GetObject<Node> ()->GetId ()
75  << " Time: " << Simulator::Now ().GetSeconds () << "s "
76  << "Ipv4ListRouting table" << std::endl;
77  for (Ipv4RoutingProtocolList::const_iterator i = m_routingProtocols.begin ();
78  i != m_routingProtocols.end (); i++)
79  {
80  *stream->GetStream () << " Priority: " << (*i).first << " Protocol: " << (*i).second->GetInstanceTypeId () << std::endl;
81  (*i).second->PrintRoutingTable (stream);
82  }
83  *stream->GetStream () << std::endl;
84 }
85 
86 void
88 {
89  for (Ipv4RoutingProtocolList::iterator rprotoIter = m_routingProtocols.begin ();
90  rprotoIter != m_routingProtocols.end (); rprotoIter++)
91  {
92  Ptr<Ipv4RoutingProtocol> protocol = (*rprotoIter).second;
93  protocol->Start ();
94  }
96 }
97 
98 
101 {
102  NS_LOG_FUNCTION (this << header.GetDestination () << " " << header.GetSource () << " " << oif);
103  Ptr<Ipv4Route> route;
104 
105  for (Ipv4RoutingProtocolList::const_iterator i = m_routingProtocols.begin ();
106  i != m_routingProtocols.end (); i++)
107  {
108  NS_LOG_LOGIC ("Checking protocol " << (*i).second->GetInstanceTypeId () << " with priority " << (*i).first);
109  NS_LOG_LOGIC ("Requesting source address for destination " << header.GetDestination ());
110  route = (*i).second->RouteOutput (p, header, oif, sockerr);
111  if (route)
112  {
113  NS_LOG_LOGIC ("Found route " << route);
114  sockerr = Socket::ERROR_NOTERROR;
115  return route;
116  }
117  }
118  NS_LOG_LOGIC ("Done checking " << GetTypeId ());
119  NS_LOG_LOGIC ("");
120  sockerr = Socket::ERROR_NOROUTETOHOST;
121  return 0;
122 }
123 
124 // Patterned after Linux ip_route_input and ip_route_input_slow
125 bool
129 {
130  bool retVal = false;
131  NS_LOG_FUNCTION (p << header << idev);
132  NS_LOG_LOGIC ("RouteInput logic for node: " << m_ipv4->GetObject<Node> ()->GetId ());
133 
134  NS_ASSERT (m_ipv4 != 0);
135  // Check if input device supports IP
136  NS_ASSERT (m_ipv4->GetInterfaceForDevice (idev) >= 0);
137  uint32_t iif = m_ipv4->GetInterfaceForDevice (idev);
138 
139  retVal = m_ipv4->IsDestinationAddress (header.GetDestination (), iif);
140  if (retVal == true)
141  {
142  NS_LOG_LOGIC ("Address "<< header.GetDestination () << " is a match for local delivery");
143  if (header.GetDestination ().IsMulticast ())
144  {
145  Ptr<Packet> packetCopy = p->Copy ();
146  lcb (packetCopy, header, iif);
147  retVal = true;
148  // Fall through
149  }
150  else
151  {
152  lcb (p, header, iif);
153  return true;
154  }
155  }
156  // Check if input device supports IP forwarding
157  if (m_ipv4->IsForwarding (iif) == false)
158  {
159  NS_LOG_LOGIC ("Forwarding disabled for this interface");
160  ecb (p, header, Socket::ERROR_NOROUTETOHOST);
161  return false;
162  }
163  // Next, try to find a route
164  // If we have already delivered a packet locally (e.g. multicast)
165  // we suppress further downstream local delivery by nulling the callback
166  LocalDeliverCallback downstreamLcb = lcb;
167  if (retVal == true)
168  {
169  downstreamLcb = MakeNullCallback<void, Ptr<const Packet>, const Ipv4Header &, uint32_t > ();
170  }
171  for (Ipv4RoutingProtocolList::const_iterator rprotoIter =
172  m_routingProtocols.begin ();
173  rprotoIter != m_routingProtocols.end ();
174  rprotoIter++)
175  {
176  if ((*rprotoIter).second->RouteInput (p, header, idev, ucb, mcb, downstreamLcb, ecb))
177  {
178  NS_LOG_LOGIC ("Route found to forward packet in protocol " << (*rprotoIter).second->GetInstanceTypeId ().GetName ());
179  return true;
180  }
181  }
182  // No routing protocol has found a route.
183  return retVal;
184 }
185 
186 void
188 {
189  NS_LOG_FUNCTION (this << interface);
190  for (Ipv4RoutingProtocolList::const_iterator rprotoIter =
191  m_routingProtocols.begin ();
192  rprotoIter != m_routingProtocols.end ();
193  rprotoIter++)
194  {
195  (*rprotoIter).second->NotifyInterfaceUp (interface);
196  }
197 }
198 void
200 {
201  NS_LOG_FUNCTION (this << interface);
202  for (Ipv4RoutingProtocolList::const_iterator rprotoIter =
203  m_routingProtocols.begin ();
204  rprotoIter != m_routingProtocols.end ();
205  rprotoIter++)
206  {
207  (*rprotoIter).second->NotifyInterfaceDown (interface);
208  }
209 }
210 void
212 {
213  NS_LOG_FUNCTION (this << interface << address);
214  for (Ipv4RoutingProtocolList::const_iterator rprotoIter =
215  m_routingProtocols.begin ();
216  rprotoIter != m_routingProtocols.end ();
217  rprotoIter++)
218  {
219  (*rprotoIter).second->NotifyAddAddress (interface, address);
220  }
221 }
222 void
224 {
225  NS_LOG_FUNCTION (this << interface << address);
226  for (Ipv4RoutingProtocolList::const_iterator rprotoIter =
227  m_routingProtocols.begin ();
228  rprotoIter != m_routingProtocols.end ();
229  rprotoIter++)
230  {
231  (*rprotoIter).second->NotifyRemoveAddress (interface, address);
232  }
233 }
234 void
236 {
237  NS_LOG_FUNCTION (this << ipv4);
238  NS_ASSERT (m_ipv4 == 0);
239  for (Ipv4RoutingProtocolList::const_iterator rprotoIter =
240  m_routingProtocols.begin ();
241  rprotoIter != m_routingProtocols.end ();
242  rprotoIter++)
243  {
244  (*rprotoIter).second->SetIpv4 (ipv4);
245  }
246  m_ipv4 = ipv4;
247 }
248 
249 void
251 {
252  NS_LOG_FUNCTION (this << routingProtocol->GetInstanceTypeId () << priority);
253  m_routingProtocols.push_back (std::make_pair (priority, routingProtocol));
254  m_routingProtocols.sort ( Compare );
255  if (m_ipv4 != 0)
256  {
257  routingProtocol->SetIpv4 (m_ipv4);
258  }
259 }
260 
261 uint32_t
263 {
264  NS_LOG_FUNCTION (this);
265  return m_routingProtocols.size ();
266 }
267 
269 Ipv4ListRouting::GetRoutingProtocol (uint32_t index, int16_t& priority) const
270 {
271  NS_LOG_FUNCTION (index);
272  if (index > m_routingProtocols.size ())
273  {
274  NS_FATAL_ERROR ("Ipv4ListRouting::GetRoutingProtocol(): index " << index << " out of range");
275  }
276  uint32_t i = 0;
277  for (Ipv4RoutingProtocolList::const_iterator rprotoIter = m_routingProtocols.begin ();
278  rprotoIter != m_routingProtocols.end (); rprotoIter++, i++)
279  {
280  if (i == index)
281  {
282  priority = (*rprotoIter).first;
283  return (*rprotoIter).second;
284  }
285  }
286  return 0;
287 }
288 
289 bool
291 {
292  return a.first > b.first;
293 }
294 
295 
296 } // namespace ns3
297