A Discrete-Event Network Simulator
API
ipv4-list-routing.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009 University of Washington
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  */
18 
19 #include "ipv4-list-routing.h"
20 
21 #include "ns3/ipv4-route.h"
22 #include "ns3/ipv4-static-routing.h"
23 #include "ns3/ipv4.h"
24 #include "ns3/log.h"
25 #include "ns3/node.h"
26 
27 namespace ns3
28 {
29 
30 NS_LOG_COMPONENT_DEFINE("Ipv4ListRouting");
31 
32 NS_OBJECT_ENSURE_REGISTERED(Ipv4ListRouting);
33 
34 TypeId
36 {
37  static TypeId tid = TypeId("ns3::Ipv4ListRouting")
39  .SetGroupName("Internet")
40  .AddConstructor<Ipv4ListRouting>();
41  return tid;
42 }
43 
45  : m_ipv4(nullptr)
46 {
47  NS_LOG_FUNCTION(this);
48 }
49 
51 {
52  NS_LOG_FUNCTION(this);
53 }
54 
55 void
57 {
58  NS_LOG_FUNCTION(this);
59  for (Ipv4RoutingProtocolList::iterator rprotoIter = m_routingProtocols.begin();
60  rprotoIter != m_routingProtocols.end();
61  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 = nullptr;
67  }
68  m_routingProtocols.clear();
69  m_ipv4 = nullptr;
70 }
71 
72 void
74 {
75  NS_LOG_FUNCTION(this << stream);
76  *stream->GetStream() << "Node: " << m_ipv4->GetObject<Node>()->GetId()
77  << ", Time: " << Now().As(unit)
78  << ", Local time: " << m_ipv4->GetObject<Node>()->GetLocalTime().As(unit)
79  << ", Ipv4ListRouting table" << std::endl;
80  for (Ipv4RoutingProtocolList::const_iterator i = m_routingProtocols.begin();
81  i != m_routingProtocols.end();
82  i++)
83  {
84  *stream->GetStream() << " Priority: " << (*i).first
85  << " Protocol: " << (*i).second->GetInstanceTypeId() << std::endl;
86  (*i).second->PrintRoutingTable(stream, unit);
87  }
88 }
89 
90 void
92 {
93  NS_LOG_FUNCTION(this);
94  for (Ipv4RoutingProtocolList::iterator rprotoIter = m_routingProtocols.begin();
95  rprotoIter != m_routingProtocols.end();
96  rprotoIter++)
97  {
98  Ptr<Ipv4RoutingProtocol> protocol = (*rprotoIter).second;
99  protocol->Initialize();
100  }
102 }
103 
106  const Ipv4Header& header,
107  Ptr<NetDevice> oif,
108  enum Socket::SocketErrno& sockerr)
109 {
110  NS_LOG_FUNCTION(this << p << header.GetDestination() << header.GetSource() << oif << sockerr);
111  Ptr<Ipv4Route> route;
112 
113  for (Ipv4RoutingProtocolList::const_iterator i = m_routingProtocols.begin();
114  i != m_routingProtocols.end();
115  i++)
116  {
117  NS_LOG_LOGIC("Checking protocol " << (*i).second->GetInstanceTypeId() << " with priority "
118  << (*i).first);
119  NS_LOG_LOGIC("Requesting source address for destination " << header.GetDestination());
120  route = (*i).second->RouteOutput(p, header, oif, sockerr);
121  if (route)
122  {
123  NS_LOG_LOGIC("Found route " << route);
124  sockerr = Socket::ERROR_NOTERROR;
125  return route;
126  }
127  }
128  NS_LOG_LOGIC("Done checking " << GetTypeId());
129  NS_LOG_LOGIC("");
130  sockerr = Socket::ERROR_NOROUTETOHOST;
131  return nullptr;
132 }
133 
134 // Patterned after Linux ip_route_input and ip_route_input_slow
135 bool
137  const Ipv4Header& header,
142  ErrorCallback ecb)
143 {
144  NS_LOG_FUNCTION(this << p << header << idev << &ucb << &mcb << &lcb << &ecb);
145  bool retVal = false;
146  NS_LOG_LOGIC("RouteInput logic for node: " << m_ipv4->GetObject<Node>()->GetId());
147 
148  NS_ASSERT(m_ipv4);
149  // Check if input device supports IP
150  NS_ASSERT(m_ipv4->GetInterfaceForDevice(idev) >= 0);
151  uint32_t iif = m_ipv4->GetInterfaceForDevice(idev);
152 
153  retVal = m_ipv4->IsDestinationAddress(header.GetDestination(), iif);
154  if (retVal == true)
155  {
156  NS_LOG_LOGIC("Address " << header.GetDestination() << " is a match for local delivery");
157  if (header.GetDestination().IsMulticast())
158  {
159  Ptr<Packet> packetCopy = p->Copy();
160  lcb(packetCopy, header, iif);
161  retVal = true;
162  // Fall through
163  }
164  else
165  {
166  lcb(p, header, iif);
167  return true;
168  }
169  }
170  // Check if input device supports IP forwarding
171  if (m_ipv4->IsForwarding(iif) == false)
172  {
173  NS_LOG_LOGIC("Forwarding disabled for this interface");
174  ecb(p, header, Socket::ERROR_NOROUTETOHOST);
175  return true;
176  }
177  // Next, try to find a route
178  // If we have already delivered a packet locally (e.g. multicast)
179  // we suppress further downstream local delivery by nulling the callback
180  LocalDeliverCallback downstreamLcb = lcb;
181  if (retVal == true)
182  {
183  downstreamLcb = MakeNullCallback<void, Ptr<const Packet>, const Ipv4Header&, uint32_t>();
184  }
185  for (Ipv4RoutingProtocolList::const_iterator rprotoIter = m_routingProtocols.begin();
186  rprotoIter != m_routingProtocols.end();
187  rprotoIter++)
188  {
189  if ((*rprotoIter).second->RouteInput(p, header, idev, ucb, mcb, downstreamLcb, ecb))
190  {
191  NS_LOG_LOGIC("Route found to forward packet in protocol "
192  << (*rprotoIter).second->GetInstanceTypeId().GetName());
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 (Ipv4RoutingProtocolList::const_iterator rprotoIter = m_routingProtocols.begin();
205  rprotoIter != m_routingProtocols.end();
206  rprotoIter++)
207  {
208  (*rprotoIter).second->NotifyInterfaceUp(interface);
209  }
210 }
211 
212 void
214 {
215  NS_LOG_FUNCTION(this << interface);
216  for (Ipv4RoutingProtocolList::const_iterator rprotoIter = m_routingProtocols.begin();
217  rprotoIter != m_routingProtocols.end();
218  rprotoIter++)
219  {
220  (*rprotoIter).second->NotifyInterfaceDown(interface);
221  }
222 }
223 
224 void
226 {
227  NS_LOG_FUNCTION(this << interface << address);
228  for (Ipv4RoutingProtocolList::const_iterator rprotoIter = m_routingProtocols.begin();
229  rprotoIter != m_routingProtocols.end();
230  rprotoIter++)
231  {
232  (*rprotoIter).second->NotifyAddAddress(interface, address);
233  }
234 }
235 
236 void
238 {
239  NS_LOG_FUNCTION(this << interface << address);
240  for (Ipv4RoutingProtocolList::const_iterator rprotoIter = m_routingProtocols.begin();
241  rprotoIter != m_routingProtocols.end();
242  rprotoIter++)
243  {
244  (*rprotoIter).second->NotifyRemoveAddress(interface, address);
245  }
246 }
247 
248 void
250 {
251  NS_LOG_FUNCTION(this << ipv4);
252  NS_ASSERT(!m_ipv4);
253  for (Ipv4RoutingProtocolList::const_iterator rprotoIter = m_routingProtocols.begin();
254  rprotoIter != m_routingProtocols.end();
255  rprotoIter++)
256  {
257  (*rprotoIter).second->SetIpv4(ipv4);
258  }
259  m_ipv4 = ipv4;
260 }
261 
262 void
264 {
265  NS_LOG_FUNCTION(this << routingProtocol->GetInstanceTypeId() << priority);
266  m_routingProtocols.emplace_back(priority, routingProtocol);
268  if (m_ipv4)
269  {
270  routingProtocol->SetIpv4(m_ipv4);
271  }
272 }
273 
274 uint32_t
276 {
277  NS_LOG_FUNCTION(this);
278  return m_routingProtocols.size();
279 }
280 
282 Ipv4ListRouting::GetRoutingProtocol(uint32_t index, int16_t& priority) const
283 {
284  NS_LOG_FUNCTION(this << index << priority);
285  if (index >= m_routingProtocols.size())
286  {
287  NS_FATAL_ERROR("Ipv4ListRouting::GetRoutingProtocol(): index " << index
288  << " out of range");
289  }
290  uint32_t i = 0;
291  for (Ipv4RoutingProtocolList::const_iterator rprotoIter = m_routingProtocols.begin();
292  rprotoIter != m_routingProtocols.end();
293  rprotoIter++, i++)
294  {
295  if (i == index)
296  {
297  priority = (*rprotoIter).first;
298  return (*rprotoIter).second;
299  }
300  }
301  return nullptr;
302 }
303 
304 bool
306 {
307  NS_LOG_FUNCTION(a.first << a.second << b.first << b.second);
308  return a.first > b.first;
309 }
310 
311 } // namespace ns3
Callback template class.
Definition: callback.h:443
bool IsMulticast() const
Packet header for IPv4.
Definition: ipv4-header.h:34
Ipv4Address GetSource() const
Definition: ipv4-header.cc:302
Ipv4Address GetDestination() const
Definition: ipv4-header.cc:316
a class to store IPv4 address information on an interface
IPv4 list routing.
std::pair< int16_t, Ptr< Ipv4RoutingProtocol > > Ipv4RoutingProtocolEntry
Container identifying an IPv4 Routing Protocol entry in the list.
static TypeId GetTypeId()
Get the type ID of this class.
void DoDispose() override
Destructor implementation.
Ipv4RoutingProtocolList m_routingProtocols
List of routing protocols.
bool RouteInput(Ptr< const Packet > p, const Ipv4Header &header, Ptr< const NetDevice > idev, UnicastForwardCallback ucb, MulticastForwardCallback mcb, LocalDeliverCallback lcb, ErrorCallback ecb) override
Route an input packet (to be forwarded or locally delivered)
void NotifyRemoveAddress(uint32_t interface, Ipv4InterfaceAddress address) override
Ptr< Ipv4Route > RouteOutput(Ptr< Packet > p, const Ipv4Header &header, Ptr< NetDevice > oif, Socket::SocketErrno &sockerr) override
Query routing cache for an existing route, for an outbound packet.
void SetIpv4(Ptr< Ipv4 > ipv4) override
virtual uint32_t GetNRoutingProtocols() const
void PrintRoutingTable(Ptr< OutputStreamWrapper > stream, Time::Unit unit=Time::S) const override
Print the Routing Table entries.
virtual void AddRoutingProtocol(Ptr< Ipv4RoutingProtocol > routingProtocol, int16_t priority)
Register a new routing protocol to be used in this IPv4 stack.
Ptr< Ipv4 > m_ipv4
Ipv4 this protocol is associated with.
static bool Compare(const Ipv4RoutingProtocolEntry &a, const Ipv4RoutingProtocolEntry &b)
Compare two routing protocols.
void NotifyInterfaceDown(uint32_t interface) override
void DoInitialize() override
Initialize() implementation.
virtual Ptr< Ipv4RoutingProtocol > GetRoutingProtocol(uint32_t index, int16_t &priority) const
Return pointer to routing protocol stored at index, with the first protocol (index 0) the highest pri...
void NotifyAddAddress(uint32_t interface, Ipv4InterfaceAddress address) override
void NotifyInterfaceUp(uint32_t interface) override
Abstract base class for IPv4 routing protocols.
A network Node.
Definition: node.h:56
uint32_t GetId() const
Definition: node.cc:117
virtual void DoInitialize()
Initialize() implementation.
Definition: object.cc:360
std::ostream * GetStream()
Return a pointer to an ostream previously set in the wrapper.
Ptr< Packet > Copy() const
performs a COW copy of the packet.
Definition: packet.cc:131
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:84
@ ERROR_NOROUTETOHOST
Definition: socket.h:95
@ ERROR_NOTERROR
Definition: socket.h:85
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:417
Unit
The unit to use to interpret a number representing time.
Definition: nstime.h:111
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:296
address
Definition: first.py:40
Every class exported by the ns3 library is enclosed in the ns3 namespace.