A Discrete-Event Network Simulator
API
rip.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2016 Universita' di Firenze, Italy
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  * Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
19  */
20 
21 #include <iomanip>
22 #include "rip.h"
23 #include "ns3/log.h"
24 #include "ns3/abort.h"
25 #include "ns3/assert.h"
26 #include "ns3/random-variable-stream.h"
27 #include "ns3/ipv4-route.h"
28 #include "ns3/node.h"
29 #include "ns3/names.h"
30 #include "ns3/rip-header.h"
31 #include "ns3/udp-header.h"
32 #include "ns3/enum.h"
33 #include "ns3/uinteger.h"
34 #include "ns3/ipv4-packet-info-tag.h"
35 #include "ns3/loopback-net-device.h"
36 
37 #define RIP_ALL_NODE "224.0.0.9"
38 #define RIP_PORT 520
39 
40 namespace ns3 {
41 
43 
45 
47  : m_ipv4 (0), m_splitHorizonStrategy (Rip::POISON_REVERSE), m_initialized (false)
48 {
49  m_rng = CreateObject<UniformRandomVariable> ();
50 }
51 
53 {
54 }
55 
56 TypeId
58 {
59  static TypeId tid = TypeId ("ns3::Rip")
61  .SetGroupName ("Internet")
62  .AddConstructor<Rip> ()
63  .AddAttribute ("UnsolicitedRoutingUpdate", "The time between two Unsolicited Routing Updates.",
64  TimeValue (Seconds(30)),
66  MakeTimeChecker ())
67  .AddAttribute ("StartupDelay", "Maximum random delay for protocol startup (send route requests).",
68  TimeValue (Seconds(1)),
70  MakeTimeChecker ())
71  .AddAttribute ("TimeoutDelay", "The delay to invalidate a route.",
72  TimeValue (Seconds(180)),
74  MakeTimeChecker ())
75  .AddAttribute ("GarbageCollectionDelay", "The delay to delete an expired route.",
76  TimeValue (Seconds(120)),
78  MakeTimeChecker ())
79  .AddAttribute ("MinTriggeredCooldown", "Min cooldown delay after a Triggered Update.",
80  TimeValue (Seconds(1)),
82  MakeTimeChecker ())
83  .AddAttribute ("MaxTriggeredCooldown", "Max cooldown delay after a Triggered Update.",
84  TimeValue (Seconds(5)),
86  MakeTimeChecker ())
87  .AddAttribute ("SplitHorizon", "Split Horizon strategy.",
90  MakeEnumChecker (Rip::NO_SPLIT_HORIZON, "NoSplitHorizon",
91  Rip::SPLIT_HORIZON, "SplitHorizon",
92  Rip::POISON_REVERSE, "PoisonReverse"))
93  .AddAttribute ("LinkDownValue", "Value for link down in count to infinity.",
94  UintegerValue (16),
96  MakeUintegerChecker<uint32_t> ())
97  ;
98  return tid;
99 }
100 
101 int64_t Rip::AssignStreams (int64_t stream)
102 {
103  NS_LOG_FUNCTION (this << stream);
104 
105  m_rng->SetStream (stream);
106  return 1;
107 }
108 
110 {
111  NS_LOG_FUNCTION (this);
112 
113  bool addedGlobal = false;
114 
115  m_initialized = true;
116 
119 
120 
121  for (uint32_t i = 0 ; i < m_ipv4->GetNInterfaces (); i++)
122  {
123  Ptr<LoopbackNetDevice> check = DynamicCast<LoopbackNetDevice> (m_ipv4->GetNetDevice (i));
124  if (check)
125  {
126  continue;
127  }
128 
129  bool activeInterface = false;
130  if (m_interfaceExclusions.find (i) == m_interfaceExclusions.end ())
131  {
132  activeInterface = true;
133  m_ipv4->SetForwarding (i, true);
134  }
135 
136  for (uint32_t j = 0; j < m_ipv4->GetNAddresses (i); j++)
137  {
138  Ipv4InterfaceAddress address = m_ipv4->GetAddress (i, j);
139  if (address.GetScope() != Ipv4InterfaceAddress::HOST && activeInterface == true)
140  {
141  NS_LOG_LOGIC ("RIP: adding socket to " << address.GetLocal ());
142  TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
143  Ptr<Node> theNode = GetObject<Node> ();
144  Ptr<Socket> socket = Socket::CreateSocket (theNode, tid);
145  InetSocketAddress local = InetSocketAddress (address.GetLocal (), RIP_PORT);
146  socket->BindToNetDevice (m_ipv4->GetNetDevice (i));
147  int ret = socket->Bind (local);
148  NS_ASSERT_MSG (ret == 0, "Bind unsuccessful");
149 
150  socket->SetRecvCallback (MakeCallback (&Rip::Receive, this));
151  socket->SetIpRecvTtl (true);
152  socket->SetRecvPktInfo (true);
153 
154  m_unicastSocketList[socket] = i;
155  }
156  else if (m_ipv4->GetAddress (i, j).GetScope() == Ipv4InterfaceAddress::GLOBAL)
157  {
158  addedGlobal = true;
159  }
160  }
161  }
162 
164  {
165  NS_LOG_LOGIC ("RIP: adding receiving socket");
166  TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
167  Ptr<Node> theNode = GetObject<Node> ();
170  m_multicastRecvSocket->Bind (local);
174  }
175 
176 
177  if (addedGlobal)
178  {
181  }
182 
183  delay = Seconds (m_rng->GetValue (0.01, m_startupDelay.GetSeconds ()));
185 
187 }
188 
190 {
191  NS_LOG_FUNCTION (this << header << oif);
192 
193  Ipv4Address destination = header.GetDestination ();
194  Ptr<Ipv4Route> rtentry = 0;
195 
196  if (destination.IsMulticast ())
197  {
198  // Note: Multicast routes for outbound packets are stored in the
199  // normal unicast table. An implication of this is that it is not
200  // possible to source multicast datagrams on multiple interfaces.
201  // This is a well-known property of sockets implementation on
202  // many Unix variants.
203  // So, we just log it and fall through to LookupStatic ()
204  NS_LOG_LOGIC ("RouteOutput (): Multicast destination");
205  }
206 
207  rtentry = Lookup (destination, true, oif);
208  if (rtentry)
209  {
210  sockerr = Socket::ERROR_NOTERROR;
211  }
212  else
213  {
214  sockerr = Socket::ERROR_NOROUTETOHOST;
215  }
216  return rtentry;
217 }
218 
222 {
223  NS_LOG_FUNCTION (this << p << header << header.GetSource () << header.GetDestination () << idev);
224 
225  NS_ASSERT (m_ipv4 != 0);
226  // Check if input device supports IP
227  NS_ASSERT (m_ipv4->GetInterfaceForDevice (idev) >= 0);
228  uint32_t iif = m_ipv4->GetInterfaceForDevice (idev);
229  Ipv4Address dst = header.GetDestination ();
230 
231  if (m_ipv4->IsDestinationAddress (header.GetDestination (), iif))
232  {
233  if (!lcb.IsNull ())
234  {
235  NS_LOG_LOGIC ("Local delivery to " << header.GetDestination ());
236  lcb (p, header, iif);
237  return true;
238  }
239  else
240  {
241  // The local delivery callback is null. This may be a multicast
242  // or broadcast packet, so return false so that another
243  // multicast routing protocol can handle it. It should be possible
244  // to extend this to explicitly check whether it is a unicast
245  // packet, and invoke the error callback if so
246  return false;
247  }
248  }
249 
250  if (dst.IsMulticast ())
251  {
252  NS_LOG_LOGIC ("Multicast route not supported by RIP");
253  return false; // Let other routing protocols try to handle this
254  }
255 
256  if (header.GetDestination ().IsBroadcast ())
257  {
258  NS_LOG_LOGIC ("Dropping packet not for me and with dst Broadcast");
259  if (!ecb.IsNull ())
260  {
261  ecb (p, header, Socket::ERROR_NOROUTETOHOST);
262  }
263  return false;
264  }
265 
266  // Check if input device supports IP forwarding
267  if (m_ipv4->IsForwarding (iif) == false)
268  {
269  NS_LOG_LOGIC ("Forwarding disabled for this interface");
270  if (!ecb.IsNull ())
271  {
272  ecb (p, header, Socket::ERROR_NOROUTETOHOST);
273  }
274  return true;
275  }
276  // Next, try to find a route
277  NS_LOG_LOGIC ("Unicast destination");
278  Ptr<Ipv4Route> rtentry = Lookup (header.GetDestination (), false);
279 
280  if (rtentry != 0)
281  {
282  NS_LOG_LOGIC ("Found unicast destination - calling unicast callback");
283  ucb (rtentry, p, header); // unicast forwarding callback
284  return true;
285  }
286  else
287  {
288  NS_LOG_LOGIC ("Did not find unicast destination - returning false");
289  return false; // Let other routing protocols try to handle this
290  }
291 }
292 
293 void Rip::NotifyInterfaceUp (uint32_t i)
294 {
295  NS_LOG_FUNCTION (this << i);
296 
297  Ptr<LoopbackNetDevice> check = DynamicCast<LoopbackNetDevice> (m_ipv4->GetNetDevice (i));
298  if (check)
299  {
300  return;
301  }
302 
303  for (uint32_t j = 0; j < m_ipv4->GetNAddresses (i); j++)
304  {
305  Ipv4InterfaceAddress address = m_ipv4->GetAddress (i, j);
306  Ipv4Mask networkMask = address.GetMask ();
307  Ipv4Address networkAddress = address.GetLocal ().CombineMask (networkMask);
308 
309  if (address.GetScope () == Ipv4InterfaceAddress::GLOBAL)
310  {
311  AddNetworkRouteTo (networkAddress, networkMask, i);
312  }
313  }
314 
315  if (!m_initialized)
316  {
317  return;
318  }
319 
320 
321  bool sendSocketFound = false;
322  for (SocketListI iter = m_unicastSocketList.begin (); iter != m_unicastSocketList.end (); iter++ )
323  {
324  if (iter->second == i)
325  {
326  sendSocketFound = true;
327  break;
328  }
329  }
330 
331  bool activeInterface = false;
332  if (m_interfaceExclusions.find (i) == m_interfaceExclusions.end ())
333  {
334  activeInterface = true;
335  m_ipv4->SetForwarding (i, true);
336  }
337 
338  for (uint32_t j = 0; j < m_ipv4->GetNAddresses (i); j++)
339  {
340  Ipv4InterfaceAddress address = m_ipv4->GetAddress (i, j);
341 
342  if (address.GetScope() != Ipv4InterfaceAddress::HOST && sendSocketFound == false && activeInterface == true)
343  {
344  NS_LOG_LOGIC ("RIP: adding sending socket to " << address.GetLocal ());
345  TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
346  Ptr<Node> theNode = GetObject<Node> ();
347  Ptr<Socket> socket = Socket::CreateSocket (theNode, tid);
348  InetSocketAddress local = InetSocketAddress (address.GetLocal (), RIP_PORT);
349  socket->BindToNetDevice (m_ipv4->GetNetDevice (i));
350  socket->Bind (local);
351  socket->SetRecvCallback (MakeCallback (&Rip::Receive, this));
352  socket->SetIpRecvTtl (true);
353  socket->SetRecvPktInfo (true);
354  m_unicastSocketList[socket] = i;
355  }
356  if (address.GetScope () == Ipv4InterfaceAddress::GLOBAL)
357  {
359  }
360  }
361 
363  {
364  NS_LOG_LOGIC ("RIP: adding receiving socket");
365  TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
366  Ptr<Node> theNode = GetObject<Node> ();
369  m_multicastRecvSocket->Bind (local);
373  }
374 }
375 
376 void Rip::NotifyInterfaceDown (uint32_t interface)
377 {
378  NS_LOG_FUNCTION (this << interface);
379 
380  /* remove all routes that are going through this interface */
381  for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++)
382  {
383  if (it->first->GetInterface () == interface)
384  {
385  InvalidateRoute (it->first);
386  }
387  }
388 
389  for (SocketListI iter = m_unicastSocketList.begin (); iter != m_unicastSocketList.end (); iter++ )
390  {
391  NS_LOG_INFO ("Checking socket for interface " << interface);
392  if (iter->second == interface)
393  {
394  NS_LOG_INFO ("Removed socket for interface " << interface);
395  iter->first->Close ();
396  m_unicastSocketList.erase (iter);
397  break;
398  }
399  }
400 
401  if (m_interfaceExclusions.find (interface) == m_interfaceExclusions.end ())
402  {
404  }
405 }
406 
408 {
409  NS_LOG_FUNCTION (this << interface << address);
410 
411  if (!m_ipv4->IsUp (interface))
412  {
413  return;
414  }
415 
416  if (m_interfaceExclusions.find (interface) != m_interfaceExclusions.end ())
417  {
418  return;
419  }
420 
421  Ipv4Address networkAddress = address.GetLocal ().CombineMask (address.GetMask ());
422  Ipv4Mask networkMask = address.GetMask ();
423 
424  if (address.GetScope () == Ipv4InterfaceAddress::GLOBAL)
425  {
426  AddNetworkRouteTo (networkAddress, networkMask, interface);
427  }
428 
430 }
431 
433 {
434  NS_LOG_FUNCTION (this << interface << address);
435 
436  if (!m_ipv4->IsUp (interface))
437  {
438  return;
439  }
440 
441  if (address.GetScope() != Ipv4InterfaceAddress::GLOBAL)
442  {
443  return;
444  }
445 
446  Ipv4Address networkAddress = address.GetLocal ().CombineMask (address.GetMask ());
447  Ipv4Mask networkMask = address.GetMask ();
448 
449  // Remove all routes that are going through this interface
450  // which reference this network
451  for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++)
452  {
453  if (it->first->GetInterface () == interface
454  && it->first->IsNetwork ()
455  && it->first->GetDestNetwork () == networkAddress
456  && it->first->GetDestNetworkMask () == networkMask)
457  {
458  InvalidateRoute (it->first);
459  }
460  }
461 
462  if (m_interfaceExclusions.find (interface) == m_interfaceExclusions.end ())
463  {
465  }
466 
467 }
468 
470 {
471  NS_LOG_FUNCTION (this << ipv4);
472 
473  NS_ASSERT (m_ipv4 == 0 && ipv4 != 0);
474  uint32_t i = 0;
475  m_ipv4 = ipv4;
476 
477  for (i = 0; i < m_ipv4->GetNInterfaces (); i++)
478  {
479  if (m_ipv4->IsUp (i))
480  {
481  NotifyInterfaceUp (i);
482  }
483  else
484  {
486  }
487  }
488 }
489 
491 {
492  NS_LOG_FUNCTION (this << stream);
493 
494  std::ostream* os = stream->GetStream ();
495  // Copy the current ostream state
496  std::ios oldState (nullptr);
497  oldState.copyfmt (*os);
498 
499  *os << std::resetiosflags (std::ios::adjustfield) << std::setiosflags (std::ios::left);
500 
501  *os << "Node: " << m_ipv4->GetObject<Node> ()->GetId ()
502  << ", Time: " << Now().As (unit)
503  << ", Local time: " << m_ipv4->GetObject<Node> ()->GetLocalTime ().As (unit)
504  << ", IPv4 RIP table" << std::endl;
505 
506  if (!m_routes.empty ())
507  {
508  *os << "Destination Gateway Genmask Flags Metric Ref Use Iface" << std::endl;
509  for (RoutesCI it = m_routes.begin (); it != m_routes.end (); it++)
510  {
511  RipRoutingTableEntry* route = it->first;
513 
514  if (status == RipRoutingTableEntry::RIP_VALID)
515  {
516  std::ostringstream dest, gw, mask, flags;
517  dest << route->GetDest ();
518  *os << std::setw (16) << dest.str ();
519  gw << route->GetGateway ();
520  *os << std::setw (16) << gw.str ();
521  mask << route->GetDestNetworkMask ();
522  *os << std::setw (16) << mask.str ();
523  flags << "U";
524  if (route->IsHost ())
525  {
526  flags << "HS";
527  }
528  else if (route->IsGateway ())
529  {
530  flags << "GS";
531  }
532  *os << std::setw (6) << flags.str ();
533  *os << std::setw (7) << int(route->GetRouteMetric ());
534  // Ref ct not implemented
535  *os << "-" << " ";
536  // Use not implemented
537  *os << "-" << " ";
538  if (Names::FindName (m_ipv4->GetNetDevice (route->GetInterface ())) != "")
539  {
540  *os << Names::FindName (m_ipv4->GetNetDevice (route->GetInterface ()));
541  }
542  else
543  {
544  *os << route->GetInterface ();
545  }
546  *os << std::endl;
547  }
548  }
549  }
550  *os << std::endl;
551  // Restore the previous ostream state
552  (*os).copyfmt (oldState);
553 }
554 
556 {
557  NS_LOG_FUNCTION (this);
558 
559  for (RoutesI j = m_routes.begin (); j != m_routes.end (); j = m_routes.erase (j))
560  {
561  delete j->first;
562  }
563  m_routes.clear ();
564 
569 
570  for (SocketListI iter = m_unicastSocketList.begin (); iter != m_unicastSocketList.end (); iter++ )
571  {
572  iter->first->Close ();
573  }
574  m_unicastSocketList.clear ();
575 
578 
579  m_ipv4 = 0;
580 
582 }
583 
584 Ptr<Ipv4Route> Rip::Lookup (Ipv4Address dst, bool setSource, Ptr<NetDevice> interface)
585 {
586  NS_LOG_FUNCTION (this << dst << interface);
587 
588  Ptr<Ipv4Route> rtentry = 0;
589  uint16_t longestMask = 0;
590 
591  /* when sending on local multicast, there have to be interface specified */
592  if (dst.IsLocalMulticast ())
593  {
594  NS_ASSERT_MSG (interface, "Try to send on local multicast address, and no interface index is given!");
595  rtentry = Create<Ipv4Route> ();
596  rtentry->SetSource (m_ipv4->SourceAddressSelection (m_ipv4->GetInterfaceForDevice (interface), dst));
597  rtentry->SetDestination (dst);
598  rtentry->SetGateway (Ipv4Address::GetZero ());
599  rtentry->SetOutputDevice (interface);
600  return rtentry;
601  }
602 
603  for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++)
604  {
605  RipRoutingTableEntry* j = it->first;
606 
608  {
609  Ipv4Mask mask = j->GetDestNetworkMask ();
610  uint16_t maskLen = mask.GetPrefixLength ();
611  Ipv4Address entry = j->GetDestNetwork ();
612 
613  NS_LOG_LOGIC ("Searching for route to " << dst << ", mask length " << maskLen);
614 
615  if (mask.IsMatch (dst, entry))
616  {
617  NS_LOG_LOGIC ("Found global network route " << j << ", mask length " << maskLen);
618 
619  /* if interface is given, check the route will output on this interface */
620  if (!interface || interface == m_ipv4->GetNetDevice (j->GetInterface ()))
621  {
622  if (maskLen < longestMask)
623  {
624  NS_LOG_LOGIC ("Previous match longer, skipping");
625  continue;
626  }
627 
628  longestMask = maskLen;
629 
630  Ipv4RoutingTableEntry* route = j;
631  uint32_t interfaceIdx = route->GetInterface ();
632  rtentry = Create<Ipv4Route> ();
633 
634  if (setSource)
635  {
636  if (route->GetDest ().IsAny ()) /* default route */
637  {
638  rtentry->SetSource (m_ipv4->SourceAddressSelection (interfaceIdx, route->GetGateway ()));
639  }
640  else
641  {
642  rtentry->SetSource (m_ipv4->SourceAddressSelection (interfaceIdx, route->GetDest ()));
643  }
644  }
645 
646  rtentry->SetDestination (route->GetDest ());
647  rtentry->SetGateway (route->GetGateway ());
648  rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceIdx));
649  }
650  }
651  }
652  }
653 
654  if (rtentry)
655  {
656  NS_LOG_LOGIC ("Matching route via " << rtentry->GetDestination () << " (through " << rtentry->GetGateway () << ") at the end");
657  }
658  return rtentry;
659 }
660 
661 void Rip::AddNetworkRouteTo (Ipv4Address network, Ipv4Mask networkPrefix, Ipv4Address nextHop, uint32_t interface)
662 {
663  NS_LOG_FUNCTION (this << network << networkPrefix << nextHop << interface);
664 
665  RipRoutingTableEntry* route = new RipRoutingTableEntry (network, networkPrefix, nextHop, interface);
666  route->SetRouteMetric (1);
668  route->SetRouteChanged (true);
669 
670  m_routes.push_back (std::make_pair (route, EventId ()));
671 }
672 
673 void Rip::AddNetworkRouteTo (Ipv4Address network, Ipv4Mask networkPrefix, uint32_t interface)
674 {
675  NS_LOG_FUNCTION (this << network << networkPrefix << interface);
676 
677  RipRoutingTableEntry* route = new RipRoutingTableEntry (network, networkPrefix, interface);
678  route->SetRouteMetric (1);
680  route->SetRouteChanged (true);
681 
682  m_routes.push_back (std::make_pair (route, EventId ()));
683 }
684 
686 {
687  NS_LOG_FUNCTION (this << *route);
688 
689  for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++)
690  {
691  if (it->first == route)
692  {
694  route->SetRouteMetric (m_linkDown);
695  route->SetRouteChanged (true);
696  if (it->second.IsRunning ())
697  {
698  it->second.Cancel ();
699  }
700  it->second = Simulator::Schedule (m_garbageCollectionDelay, &Rip::DeleteRoute, this, route);
701  return;
702  }
703  }
704  NS_ABORT_MSG ("RIP::InvalidateRoute - cannot find the route to update");
705 }
706 
708 {
709  NS_LOG_FUNCTION (this << *route);
710 
711  for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++)
712  {
713  if (it->first == route)
714  {
715  delete route;
716  m_routes.erase (it);
717  return;
718  }
719  }
720  NS_ABORT_MSG ("RIP::DeleteRoute - cannot find the route to delete");
721 }
722 
723 
725 {
726  NS_LOG_FUNCTION (this << socket);
727 
728  Address sender;
729  Ptr<Packet> packet = socket->RecvFrom (sender);
731  NS_LOG_INFO ("Received " << *packet << " from " << senderAddr.GetIpv4 () << ":" << senderAddr.GetPort ());
732 
733  Ipv4Address senderAddress = senderAddr.GetIpv4 ();
734  uint16_t senderPort = senderAddr.GetPort ();
735 
736  if (socket == m_multicastRecvSocket)
737  {
738  NS_LOG_LOGIC ("Received a packet from the multicast socket");
739  }
740  else
741  {
742  NS_LOG_LOGIC ("Received a packet from one of the unicast sockets");
743  }
744 
745  Ipv4PacketInfoTag interfaceInfo;
746  if (!packet->RemovePacketTag (interfaceInfo))
747  {
748  NS_ABORT_MSG ("No incoming interface on RIP message, aborting.");
749  }
750  uint32_t incomingIf = interfaceInfo.GetRecvIf ();
751  Ptr<Node> node = this->GetObject<Node> ();
752  Ptr<NetDevice> dev = node->GetDevice (incomingIf);
753  uint32_t ipInterfaceIndex = m_ipv4->GetInterfaceForDevice (dev);
754 
755  SocketIpTtlTag hoplimitTag;
756  if (!packet->RemovePacketTag (hoplimitTag))
757  {
758  NS_ABORT_MSG ("No incoming Hop Count on RIP message, aborting.");
759  }
760  uint8_t hopLimit = hoplimitTag.GetTtl ();
761 
762  int32_t interfaceForAddress = m_ipv4->GetInterfaceForAddress (senderAddress);
763  if (interfaceForAddress != -1)
764  {
765  NS_LOG_LOGIC ("Ignoring a packet sent by myself.");
766  return;
767  }
768 
769  RipHeader hdr;
770  packet->RemoveHeader (hdr);
771 
772  if (hdr.GetCommand () == RipHeader::RESPONSE)
773  {
774  NS_LOG_LOGIC ("The message is a Response from " << senderAddr.GetIpv4 () << ":" << senderAddr.GetPort ());
775  HandleResponses (hdr, senderAddress, ipInterfaceIndex, hopLimit);
776  }
777  else if (hdr.GetCommand () == RipHeader::REQUEST)
778  {
779  NS_LOG_LOGIC ("The message is a Request from " << senderAddr.GetIpv4 () << ":" << senderAddr.GetPort ());
780  HandleRequests (hdr, senderAddress, senderPort, ipInterfaceIndex, hopLimit);
781  }
782  else
783  {
784  NS_LOG_LOGIC ("Ignoring message with unknown command: " << int (hdr.GetCommand ()));
785  }
786  return;
787 }
788 
789 void Rip::HandleRequests (RipHeader requestHdr, Ipv4Address senderAddress, uint16_t senderPort, uint32_t incomingInterface, uint8_t hopLimit)
790 {
791  NS_LOG_FUNCTION (this << senderAddress << int (senderPort) << incomingInterface << int (hopLimit) << requestHdr);
792 
793  std::list<RipRte> rtes = requestHdr.GetRteList ();
794 
795  if (rtes.empty ())
796  {
797  return;
798  }
799 
800  // check if it's a request for the full table from a neighbor
801  if (rtes.size () == 1)
802  {
803  if (rtes.begin ()->GetPrefix () == Ipv4Address::GetAny () &&
804  rtes.begin ()->GetSubnetMask ().GetPrefixLength () == 0 &&
805  rtes.begin ()->GetRouteMetric () == m_linkDown)
806  {
807  // Output whole thing. Use Split Horizon
808  if (m_interfaceExclusions.find (incomingInterface) == m_interfaceExclusions.end ())
809  {
810  // we use one of the sending sockets, as they're bound to the right interface
811  // and the local address might be used on different interfaces.
812  Ptr<Socket> sendingSocket;
813  for (SocketListI iter = m_unicastSocketList.begin (); iter != m_unicastSocketList.end (); iter++ )
814  {
815  if (iter->second == incomingInterface)
816  {
817  sendingSocket = iter->first;
818  }
819  }
820  NS_ASSERT_MSG (sendingSocket, "HandleRequest - Impossible to find a socket to send the reply");
821 
822  uint16_t mtu = m_ipv4->GetMtu (incomingInterface);
823  uint16_t maxRte = (mtu - Ipv4Header ().GetSerializedSize () - UdpHeader ().GetSerializedSize () - RipHeader ().GetSerializedSize ()) / RipRte ().GetSerializedSize ();
824 
825  Ptr<Packet> p = Create<Packet> ();
826  SocketIpTtlTag tag;
827  p->RemovePacketTag (tag);
828  if (senderAddress == Ipv4Address(RIP_ALL_NODE))
829  {
830  tag.SetTtl (1);
831  }
832  else
833  {
834  tag.SetTtl (255);
835  }
836  p->AddPacketTag (tag);
837 
838  RipHeader hdr;
840 
841  for (RoutesI rtIter = m_routes.begin (); rtIter != m_routes.end (); rtIter++)
842  {
843  bool splitHorizoning = (rtIter->first->GetInterface () == incomingInterface);
844 
845  Ipv4InterfaceAddress rtDestAddr = Ipv4InterfaceAddress(rtIter->first->GetDestNetwork (), rtIter->first->GetDestNetworkMask ());
846 
847  bool isGlobal = (rtDestAddr.GetScope () == Ipv4InterfaceAddress::GLOBAL);
848  bool isDefaultRoute = ((rtIter->first->GetDestNetwork () == Ipv4Address::GetAny ()) &&
849  (rtIter->first->GetDestNetworkMask () == Ipv4Mask::GetZero ()) &&
850  (rtIter->first->GetInterface () != incomingInterface));
851 
852  if ((isGlobal || isDefaultRoute) &&
853  (rtIter->first->GetRouteStatus () == RipRoutingTableEntry::RIP_VALID) )
854  {
855  RipRte rte;
856  rte.SetPrefix (rtIter->first->GetDestNetwork ());
857  rte.SetSubnetMask (rtIter->first->GetDestNetworkMask ());
858  if (m_splitHorizonStrategy == POISON_REVERSE && splitHorizoning)
859  {
861  }
862  else
863  {
864  rte.SetRouteMetric (rtIter->first->GetRouteMetric ());
865  }
866  rte.SetRouteTag (rtIter->first->GetRouteTag ());
868  (m_splitHorizonStrategy == SPLIT_HORIZON && !splitHorizoning))
869  {
870  hdr.AddRte (rte);
871  }
872  }
873  if (hdr.GetRteNumber () == maxRte)
874  {
875  p->AddHeader (hdr);
876  NS_LOG_DEBUG ("SendTo: " << *p);
877  sendingSocket->SendTo (p, 0, InetSocketAddress (senderAddress, RIP_PORT));
878  p->RemoveHeader (hdr);
879  hdr.ClearRtes ();
880  }
881  }
882  if (hdr.GetRteNumber () > 0)
883  {
884  p->AddHeader (hdr);
885  NS_LOG_DEBUG ("SendTo: " << *p);
886  sendingSocket->SendTo (p, 0, InetSocketAddress (senderAddress, RIP_PORT));
887  }
888  }
889  }
890  }
891  else
892  {
893  // note: we got the request as a single packet, so no check is necessary for MTU limit
894 
895  Ptr<Packet> p = Create<Packet> ();
896  SocketIpTtlTag tag;
897  p->RemovePacketTag (tag);
898  if (senderAddress == Ipv4Address(RIP_ALL_NODE))
899  {
900  tag.SetTtl (1);
901  }
902  else
903  {
904  tag.SetTtl (255);
905  }
906  p->AddPacketTag (tag);
907 
908  RipHeader hdr;
910 
911  for (std::list<RipRte>::iterator iter = rtes.begin ();
912  iter != rtes.end (); iter++)
913  {
914  bool found = false;
915  for (RoutesI rtIter = m_routes.begin (); rtIter != m_routes.end (); rtIter++)
916  {
917 
918  Ipv4InterfaceAddress rtDestAddr = Ipv4InterfaceAddress (rtIter->first->GetDestNetwork (), rtIter->first->GetDestNetworkMask ());
919  if ((rtDestAddr.GetScope () == Ipv4InterfaceAddress::GLOBAL) &&
920  (rtIter->first->GetRouteStatus () == RipRoutingTableEntry::RIP_VALID))
921  {
922  Ipv4Address requestedAddress = iter->GetPrefix ();
923  requestedAddress.CombineMask (iter->GetSubnetMask ());
924  Ipv4Address rtAddress = rtIter->first->GetDestNetwork ();
925  rtAddress.CombineMask (rtIter->first->GetDestNetworkMask ());
926 
927  if (requestedAddress == rtAddress)
928  {
929  iter->SetRouteMetric (rtIter->first->GetRouteMetric ());
930  iter->SetRouteTag (rtIter->first->GetRouteTag ());
931  hdr.AddRte (*iter);
932  found = true;
933  break;
934  }
935  }
936  }
937  if (!found)
938  {
939  iter->SetRouteMetric (m_linkDown);
940  iter->SetRouteTag (0);
941  hdr.AddRte (*iter);
942  }
943  }
944  p->AddHeader (hdr);
945  NS_LOG_DEBUG ("SendTo: " << *p);
946  m_multicastRecvSocket->SendTo (p, 0, InetSocketAddress (senderAddress, senderPort));
947  }
948 
949 }
950 
951 void Rip::HandleResponses (RipHeader hdr, Ipv4Address senderAddress, uint32_t incomingInterface, uint8_t hopLimit)
952 {
953  NS_LOG_FUNCTION (this << senderAddress << incomingInterface << int (hopLimit) << hdr);
954 
955  if (m_interfaceExclusions.find (incomingInterface) != m_interfaceExclusions.end ())
956  {
957  NS_LOG_LOGIC ("Ignoring an update message from an excluded interface: " << incomingInterface);
958  return;
959  }
960 
961  std::list<RipRte> rtes = hdr.GetRteList ();
962 
963  // validate the RTEs before processing
964  for (std::list<RipRte>::iterator iter = rtes.begin ();
965  iter != rtes.end (); iter++)
966  {
967  if (iter->GetRouteMetric () == 0 || iter->GetRouteMetric () > m_linkDown)
968  {
969  NS_LOG_LOGIC ("Ignoring an update message with malformed metric: " << int (iter->GetRouteMetric ()));
970  return;
971  }
972  if (iter->GetPrefix ().IsLocalhost () ||
973  iter->GetPrefix ().IsBroadcast () ||
974  iter->GetPrefix ().IsMulticast ())
975  {
976  NS_LOG_LOGIC ("Ignoring an update message with wrong prefixes: " << iter->GetPrefix ());
977  return;
978  }
979  }
980 
981  bool changed = false;
982 
983  for (std::list<RipRte>::iterator iter = rtes.begin ();
984  iter != rtes.end (); iter++)
985  {
986  Ipv4Mask rtePrefixMask = iter->GetSubnetMask ();
987  Ipv4Address rteAddr = iter->GetPrefix ().CombineMask (rtePrefixMask);
988 
989  NS_LOG_LOGIC ("Processing RTE " << *iter);
990 
991  uint32_t interfaceMetric = 1;
992  if (m_interfaceMetrics.find (incomingInterface) != m_interfaceMetrics.end ())
993  {
994  interfaceMetric = m_interfaceMetrics[incomingInterface];
995  }
996  uint64_t rteMetric = iter->GetRouteMetric () + interfaceMetric;
997  if (rteMetric > m_linkDown)
998  {
999  rteMetric = m_linkDown;
1000  }
1001 
1002  RoutesI it;
1003  bool found = false;
1004  for (it = m_routes.begin (); it != m_routes.end (); it++)
1005  {
1006  if (it->first->GetDestNetwork () == rteAddr &&
1007  it->first->GetDestNetworkMask () == rtePrefixMask)
1008  {
1009  found = true;
1010  if (rteMetric < it->first->GetRouteMetric ())
1011  {
1012  if (senderAddress != it->first->GetGateway ())
1013  {
1014  RipRoutingTableEntry* route = new RipRoutingTableEntry (rteAddr, rtePrefixMask, senderAddress, incomingInterface);
1015  delete it->first;
1016  it->first = route;
1017  }
1018  it->first->SetRouteMetric (rteMetric);
1019  it->first->SetRouteStatus (RipRoutingTableEntry::RIP_VALID);
1020  it->first->SetRouteTag (iter->GetRouteTag ());
1021  it->first->SetRouteChanged (true);
1022  it->second.Cancel ();
1023  it->second = Simulator::Schedule (m_timeoutDelay, &Rip::InvalidateRoute, this, it->first);
1024  changed = true;
1025  }
1026  else if (rteMetric == it->first->GetRouteMetric ())
1027  {
1028  if (senderAddress == it->first->GetGateway ())
1029  {
1030  it->second.Cancel ();
1031  it->second = Simulator::Schedule (m_timeoutDelay, &Rip::InvalidateRoute, this, it->first);
1032  }
1033  else
1034  {
1035  if (Simulator::GetDelayLeft (it->second) < m_timeoutDelay/2)
1036  {
1037  RipRoutingTableEntry* route = new RipRoutingTableEntry (rteAddr, rtePrefixMask, senderAddress, incomingInterface);
1038  route->SetRouteMetric (rteMetric);
1040  route->SetRouteTag (iter->GetRouteTag ());
1041  route->SetRouteChanged (true);
1042  delete it->first;
1043  it->first = route;
1044  it->second.Cancel ();
1045  it->second = Simulator::Schedule (m_timeoutDelay, &Rip::InvalidateRoute, this, route);
1046  changed = true;
1047  }
1048  }
1049  }
1050  else if (rteMetric > it->first->GetRouteMetric () && senderAddress == it->first->GetGateway ())
1051  {
1052  it->second.Cancel ();
1053  if (rteMetric < m_linkDown)
1054  {
1055  it->first->SetRouteMetric (rteMetric);
1056  it->first->SetRouteStatus (RipRoutingTableEntry::RIP_VALID);
1057  it->first->SetRouteTag (iter->GetRouteTag ());
1058  it->first->SetRouteChanged (true);
1059  it->second.Cancel ();
1060  it->second = Simulator::Schedule (m_timeoutDelay, &Rip::InvalidateRoute, this, it->first);
1061  }
1062  else
1063  {
1064  InvalidateRoute (it->first);
1065  }
1066  changed = true;
1067  }
1068  }
1069  }
1070  if (!found && rteMetric != m_linkDown)
1071  {
1072  NS_LOG_LOGIC ("Received a RTE with new route, adding.");
1073 
1074  RipRoutingTableEntry* route = new RipRoutingTableEntry (rteAddr, rtePrefixMask, senderAddress, incomingInterface);
1075  route->SetRouteMetric (rteMetric);
1077  route->SetRouteChanged (true);
1078  m_routes.push_front (std::make_pair (route, EventId ()));
1079  EventId invalidateEvent = Simulator::Schedule (m_timeoutDelay, &Rip::InvalidateRoute, this, route);
1080  (m_routes.begin ())->second = invalidateEvent;
1081  changed = true;
1082  }
1083  }
1084 
1085  if (changed)
1086  {
1088  }
1089 }
1090 
1091 void Rip::DoSendRouteUpdate (bool periodic)
1092 {
1093  NS_LOG_FUNCTION (this << (periodic ? " periodic" : " triggered"));
1094 
1095  for (SocketListI iter = m_unicastSocketList.begin (); iter != m_unicastSocketList.end (); iter++ )
1096  {
1097  uint32_t interface = iter->second;
1098 
1099  if (m_interfaceExclusions.find (interface) == m_interfaceExclusions.end ())
1100  {
1101  uint16_t mtu = m_ipv4->GetMtu (interface);
1102  uint16_t maxRte = (mtu - Ipv4Header ().GetSerializedSize () - UdpHeader ().GetSerializedSize () - RipHeader ().GetSerializedSize ()) / RipRte ().GetSerializedSize ();
1103 
1104  Ptr<Packet> p = Create<Packet> ();
1105  SocketIpTtlTag tag;
1106  tag.SetTtl (1);
1107  p->AddPacketTag (tag);
1108 
1109  RipHeader hdr;
1111 
1112  for (RoutesI rtIter = m_routes.begin (); rtIter != m_routes.end (); rtIter++)
1113  {
1114  bool splitHorizoning = (rtIter->first->GetInterface () == interface);
1115  Ipv4InterfaceAddress rtDestAddr = Ipv4InterfaceAddress(rtIter->first->GetDestNetwork (), rtIter->first->GetDestNetworkMask ());
1116 
1117  NS_LOG_DEBUG ("Processing RT " << rtDestAddr << " " << int(rtIter->first->IsRouteChanged ()));
1118 
1119  bool isGlobal = (rtDestAddr.GetScope () == Ipv4InterfaceAddress::GLOBAL);
1120  bool isDefaultRoute = ((rtIter->first->GetDestNetwork () == Ipv4Address::GetAny ()) &&
1121  (rtIter->first->GetDestNetworkMask () == Ipv4Mask::GetZero ()) &&
1122  (rtIter->first->GetInterface () != interface));
1123 
1124  bool sameNetwork = false;
1125  for (uint32_t index = 0; index < m_ipv4->GetNAddresses (interface); index++)
1126  {
1127  Ipv4InterfaceAddress addr = m_ipv4->GetAddress (interface, index);
1128  if (addr.GetLocal ().CombineMask (addr.GetMask ()) == rtIter->first->GetDestNetwork ())
1129  {
1130  sameNetwork = true;
1131  }
1132  }
1133 
1134  if ((isGlobal || isDefaultRoute) &&
1135  (periodic || rtIter->first->IsRouteChanged ()) &&
1136  !sameNetwork)
1137  {
1138  RipRte rte;
1139  rte.SetPrefix (rtIter->first->GetDestNetwork ());
1140  rte.SetSubnetMask (rtIter->first->GetDestNetworkMask ());
1141  if (m_splitHorizonStrategy == POISON_REVERSE && splitHorizoning)
1142  {
1143  rte.SetRouteMetric (m_linkDown);
1144  }
1145  else
1146  {
1147  rte.SetRouteMetric (rtIter->first->GetRouteMetric ());
1148  }
1149  rte.SetRouteTag (rtIter->first->GetRouteTag ());
1150  if (m_splitHorizonStrategy == SPLIT_HORIZON && !splitHorizoning)
1151  {
1152  hdr.AddRte (rte);
1153  }
1155  {
1156  hdr.AddRte (rte);
1157  }
1158  }
1159  if (hdr.GetRteNumber () == maxRte)
1160  {
1161  p->AddHeader (hdr);
1162  NS_LOG_DEBUG ("SendTo: " << *p);
1163  iter->first->SendTo (p, 0, InetSocketAddress (RIP_ALL_NODE, RIP_PORT));
1164  p->RemoveHeader (hdr);
1165  hdr.ClearRtes ();
1166  }
1167  }
1168  if (hdr.GetRteNumber () > 0)
1169  {
1170  p->AddHeader (hdr);
1171  NS_LOG_DEBUG ("SendTo: " << *p);
1172  iter->first->SendTo (p, 0, InetSocketAddress (RIP_ALL_NODE, RIP_PORT));
1173  }
1174  }
1175  }
1176  for (RoutesI rtIter = m_routes.begin (); rtIter != m_routes.end (); rtIter++)
1177  {
1178  rtIter->first->SetRouteChanged (false);
1179  }
1180 }
1181 
1183 {
1184  NS_LOG_FUNCTION (this);
1185 
1187  {
1188  NS_LOG_LOGIC ("Skipping Triggered Update due to cooldown");
1189  return;
1190  }
1191 
1192  // DoSendRouteUpdate (false);
1193 
1194  // note: The RFC states:
1195  // After a triggered
1196  // update is sent, a timer should be set for a random interval between 1
1197  // and 5 seconds. If other changes that would trigger updates occur
1198  // before the timer expires, a single update is triggered when the timer
1199  // expires. The timer is then reset to another random value between 1
1200  // and 5 seconds. Triggered updates may be suppressed if a regular
1201  // update is due by the time the triggered update would be sent.
1202  // Here we rely on this:
1203  // When an update occurs (either Triggered or Periodic) the "IsChanged ()"
1204  // route field will be cleared.
1205  // Hence, the following Triggered Update will be fired, but will not send
1206  // any route update.
1207 
1210 }
1211 
1213 {
1214  NS_LOG_FUNCTION (this);
1215 
1217  {
1219  }
1220 
1221  DoSendRouteUpdate (true);
1222 
1225 }
1226 
1227 std::set<uint32_t> Rip::GetInterfaceExclusions () const
1228 {
1229  return m_interfaceExclusions;
1230 }
1231 
1232 void Rip::SetInterfaceExclusions (std::set<uint32_t> exceptions)
1233 {
1234  NS_LOG_FUNCTION (this);
1235 
1236  m_interfaceExclusions = exceptions;
1237 }
1238 
1239 uint8_t Rip::GetInterfaceMetric (uint32_t interface) const
1240 {
1241  NS_LOG_FUNCTION (this << interface);
1242 
1243  std::map<uint32_t, uint8_t>::const_iterator iter = m_interfaceMetrics.find (interface);
1244  if (iter != m_interfaceMetrics.end ())
1245  {
1246  return iter->second;
1247  }
1248  return 1;
1249 }
1250 
1251 void Rip::SetInterfaceMetric (uint32_t interface, uint8_t metric)
1252 {
1253  NS_LOG_FUNCTION (this << interface << int (metric));
1254 
1255  if (metric < m_linkDown)
1256  {
1257  m_interfaceMetrics[interface] = metric;
1258  }
1259 }
1260 
1262 {
1263  NS_LOG_FUNCTION (this);
1264 
1265  Ptr<Packet> p = Create<Packet> ();
1266  SocketIpTtlTag tag;
1267  p->RemovePacketTag (tag);
1268  tag.SetTtl (1);
1269  p->AddPacketTag (tag);
1270 
1271  RipHeader hdr;
1273 
1274  RipRte rte;
1275  rte.SetPrefix (Ipv4Address::GetAny ());
1277  rte.SetRouteMetric (m_linkDown);
1278 
1279  hdr.AddRte (rte);
1280  p->AddHeader (hdr);
1281 
1282  for (SocketListI iter = m_unicastSocketList.begin (); iter != m_unicastSocketList.end (); iter++ )
1283  {
1284  uint32_t interface = iter->second;
1285 
1286  if (m_interfaceExclusions.find (interface) == m_interfaceExclusions.end ())
1287  {
1288  NS_LOG_DEBUG ("SendTo: " << *p);
1289  iter->first->SendTo (p, 0, InetSocketAddress (RIP_ALL_NODE, RIP_PORT));
1290  }
1291  }
1292 }
1293 
1294 void Rip::AddDefaultRouteTo (Ipv4Address nextHop, uint32_t interface)
1295 {
1296  NS_LOG_FUNCTION (this << interface);
1297 
1298  AddNetworkRouteTo (Ipv4Address ("0.0.0.0"), Ipv4Mask::GetZero (), nextHop, interface);
1299 }
1300 
1301 
1302 /*
1303  * RipRoutingTableEntry
1304  */
1305 
1307  : m_tag (0), m_metric (0), m_status (RIP_INVALID), m_changed (false)
1308 {
1309 }
1310 
1311 RipRoutingTableEntry::RipRoutingTableEntry (Ipv4Address network, Ipv4Mask networkPrefix, Ipv4Address nextHop, uint32_t interface)
1312  : Ipv4RoutingTableEntry ( Ipv4RoutingTableEntry::CreateNetworkRouteTo (network, networkPrefix, nextHop, interface) ),
1313  m_tag (0), m_metric (0), m_status (RIP_INVALID), m_changed (false)
1314 {
1315 }
1316 
1317 RipRoutingTableEntry::RipRoutingTableEntry (Ipv4Address network, Ipv4Mask networkPrefix, uint32_t interface)
1318  : Ipv4RoutingTableEntry ( Ipv4RoutingTableEntry::CreateNetworkRouteTo (network, networkPrefix, interface) ),
1319  m_tag (0), m_metric (0), m_status (RIP_INVALID), m_changed (false)
1320 {
1321 }
1322 
1324 {
1325 }
1326 
1327 
1328 void RipRoutingTableEntry::SetRouteTag (uint16_t routeTag)
1329 {
1330  if (m_tag != routeTag)
1331  {
1332  m_tag = routeTag;
1333  m_changed = true;
1334  }
1335 }
1336 
1338 {
1339  return m_tag;
1340 }
1341 
1342 void RipRoutingTableEntry::SetRouteMetric (uint8_t routeMetric)
1343 {
1344  if (m_metric != routeMetric)
1345  {
1346  m_metric = routeMetric;
1347  m_changed = true;
1348  }
1349 }
1350 
1352 {
1353  return m_metric;
1354 }
1355 
1357 {
1358  if (m_status != status)
1359  {
1360  m_status = status;
1361  m_changed = true;
1362  }
1363 }
1364 
1366 {
1367  return m_status;
1368 }
1369 
1371 {
1372  m_changed = changed;
1373 }
1374 
1376 {
1377  return m_changed;
1378 }
1379 
1380 
1381 std::ostream & operator << (std::ostream& os, const RipRoutingTableEntry& rte)
1382 {
1383  os << static_cast<const Ipv4RoutingTableEntry &>(rte);
1384  os << ", metric: " << int (rte.GetRouteMetric ()) << ", tag: " << int (rte.GetRouteTag ());
1385 
1386  return os;
1387 }
1388 
1389 
1390 }
1391 
a polymophic address class
Definition: address.h:91
Callback template class.
Definition: callback.h:1279
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:1386
Hold variables of type enum.
Definition: enum.h:55
An identifier for simulation events.
Definition: event-id.h:54
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:71
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:53
an Inet address class
uint16_t GetPort(void) const
Ipv4Address GetIpv4(void) const
static InetSocketAddress ConvertFrom(const Address &address)
Returns an InetSocketAddress which corresponds to the input Address.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
bool IsMulticast(void) const
bool IsBroadcast(void) const
static Ipv4Address GetAny(void)
bool IsLocalMulticast(void) const
Ipv4Address CombineMask(Ipv4Mask const &mask) const
Combine this address with a network mask.
static Ipv4Address GetZero(void)
bool IsAny(void) const
Packet header for IPv4.
Definition: ipv4-header.h:34
virtual uint32_t GetSerializedSize(void) const
Definition: ipv4-header.cc:375
Ipv4Address GetSource(void) const
Definition: ipv4-header.cc:291
Ipv4Address GetDestination(void) const
Definition: ipv4-header.cc:304
a class to store IPv4 address information on an interface
Ipv4InterfaceAddress::InterfaceAddressScope_e GetScope(void) const
Get address scope.
Ipv4Mask GetMask(void) const
Get the network mask.
Ipv4Address GetLocal(void) const
Get the local address.
a class to represent an Ipv4 address mask
Definition: ipv4-address.h:256
uint16_t GetPrefixLength(void) const
static Ipv4Mask GetZero(void)
bool IsMatch(Ipv4Address a, Ipv4Address b) const
This class implements Linux struct pktinfo in order to deliver ancillary information to the socket in...
uint32_t GetRecvIf(void) const
Get the tag's receiving interface.
Abstract base class for IPv4 routing protocols.
A record of an IPv4 routing table entry for Ipv4GlobalRouting and Ipv4StaticRouting.
bool IsHost(void) const
uint32_t GetInterface(void) const
bool IsGateway(void) const
Ipv4Address GetDestNetwork(void) const
Ipv4Address GetDest(void) const
Ipv4Mask GetDestNetworkMask(void) const
Ipv4Address GetGateway(void) const
static std::string FindName(Ptr< Object > object)
Given a pointer to an object, look to see if that object has a name associated with it and,...
Definition: names.cc:817
A network Node.
Definition: node.h:57
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
Definition: node.cc:144
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:346
virtual void DoInitialize(void)
Initialize() implementation.
Definition: object.cc:353
std::ostream * GetStream(void)
Return a pointer to an ostream previously set in the wrapper.
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:963
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:956
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:74
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
RipHeader - see RFC 2453
Definition: rip-header.h:158
std::list< RipRte > GetRteList(void) const
Get the list of the RTEs included in the message.
Definition: rip-header.cc:272
void AddRte(RipRte rte)
Add a RTE to the message.
Definition: rip-header.cc:257
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
Definition: rip-header.cc:187
void SetCommand(Command_e command)
Set the command.
Definition: rip-header.cc:247
void ClearRtes()
Clear all the RTEs from the header.
Definition: rip-header.cc:262
uint16_t GetRteNumber(void) const
Get the number of RTE included in the message.
Definition: rip-header.cc:267
Command_e GetCommand(void) const
Get the command.
Definition: rip-header.cc:252
RIP Routing Protocol, defined in RFC 2453.
Definition: rip.h:174
std::map< Ptr< Socket >, uint32_t >::iterator SocketListI
Socket list type iterator.
Definition: rip.h:389
void SetInterfaceMetric(uint32_t interface, uint8_t metric)
Set the metric for an interface.
Definition: rip.cc:1251
void DoSendRouteUpdate(bool periodic)
Send Routing Updates on all interfaces.
Definition: rip.cc:1091
virtual void NotifyInterfaceDown(uint32_t interface)
Definition: rip.cc:376
std::list< std::pair< RipRoutingTableEntry *, EventId > >::const_iterator RoutesCI
Const Iterator for container for the network routes.
Definition: rip.h:271
SplitHorizonType_e m_splitHorizonStrategy
Split Horizon strategy.
Definition: rip.h:404
Rip()
Definition: rip.cc:46
Time m_startupDelay
Random delay before protocol startup.
Definition: rip.h:377
std::map< uint32_t, uint8_t > m_interfaceMetrics
Map of interface metrics.
Definition: rip.h:402
virtual ~Rip()
Definition: rip.cc:52
std::set< uint32_t > m_interfaceExclusions
Set of excluded interfaces.
Definition: rip.h:401
uint32_t m_linkDown
Link down value.
Definition: rip.h:407
void HandleRequests(RipHeader hdr, Ipv4Address senderAddress, uint16_t senderPort, uint32_t incomingInterface, uint8_t hopLimit)
Handle RIP requests.
Definition: rip.cc:789
bool RouteInput(Ptr< const Packet > p, const Ipv4Header &header, Ptr< const NetDevice > idev, UnicastForwardCallback ucb, MulticastForwardCallback mcb, LocalDeliverCallback lcb, ErrorCallback ecb)
Route an input packet (to be forwarded or locally delivered)
Definition: rip.cc:219
void DeleteRoute(RipRoutingTableEntry *route)
Delete a route.
Definition: rip.cc:707
void InvalidateRoute(RipRoutingTableEntry *route)
Invalidate a route.
Definition: rip.cc:685
void Receive(Ptr< Socket > socket)
Receive RIP packets.
Definition: rip.cc:724
Ptr< Ipv4Route > Lookup(Ipv4Address dest, bool setSource, Ptr< NetDevice >=0)
Lookup in the forwarding table for destination.
Definition: rip.cc:584
virtual void DoDispose()
Dispose this object.
Definition: rip.cc:555
virtual void NotifyInterfaceUp(uint32_t interface)
Definition: rip.cc:293
EventId m_nextUnsolicitedUpdate
Next Unsolicited Update event.
Definition: rip.h:396
Ptr< Ipv4Route > RouteOutput(Ptr< Packet > p, const Ipv4Header &header, Ptr< NetDevice > oif, Socket::SocketErrno &sockerr)
Query routing cache for an existing route, for an outbound packet.
Definition: rip.cc:189
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
Definition: rip.cc:101
void DoInitialize()
Start protocol operation.
Definition: rip.cc:109
virtual void NotifyRemoveAddress(uint32_t interface, Ipv4InterfaceAddress address)
Definition: rip.cc:432
EventId m_nextTriggeredUpdate
Next Triggered Update event.
Definition: rip.h:397
Ptr< Ipv4 > m_ipv4
IPv4 reference.
Definition: rip.h:376
void SendRouteRequest()
Send Routing Request on all interfaces.
Definition: rip.cc:1261
std::list< std::pair< RipRoutingTableEntry *, EventId > >::iterator RoutesI
Iterator for container for the network routes.
Definition: rip.h:274
Time m_timeoutDelay
Delay before invalidating a route.
Definition: rip.h:381
void AddNetworkRouteTo(Ipv4Address network, Ipv4Mask networkPrefix, Ipv4Address nextHop, uint32_t interface)
Add route to network.
Definition: rip.cc:661
Ptr< Socket > m_multicastRecvSocket
multicast receive socket
Definition: rip.h:394
Time m_minTriggeredUpdateDelay
Min cooldown delay after a Triggered Update.
Definition: rip.h:378
virtual void NotifyAddAddress(uint32_t interface, Ipv4InterfaceAddress address)
Definition: rip.cc:407
@ SPLIT_HORIZON
Split Horizon.
Definition: rip.h:204
@ NO_SPLIT_HORIZON
No Split Horizon.
Definition: rip.h:203
@ POISON_REVERSE
Poison Reverse Split Horizon.
Definition: rip.h:205
Time m_unsolicitedUpdate
time between two Unsolicited Routing Updates
Definition: rip.h:380
std::set< uint32_t > GetInterfaceExclusions() const
Get the set of interface excluded from the protocol.
Definition: rip.cc:1227
virtual void SetIpv4(Ptr< Ipv4 > ipv4)
Definition: rip.cc:469
virtual void PrintRoutingTable(Ptr< OutputStreamWrapper > stream, Time::Unit unit=Time::S) const
Print the Routing Table entries.
Definition: rip.cc:490
uint8_t GetInterfaceMetric(uint32_t interface) const
Get the metric for an interface.
Definition: rip.cc:1239
static TypeId GetTypeId(void)
Get the type ID.
Definition: rip.cc:57
SocketList m_unicastSocketList
list of sockets for unicast messages (socket, interface index)
Definition: rip.h:393
Time m_garbageCollectionDelay
Delay before deleting an INVALID route.
Definition: rip.h:382
bool m_initialized
flag to allow socket's late-creation.
Definition: rip.h:406
void SetInterfaceExclusions(std::set< uint32_t > exceptions)
Set the set of interface excluded from the protocol.
Definition: rip.cc:1232
void AddDefaultRouteTo(Ipv4Address nextHop, uint32_t interface)
Add a default route to the router through the nextHop located on interface.
Definition: rip.cc:1294
void SendUnsolicitedRouteUpdate(void)
Send Unsolicited Routing Updates on all interfaces.
Definition: rip.cc:1212
Routes m_routes
the forwarding table for network.
Definition: rip.h:375
Time m_maxTriggeredUpdateDelay
Max cooldown delay after a Triggered Update.
Definition: rip.h:379
void SendTriggeredRouteUpdate()
Send Triggered Routing Updates on all interfaces.
Definition: rip.cc:1182
void HandleResponses(RipHeader hdr, Ipv4Address senderAddress, uint32_t incomingInterface, uint8_t hopLimit)
Handle RIP responses.
Definition: rip.cc:951
Ptr< UniformRandomVariable > m_rng
Rng stream.
Definition: rip.h:399
Rip Routing Table Entry.
Definition: rip.h:64
void SetRouteMetric(uint8_t routeMetric)
Set the route metric.
Definition: rip.cc:1342
Status_e m_status
route status
Definition: rip.h:153
uint8_t GetRouteMetric(void) const
Get the route metric.
Definition: rip.cc:1351
bool m_changed
route has been updated
Definition: rip.h:154
void SetRouteStatus(Status_e status)
Set the route status.
Definition: rip.cc:1356
Status_e
Route status.
Definition: rip.h:70
@ RIP_INVALID
Definition: rip.h:72
@ RIP_VALID
Definition: rip.h:71
bool IsRouteChanged(void) const
Get the route changed status.
Definition: rip.cc:1375
void SetRouteTag(uint16_t routeTag)
Set the route tag.
Definition: rip.cc:1328
uint16_t GetRouteTag(void) const
Get the route tag.
Definition: rip.cc:1337
void SetRouteChanged(bool changed)
Set the route as changed.
Definition: rip.cc:1370
Status_e GetRouteStatus(void) const
Get the route status.
Definition: rip.cc:1365
uint8_t m_metric
route metric
Definition: rip.h:152
RipRoutingTableEntry(void)
Definition: rip.cc:1306
virtual ~RipRoutingTableEntry()
Definition: rip.cc:1323
uint16_t m_tag
route tag
Definition: rip.h:151
Rip v2 Routing Table Entry (RTE) - see RFC 2453.
Definition: rip-header.h:38
void SetSubnetMask(Ipv4Mask subnetMask)
Set the subnet mask.
Definition: rip-header.cc:103
void SetRouteMetric(uint32_t routeMetric)
Set the route metric.
Definition: rip-header.cc:123
void SetPrefix(Ipv4Address prefix)
Set the prefix.
Definition: rip-header.cc:93
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
Definition: rip-header.cc:57
void SetRouteTag(uint16_t routeTag)
Set the route tag.
Definition: rip-header.cc:113
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:556
static Time GetDelayLeft(const EventId &id)
Get the remaining time until this event will execute.
Definition: simulator.cc:204
void SetRecvPktInfo(bool flag)
Enable/Disable receive packet information to socket.
Definition: socket.cc:358
virtual void BindToNetDevice(Ptr< NetDevice > netdevice)
Bind a socket to specific device.
Definition: socket.cc:330
virtual int Close(void)=0
Close a socket.
void SetRecvCallback(Callback< void, Ptr< Socket > > receivedData)
Notify application when new data is available to be read.
Definition: socket.cc:128
static Ptr< Socket > CreateSocket(Ptr< Node > node, TypeId tid)
This method wraps the creation of sockets that is performed on a given node by a SocketFactory specif...
Definition: socket.cc:71
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:82
@ ERROR_NOROUTETOHOST
Definition: socket.h:93
@ ERROR_NOTERROR
Definition: socket.h:83
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
void SetIpRecvTtl(bool ipv4RecvTtl)
Tells a socket to pass information about IP_TTL up the stack.
Definition: socket.cc:526
virtual Ptr< Packet > RecvFrom(uint32_t maxSize, uint32_t flags, Address &fromAddress)=0
Read a single packet from the socket and retrieve the sender address.
virtual int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress)=0
Send data to a specified peer.
This class implements a tag that carries the socket-specific TTL of a packet to the IP layer.
Definition: socket.h:1117
uint8_t GetTtl(void) const
Get the tag's TTL.
Definition: socket.cc:611
void SetTtl(uint8_t ttl)
Set the tag's TTL.
Definition: socket.cc:604
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:379
Unit
The unit to use to interpret a number representing time.
Definition: nstime.h:109
TimeWithUnit As(const enum Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:418
AttributeValue implementation for Time.
Definition: nstime.h:1308
a unique identifier for an interface.
Definition: type-id.h:59
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:829
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
Packet header for UDP packets.
Definition: udp-header.h:40
virtual uint32_t GetSerializedSize(void) const
Definition: udp-header.cc:178
Hold an unsigned integer type.
Definition: uinteger.h:44
double GetValue(double min, double max)
Get the next random value, as a double in the specified range .
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:88
Ptr< const AttributeAccessor > MakeEnumAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: enum.h:205
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: nstime.h:1309
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: uinteger.h:45
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:281
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:287
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
Definition: first.py:1
address
Definition: first.py:44
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeEnumChecker(int v, std::string n, Ts... args)
Make an EnumChecker pre-configured with a set of allowed values by name.
Definition: enum.h:162
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:522
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:139
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1648
Definition: second.py:1
#define RIP_ALL_NODE
Definition: rip.cc:37
#define RIP_PORT
Definition: rip.cc:38