A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ipv6-list-routing.cc
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/ipv6.h"
22 #include "ns3/ipv6-route.h"
23 #include "ns3/node.h"
24 #include "ns3/ipv6-static-routing.h"
25 #include "ipv6-list-routing.h"
26 #include "ns3/simulator.h"
27 
28 NS_LOG_COMPONENT_DEFINE ("Ipv6ListRouting");
29 
30 namespace ns3 {
31 
32 NS_OBJECT_ENSURE_REGISTERED (Ipv6ListRouting);
33 
34 TypeId
36 {
37  static TypeId tid = TypeId ("ns3::Ipv6ListRouting")
39  .AddConstructor<Ipv6ListRouting> ()
40  ;
41  return tid;
42 }
43 
44 
46  : m_ipv6 (0)
47 {
49 }
50 
52 {
54 }
55 
56 void
58 {
60  for (Ipv6RoutingProtocolList::iterator rprotoIter = m_routingProtocols.begin ();
61  rprotoIter != m_routingProtocols.end (); rprotoIter++)
62  {
63  // Note: Calling dispose on these protocols causes memory leak
64  // The routing protocols should not maintain a pointer to
65  // this object, so Dispose () shouldn't be necessary.
66  (*rprotoIter).second = 0;
67  }
68  m_routingProtocols.clear ();
69  m_ipv6 = 0;
70 }
71 
73 Ipv6ListRouting::RouteOutput (Ptr<Packet> p, const Ipv6Header &header, Ptr<NetDevice> oif, enum Socket::SocketErrno &sockerr)
74 {
75  NS_LOG_FUNCTION (this << header.GetDestinationAddress () << header.GetSourceAddress () << oif);
76  Ptr<Ipv6Route> route;
77 
78  for (Ipv6RoutingProtocolList::const_iterator i = m_routingProtocols.begin ();
79  i != m_routingProtocols.end (); i++)
80  {
81  NS_LOG_LOGIC ("Checking protocol " << (*i).second->GetInstanceTypeId () << " with priority " << (*i).first);
82  NS_LOG_LOGIC ("Requesting source address for destination " << header.GetDestinationAddress ());
83  route = (*i).second->RouteOutput (p, header, oif, sockerr);
84  if (route)
85  {
86  NS_LOG_LOGIC ("Found route " << route);
87  sockerr = Socket::ERROR_NOTERROR;
88  return route;
89  }
90  }
91  NS_LOG_LOGIC ("Done checking " << GetTypeId ());
92  NS_LOG_LOGIC ("");
93  sockerr = Socket::ERROR_NOROUTETOHOST;
94  return 0;
95 }
96 
97 // Patterned after Linux ip_route_input and ip_route_input_slow
98 bool
102 {
103  bool retVal = false;
104  NS_LOG_FUNCTION (p << header << idev);
105  NS_LOG_LOGIC ("RouteInput logic for node: " << m_ipv6->GetObject<Node> ()->GetId ());
106 
107  NS_ASSERT (m_ipv6 != 0);
108  // Check if input device supports IP
109  NS_ASSERT (m_ipv6->GetInterfaceForDevice (idev) >= 0);
110  uint32_t iif = m_ipv6->GetInterfaceForDevice (idev);
111  Ipv6Address dst = header.GetDestinationAddress ();
112 
113  // Multicast recognition; handle local delivery here
114  //
115  if (dst.IsMulticast ())
116  {
117 #ifdef NOTYET
118  if (m_ipv6->MulticastCheckGroup (iif, dst))
119 #endif
120  if (true)
121  {
122  NS_LOG_LOGIC ("Multicast packet for me-- local deliver");
123  Ptr<Packet> packetCopy = p->Copy ();
124  // Here may want to disable lcb callback in recursive RouteInput
125  // call below
126  lcb (packetCopy, header, iif);
127  // Fall through-- we may also need to forward this
128  retVal = true;
129  }
130 
131  /* do not forward link-local multicast address */
133  {
134  return retVal;
135  }
136 
137  for (Ipv6RoutingProtocolList::const_iterator rprotoIter =
138  m_routingProtocols.begin (); rprotoIter != m_routingProtocols.end ();
139  rprotoIter++)
140  {
141  NS_LOG_LOGIC ("Multicast packet for me-- trying to forward");
142  if ((*rprotoIter).second->RouteInput (p, header, idev, ucb, mcb, lcb, ecb))
143  {
144  retVal = true;
145  }
146  }
147  return retVal;
148  }
149 
150  // TODO: Configurable option to enable RFC 1222 Strong End System Model
151  // Right now, we will be permissive and allow a source to send us
152  // a packet to one of our other interface addresses; that is, the
153  // destination unicast address does not match one of the iif addresses,
154  // but we check our other interfaces. This could be an option
155  // (to remove the outer loop immediately below and just check iif).
156  for (uint32_t j = 0; j < m_ipv6->GetNInterfaces (); j++)
157  {
158  for (uint32_t i = 0; i < m_ipv6->GetNAddresses (j); i++)
159  {
160  Ipv6InterfaceAddress iaddr = m_ipv6->GetAddress (j, i);
161  Ipv6Address addr = iaddr.GetAddress ();
162  if (addr.IsEqual (header.GetDestinationAddress ()))
163  {
164  if (j == iif)
165  {
166  NS_LOG_LOGIC ("For me (destination " << addr << " match)");
167  }
168  else
169  {
170  NS_LOG_LOGIC ("For me (destination " << addr << " match) on another interface " << header.GetDestinationAddress ());
171  }
172  lcb (p, header, iif);
173  return true;
174  }
175  NS_LOG_LOGIC ("Address " << addr << " not a match");
176  }
177  }
178  // Check if input device supports IP forwarding
179  if (m_ipv6->IsForwarding (iif) == false)
180  {
181  NS_LOG_LOGIC ("Forwarding disabled for this interface");
182  ecb (p, header, Socket::ERROR_NOROUTETOHOST);
183  return false;
184  }
185  // Next, try to find a route
186  for (Ipv6RoutingProtocolList::const_iterator rprotoIter =
187  m_routingProtocols.begin ();
188  rprotoIter != m_routingProtocols.end ();
189  rprotoIter++)
190  {
191  if ((*rprotoIter).second->RouteInput (p, header, idev, ucb, mcb, lcb, ecb))
192  {
193  return true;
194  }
195  }
196  // No routing protocol has found a route.
197  return retVal;
198 }
199 
200 void
202 {
203  NS_LOG_FUNCTION (this << interface);
204  for (Ipv6RoutingProtocolList::const_iterator rprotoIter =
205  m_routingProtocols.begin ();
206  rprotoIter != m_routingProtocols.end ();
207  rprotoIter++)
208  {
209  (*rprotoIter).second->NotifyInterfaceUp (interface);
210  }
211 }
212 void
214 {
215  NS_LOG_FUNCTION (this << interface);
216  for (Ipv6RoutingProtocolList::const_iterator rprotoIter =
217  m_routingProtocols.begin ();
218  rprotoIter != m_routingProtocols.end ();
219  rprotoIter++)
220  {
221  (*rprotoIter).second->NotifyInterfaceDown (interface);
222  }
223 }
224 void
226 {
227  NS_LOG_FUNCTION (this << interface << address);
228  for (Ipv6RoutingProtocolList::const_iterator rprotoIter =
229  m_routingProtocols.begin ();
230  rprotoIter != m_routingProtocols.end ();
231  rprotoIter++)
232  {
233  (*rprotoIter).second->NotifyAddAddress (interface, address);
234  }
235 }
236 void
238 {
239  NS_LOG_FUNCTION (this << interface << address);
240  for (Ipv6RoutingProtocolList::const_iterator rprotoIter =
241  m_routingProtocols.begin ();
242  rprotoIter != m_routingProtocols.end ();
243  rprotoIter++)
244  {
245  (*rprotoIter).second->NotifyRemoveAddress (interface, address);
246  }
247 }
248 
249 void Ipv6ListRouting::NotifyAddRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse)
250 {
251  NS_LOG_FUNCTION (this << dst << mask << nextHop << interface);
252  for (Ipv6RoutingProtocolList::const_iterator rprotoIter =
253  m_routingProtocols.begin ();
254  rprotoIter != m_routingProtocols.end ();
255  rprotoIter++)
256  {
257  (*rprotoIter).second->NotifyAddRoute (dst, mask, nextHop, interface, prefixToUse);
258  }
259 }
260 
261 void Ipv6ListRouting::NotifyRemoveRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse)
262 {
263  NS_LOG_FUNCTION (this << dst << mask << nextHop << interface);
264  for (Ipv6RoutingProtocolList::const_iterator rprotoIter =
265  m_routingProtocols.begin ();
266  rprotoIter != m_routingProtocols.end ();
267  rprotoIter++)
268  {
269  (*rprotoIter).second->NotifyRemoveRoute (dst, mask, nextHop, interface, prefixToUse);
270  }
271 }
272 
273 void
275 {
276  NS_LOG_FUNCTION (this);
277 
278  *stream->GetStream () << "Node: " << m_ipv6->GetObject<Node> ()->GetId ()
279  << " Time: " << Simulator::Now ().GetSeconds () << "s "
280  << "Ipv6ListRouting table" << std::endl;
281  for (Ipv6RoutingProtocolList::const_iterator i = m_routingProtocols.begin ();
282  i != m_routingProtocols.end (); i++)
283  {
284  *stream->GetStream () << " Priority: " << (*i).first << " Protocol: " << (*i).second->GetInstanceTypeId () << std::endl;
285  (*i).second->PrintRoutingTable (stream);
286  }
287  *stream->GetStream () << std::endl;
288 }
289 
290 void
292 {
293  NS_LOG_FUNCTION (this << ipv6);
294  NS_ASSERT (m_ipv6 == 0);
295  for (Ipv6RoutingProtocolList::const_iterator rprotoIter =
296  m_routingProtocols.begin ();
297  rprotoIter != m_routingProtocols.end ();
298  rprotoIter++)
299  {
300  (*rprotoIter).second->SetIpv6 (ipv6);
301  }
302  m_ipv6 = ipv6;
303 }
304 
305 void
307 {
308  NS_LOG_FUNCTION (this << routingProtocol->GetInstanceTypeId () << priority);
309  m_routingProtocols.push_back (std::make_pair (priority, routingProtocol));
310  m_routingProtocols.sort ( Compare );
311  if (m_ipv6 != 0)
312  {
313  routingProtocol->SetIpv6 (m_ipv6);
314  }
315 }
316 
317 uint32_t
319 {
320  NS_LOG_FUNCTION (this);
321  return m_routingProtocols.size ();
322 }
323 
325 Ipv6ListRouting::GetRoutingProtocol (uint32_t index, int16_t& priority) const
326 {
327  NS_LOG_FUNCTION (index);
328  if (index > m_routingProtocols.size ())
329  {
330  NS_FATAL_ERROR ("Ipv6ListRouting::GetRoutingProtocol (): index " << index << " out of range");
331  }
332  uint32_t i = 0;
333  for (Ipv6RoutingProtocolList::const_iterator rprotoIter = m_routingProtocols.begin ();
334  rprotoIter != m_routingProtocols.end (); rprotoIter++, i++)
335  {
336  if (i == index)
337  {
338  priority = (*rprotoIter).first;
339  return (*rprotoIter).second;
340  }
341  }
342  return 0;
343 }
344 
345 bool
346 Ipv6ListRouting::Compare (const Ipv6RoutingProtocolEntry& a, const Ipv6RoutingProtocolEntry& b)
347 {
348  return a.first > b.first;
349 }
350 
351 
352 } // namespace ns3
353 
Packet header for IPv6.
Definition: ipv6-header.h:33
virtual void NotifyRemoveAddress(uint32_t interface, Ipv6InterfaceAddress address)
Notify when specified interface add an address.
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:59
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
virtual uint32_t GetNRoutingProtocols(void) const
Get the number of routing protocols.
Callback template class.
Definition: callback.h:369
virtual Ptr< Ipv6Route > RouteOutput(Ptr< Packet > p, const Ipv6Header &header, Ptr< NetDevice > oif, Socket::SocketErrno &sockerr)
Query routing cache for an existing route, for an outbound packet.
#define NS_ASSERT(condition)
Definition: assert.h:64
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
IPv6 address associated with an interface.
bool IsEqual(const Ipv6Address &other) const
Comparison operation between two Ipv6Addresses.
#define NS_LOG_FUNCTION_NOARGS()
Definition: log.h:275
virtual void AddRoutingProtocol(Ptr< Ipv6RoutingProtocol > routingProtocol, int16_t priority)
Register a new routing protocol to be used in this IPv4 stack.
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
virtual void NotifyAddRoute(Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse=Ipv6Address::GetZero())
Notify a new route.
Ptr< Ipv6 > m_ipv6
Ipv6 reference.
virtual bool RouteInput(Ptr< const Packet > p, const Ipv6Header &header, Ptr< const NetDevice > idev, UnicastForwardCallback ucb, MulticastForwardCallback mcb, LocalDeliverCallback lcb, ErrorCallback ecb)
Route an input packet (to be forwarded or locally delivered)
static bool Compare(const Ipv6RoutingProtocolEntry &a, const Ipv6RoutingProtocolEntry &b)
Compare two routing protocols.
virtual void NotifyRemoveRoute(Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse=Ipv6Address::GetZero())
Notify route removing.
double GetSeconds(void) const
Definition: nstime.h:262
Ipv6Address GetAddress() const
Get the IPv6 address.
virtual void NotifyInterfaceUp(uint32_t interface)
Notify when specified interface goes UP.
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
virtual void SetIpv6(Ptr< Ipv6 > ipv6)
Typically, invoked directly or indirectly from ns3::Ipv6::SetRoutingProtocol.
static Ipv6Address GetAllHostsMulticast()
Get the "all hosts multicast" address.
Ptr< Packet > Copy(void) const
Definition: packet.cc:131
Ipv6ListRouting()
Constructor.
bool IsMulticast() const
If the IPv6 address is multicast (ff00::/8).
static Ipv6Address GetAllNodesMulticast()
Get the "all nodes multicast" address.
virtual void PrintRoutingTable(Ptr< OutputStreamWrapper > stream) const
Print the Routing Table entries.
virtual ~Ipv6ListRouting()
Destructor.
static Time Now(void)
Definition: simulator.cc:179
Describes an IPv6 address.
Definition: ipv6-address.h:44
static TypeId GetTypeId(void)
Get the type ID of this class.
uint32_t GetId(void) const
Definition: node.cc:105
virtual void NotifyInterfaceDown(uint32_t interface)
Notify when specified interface goes DOWN.
A network Node.
Definition: node.h:56
Ipv6Address GetSourceAddress(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:101
Describes an IPv6 prefix. It is just a bitmask like Ipv4Mask.
Definition: ipv6-address.h:326
virtual void DoDispose(void)
Dispose this object.
Abstract base class for Ipv6 routing protocols.
a unique identifier for an interface.
Definition: type-id.h:44
virtual Ptr< Ipv6RoutingProtocol > GetRoutingProtocol(uint32_t index, int16_t &priority) const
Get pointer to routing protocol stored at index,.
TypeId SetParent(TypeId tid)
Definition: type-id.cc:471
std::ostream * GetStream(void)
Ipv6RoutingProtocolList m_routingProtocols
List of routing protocols.
Ipv6Address GetDestinationAddress(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:111
static Ipv6Address GetAllRoutersMulticast()
Get the "all routers multicast" address.
virtual void NotifyAddAddress(uint32_t interface, Ipv6InterfaceAddress address)
Notify when specified interface add an address.