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