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 "ipv4-packet-info-tag.h"
23 #include "ipv4-route.h"
24 #include "loopback-net-device.h"
25 #include "rip-header.h"
26 #include "udp-header.h"
27 
28 #include "ns3/abort.h"
29 #include "ns3/assert.h"
30 #include "ns3/enum.h"
31 #include "ns3/log.h"
32 #include "ns3/names.h"
33 #include "ns3/node.h"
34 #include "ns3/random-variable-stream.h"
35 #include "ns3/uinteger.h"
36 
37 #include <iomanip>
38 
39 #define RIP_ALL_NODE "224.0.0.9"
40 #define RIP_PORT 520
41 
42 namespace ns3
43 {
44 
46 
48 
50  : m_ipv4(nullptr),
51  m_splitHorizonStrategy(Rip::POISON_REVERSE),
52  m_initialized(false)
53 {
54  m_rng = CreateObject<UniformRandomVariable>();
55 }
56 
58 {
59 }
60 
61 TypeId
63 {
64  static TypeId tid =
65  TypeId("ns3::Rip")
67  .SetGroupName("Internet")
68  .AddConstructor<Rip>()
69  .AddAttribute("UnsolicitedRoutingUpdate",
70  "The time between two Unsolicited Routing Updates.",
71  TimeValue(Seconds(30)),
74  .AddAttribute("StartupDelay",
75  "Maximum random delay for protocol startup (send route requests).",
76  TimeValue(Seconds(1)),
79  .AddAttribute("TimeoutDelay",
80  "The delay to invalidate a route.",
81  TimeValue(Seconds(180)),
84  .AddAttribute("GarbageCollectionDelay",
85  "The delay to delete an expired route.",
86  TimeValue(Seconds(120)),
89  .AddAttribute("MinTriggeredCooldown",
90  "Min cooldown delay after a Triggered Update.",
91  TimeValue(Seconds(1)),
94  .AddAttribute("MaxTriggeredCooldown",
95  "Max cooldown delay after a Triggered Update.",
96  TimeValue(Seconds(5)),
99  .AddAttribute("SplitHorizon",
100  "Split Horizon strategy.",
102  MakeEnumAccessor<SplitHorizonType_e>(&Rip::m_splitHorizonStrategy),
104  "NoSplitHorizon",
106  "SplitHorizon",
108  "PoisonReverse"))
109  .AddAttribute("LinkDownValue",
110  "Value for link down in count to infinity.",
111  UintegerValue(16),
113  MakeUintegerChecker<uint32_t>());
114  return tid;
115 }
116 
117 int64_t
118 Rip::AssignStreams(int64_t stream)
119 {
120  NS_LOG_FUNCTION(this << stream);
121 
122  m_rng->SetStream(stream);
123  return 1;
124 }
125 
126 void
128 {
129  NS_LOG_FUNCTION(this);
130 
131  bool addedGlobal = false;
132 
133  m_initialized = true;
134 
135  Time delay =
138 
139  for (uint32_t i = 0; i < m_ipv4->GetNInterfaces(); i++)
140  {
141  Ptr<LoopbackNetDevice> check = DynamicCast<LoopbackNetDevice>(m_ipv4->GetNetDevice(i));
142  if (check)
143  {
144  continue;
145  }
146 
147  bool activeInterface = false;
148  if (m_interfaceExclusions.find(i) == m_interfaceExclusions.end())
149  {
150  activeInterface = true;
151  m_ipv4->SetForwarding(i, true);
152  }
153 
154  for (uint32_t j = 0; j < m_ipv4->GetNAddresses(i); j++)
155  {
156  Ipv4InterfaceAddress address = m_ipv4->GetAddress(i, j);
157  if (address.GetScope() != Ipv4InterfaceAddress::HOST && activeInterface)
158  {
159  NS_LOG_LOGIC("RIP: adding socket to " << address.GetLocal());
160  TypeId tid = TypeId::LookupByName("ns3::UdpSocketFactory");
161  Ptr<Node> theNode = GetObject<Node>();
162  Ptr<Socket> socket = Socket::CreateSocket(theNode, tid);
164  socket->BindToNetDevice(m_ipv4->GetNetDevice(i));
165  int ret = socket->Bind(local);
166  NS_ASSERT_MSG(ret == 0, "Bind unsuccessful");
167 
168  socket->SetRecvCallback(MakeCallback(&Rip::Receive, this));
169  socket->SetIpRecvTtl(true);
170  socket->SetRecvPktInfo(true);
171 
172  m_unicastSocketList[socket] = i;
173  }
174  else if (m_ipv4->GetAddress(i, j).GetScope() == Ipv4InterfaceAddress::GLOBAL)
175  {
176  addedGlobal = true;
177  }
178  }
179  }
180 
182  {
183  NS_LOG_LOGIC("RIP: adding receiving socket");
184  TypeId tid = TypeId::LookupByName("ns3::UdpSocketFactory");
185  Ptr<Node> theNode = GetObject<Node>();
188  m_multicastRecvSocket->Bind(local);
192  }
193 
194  if (addedGlobal)
195  {
199  }
200 
201  delay = Seconds(m_rng->GetValue(0.01, m_startupDelay.GetSeconds()));
203 
205 }
206 
209  const Ipv4Header& header,
210  Ptr<NetDevice> oif,
211  Socket::SocketErrno& sockerr)
212 {
213  NS_LOG_FUNCTION(this << header << oif);
214 
215  Ipv4Address destination = header.GetDestination();
216  Ptr<Ipv4Route> rtentry = nullptr;
217 
218  if (destination.IsMulticast())
219  {
220  // Note: Multicast routes for outbound packets are stored in the
221  // normal unicast table. An implication of this is that it is not
222  // possible to source multicast datagrams on multiple interfaces.
223  // This is a well-known property of sockets implementation on
224  // many Unix variants.
225  // So, we just log it and fall through to LookupStatic ()
226  NS_LOG_LOGIC("RouteOutput (): Multicast destination");
227  }
228 
229  rtentry = Lookup(destination, true, oif);
230  if (rtentry)
231  {
232  sockerr = Socket::ERROR_NOTERROR;
233  }
234  else
235  {
236  sockerr = Socket::ERROR_NOROUTETOHOST;
237  }
238  return rtentry;
239 }
240 
241 bool
243  const Ipv4Header& header,
245  const UnicastForwardCallback& ucb,
246  const MulticastForwardCallback& mcb,
247  const LocalDeliverCallback& lcb,
248  const ErrorCallback& ecb)
249 {
250  NS_LOG_FUNCTION(this << p << header << header.GetSource() << header.GetDestination() << idev);
251 
252  NS_ASSERT(m_ipv4);
253  // Check if input device supports IP
254  NS_ASSERT(m_ipv4->GetInterfaceForDevice(idev) >= 0);
255  uint32_t iif = m_ipv4->GetInterfaceForDevice(idev);
256  Ipv4Address dst = header.GetDestination();
257 
258  if (m_ipv4->IsDestinationAddress(header.GetDestination(), iif))
259  {
260  if (!lcb.IsNull())
261  {
262  NS_LOG_LOGIC("Local delivery to " << header.GetDestination());
263  lcb(p, header, iif);
264  return true;
265  }
266  else
267  {
268  // The local delivery callback is null. This may be a multicast
269  // or broadcast packet, so return false so that another
270  // multicast routing protocol can handle it. It should be possible
271  // to extend this to explicitly check whether it is a unicast
272  // packet, and invoke the error callback if so
273  return false;
274  }
275  }
276 
277  if (dst.IsMulticast())
278  {
279  NS_LOG_LOGIC("Multicast route not supported by RIP");
280  return false; // Let other routing protocols try to handle this
281  }
282 
283  if (header.GetDestination().IsBroadcast())
284  {
285  NS_LOG_LOGIC("Dropping packet not for me and with dst Broadcast");
286  if (!ecb.IsNull())
287  {
288  ecb(p, header, Socket::ERROR_NOROUTETOHOST);
289  }
290  return false;
291  }
292 
293  // Check if input device supports IP forwarding
294  if (!m_ipv4->IsForwarding(iif))
295  {
296  NS_LOG_LOGIC("Forwarding disabled for this interface");
297  if (!ecb.IsNull())
298  {
299  ecb(p, header, Socket::ERROR_NOROUTETOHOST);
300  }
301  return true;
302  }
303  // Next, try to find a route
304  NS_LOG_LOGIC("Unicast destination");
305  Ptr<Ipv4Route> rtentry = Lookup(header.GetDestination(), false);
306 
307  if (rtentry)
308  {
309  NS_LOG_LOGIC("Found unicast destination - calling unicast callback");
310  ucb(rtentry, p, header); // unicast forwarding callback
311  return true;
312  }
313  else
314  {
315  NS_LOG_LOGIC("Did not find unicast destination - returning false");
316  return false; // Let other routing protocols try to handle this
317  }
318 }
319 
320 void
322 {
323  NS_LOG_FUNCTION(this << i);
324 
325  Ptr<LoopbackNetDevice> check = DynamicCast<LoopbackNetDevice>(m_ipv4->GetNetDevice(i));
326  if (check)
327  {
328  return;
329  }
330 
331  for (uint32_t j = 0; j < m_ipv4->GetNAddresses(i); j++)
332  {
333  Ipv4InterfaceAddress address = m_ipv4->GetAddress(i, j);
334  Ipv4Mask networkMask = address.GetMask();
335  Ipv4Address networkAddress = address.GetLocal().CombineMask(networkMask);
336 
337  if (address.GetScope() == Ipv4InterfaceAddress::GLOBAL)
338  {
339  AddNetworkRouteTo(networkAddress, networkMask, i);
340  }
341  }
342 
343  if (!m_initialized)
344  {
345  return;
346  }
347 
348  bool sendSocketFound = false;
349  for (auto iter = m_unicastSocketList.begin(); iter != m_unicastSocketList.end(); iter++)
350  {
351  if (iter->second == i)
352  {
353  sendSocketFound = true;
354  break;
355  }
356  }
357 
358  bool activeInterface = false;
359  if (m_interfaceExclusions.find(i) == m_interfaceExclusions.end())
360  {
361  activeInterface = true;
362  m_ipv4->SetForwarding(i, true);
363  }
364 
365  for (uint32_t j = 0; j < m_ipv4->GetNAddresses(i); j++)
366  {
367  Ipv4InterfaceAddress address = m_ipv4->GetAddress(i, j);
368 
369  if (address.GetScope() != Ipv4InterfaceAddress::HOST && !sendSocketFound && activeInterface)
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 (auto 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 (auto 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 (auto 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 (auto 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 (auto 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 (auto 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 (auto 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  auto route = new RipRoutingTableEntry(network, networkPrefix, nextHop, interface);
712  route->SetRouteMetric(1);
713  route->SetRouteStatus(RipRoutingTableEntry::RIP_VALID);
714  route->SetRouteChanged(true);
715 
716  m_routes.emplace_back(route, EventId());
717 }
718 
719 void
720 Rip::AddNetworkRouteTo(Ipv4Address network, Ipv4Mask networkPrefix, uint32_t interface)
721 {
722  NS_LOG_FUNCTION(this << network << networkPrefix << interface);
723 
724  auto route = new RipRoutingTableEntry(network, networkPrefix, interface);
725  route->SetRouteMetric(1);
726  route->SetRouteStatus(RipRoutingTableEntry::RIP_VALID);
727  route->SetRouteChanged(true);
728 
729  m_routes.emplace_back(route, EventId());
730 }
731 
732 void
734 {
735  NS_LOG_FUNCTION(this << *route);
736 
737  for (auto it = m_routes.begin(); it != m_routes.end(); it++)
738  {
739  if (it->first == route)
740  {
742  route->SetRouteMetric(m_linkDown);
743  route->SetRouteChanged(true);
744  if (it->second.IsRunning())
745  {
746  it->second.Cancel();
747  }
748  it->second =
750  return;
751  }
752  }
753  NS_ABORT_MSG("RIP::InvalidateRoute - cannot find the route to update");
754 }
755 
756 void
758 {
759  NS_LOG_FUNCTION(this << *route);
760 
761  for (auto it = m_routes.begin(); it != m_routes.end(); it++)
762  {
763  if (it->first == route)
764  {
765  delete route;
766  m_routes.erase(it);
767  return;
768  }
769  }
770  NS_ABORT_MSG("RIP::DeleteRoute - cannot find the route to delete");
771 }
772 
773 void
775 {
776  NS_LOG_FUNCTION(this << socket);
777 
778  Address sender;
779  Ptr<Packet> packet = socket->RecvFrom(sender);
781  NS_LOG_INFO("Received " << *packet << " from " << senderAddr.GetIpv4() << ":"
782  << senderAddr.GetPort());
783 
784  Ipv4Address senderAddress = senderAddr.GetIpv4();
785  uint16_t senderPort = senderAddr.GetPort();
786 
787  if (socket == m_multicastRecvSocket)
788  {
789  NS_LOG_LOGIC("Received a packet from the multicast socket");
790  }
791  else
792  {
793  NS_LOG_LOGIC("Received a packet from one of the unicast sockets");
794  }
795 
796  Ipv4PacketInfoTag interfaceInfo;
797  if (!packet->RemovePacketTag(interfaceInfo))
798  {
799  NS_ABORT_MSG("No incoming interface on RIP message, aborting.");
800  }
801  uint32_t incomingIf = interfaceInfo.GetRecvIf();
802  Ptr<Node> node = this->GetObject<Node>();
803  Ptr<NetDevice> dev = node->GetDevice(incomingIf);
804  uint32_t ipInterfaceIndex = m_ipv4->GetInterfaceForDevice(dev);
805 
806  SocketIpTtlTag hoplimitTag;
807  if (!packet->RemovePacketTag(hoplimitTag))
808  {
809  NS_ABORT_MSG("No incoming Hop Count on RIP message, aborting.");
810  }
811  uint8_t hopLimit = hoplimitTag.GetTtl();
812 
813  int32_t interfaceForAddress = m_ipv4->GetInterfaceForAddress(senderAddress);
814  if (interfaceForAddress != -1)
815  {
816  NS_LOG_LOGIC("Ignoring a packet sent by myself.");
817  return;
818  }
819 
820  RipHeader hdr;
821  packet->RemoveHeader(hdr);
822 
823  if (hdr.GetCommand() == RipHeader::RESPONSE)
824  {
825  NS_LOG_LOGIC("The message is a Response from " << senderAddr.GetIpv4() << ":"
826  << senderAddr.GetPort());
827  HandleResponses(hdr, senderAddress, ipInterfaceIndex, hopLimit);
828  }
829  else if (hdr.GetCommand() == RipHeader::REQUEST)
830  {
831  NS_LOG_LOGIC("The message is a Request from " << senderAddr.GetIpv4() << ":"
832  << senderAddr.GetPort());
833  HandleRequests(hdr, senderAddress, senderPort, ipInterfaceIndex, hopLimit);
834  }
835  else
836  {
837  NS_LOG_LOGIC("Ignoring message with unknown command: " << int(hdr.GetCommand()));
838  }
839 }
840 
841 void
843  Ipv4Address senderAddress,
844  uint16_t senderPort,
845  uint32_t incomingInterface,
846  uint8_t hopLimit)
847 {
848  NS_LOG_FUNCTION(this << senderAddress << int(senderPort) << incomingInterface << int(hopLimit)
849  << requestHdr);
850 
851  std::list<RipRte> rtes = requestHdr.GetRteList();
852 
853  if (rtes.empty())
854  {
855  return;
856  }
857 
858  // check if it's a request for the full table from a neighbor
859  if (rtes.size() == 1)
860  {
861  if (rtes.begin()->GetPrefix() == Ipv4Address::GetAny() &&
862  rtes.begin()->GetSubnetMask().GetPrefixLength() == 0 &&
863  rtes.begin()->GetRouteMetric() == m_linkDown)
864  {
865  // Output whole thing. Use Split Horizon
866  if (m_interfaceExclusions.find(incomingInterface) == m_interfaceExclusions.end())
867  {
868  // we use one of the sending sockets, as they're bound to the right interface
869  // and the local address might be used on different interfaces.
870  Ptr<Socket> sendingSocket;
871  for (auto iter = m_unicastSocketList.begin(); iter != m_unicastSocketList.end();
872  iter++)
873  {
874  if (iter->second == incomingInterface)
875  {
876  sendingSocket = iter->first;
877  }
878  }
879  NS_ASSERT_MSG(sendingSocket,
880  "HandleRequest - Impossible to find a socket to send the reply");
881 
882  uint16_t mtu = m_ipv4->GetMtu(incomingInterface);
883  uint16_t maxRte =
887 
888  Ptr<Packet> p = Create<Packet>();
889  SocketIpTtlTag tag;
890  p->RemovePacketTag(tag);
891  if (senderAddress == Ipv4Address(RIP_ALL_NODE))
892  {
893  tag.SetTtl(1);
894  }
895  else
896  {
897  tag.SetTtl(255);
898  }
899  p->AddPacketTag(tag);
900 
901  RipHeader hdr;
903 
904  for (auto rtIter = m_routes.begin(); rtIter != m_routes.end(); rtIter++)
905  {
906  bool splitHorizoning = (rtIter->first->GetInterface() == incomingInterface);
907 
908  Ipv4InterfaceAddress rtDestAddr =
909  Ipv4InterfaceAddress(rtIter->first->GetDestNetwork(),
910  rtIter->first->GetDestNetworkMask());
911 
912  bool isGlobal = (rtDestAddr.GetScope() == Ipv4InterfaceAddress::GLOBAL);
913  bool isDefaultRoute =
914  ((rtIter->first->GetDestNetwork() == Ipv4Address::GetAny()) &&
915  (rtIter->first->GetDestNetworkMask() == Ipv4Mask::GetZero()) &&
916  (rtIter->first->GetInterface() != incomingInterface));
917 
918  if ((isGlobal || isDefaultRoute) &&
919  (rtIter->first->GetRouteStatus() == RipRoutingTableEntry::RIP_VALID))
920  {
921  RipRte rte;
922  rte.SetPrefix(rtIter->first->GetDestNetwork());
923  rte.SetSubnetMask(rtIter->first->GetDestNetworkMask());
924  if (m_splitHorizonStrategy == POISON_REVERSE && splitHorizoning)
925  {
927  }
928  else
929  {
930  rte.SetRouteMetric(rtIter->first->GetRouteMetric());
931  }
932  rte.SetRouteTag(rtIter->first->GetRouteTag());
934  (m_splitHorizonStrategy == SPLIT_HORIZON && !splitHorizoning))
935  {
936  hdr.AddRte(rte);
937  }
938  }
939  if (hdr.GetRteNumber() == maxRte)
940  {
941  p->AddHeader(hdr);
942  NS_LOG_DEBUG("SendTo: " << *p);
943  sendingSocket->SendTo(p, 0, InetSocketAddress(senderAddress, RIP_PORT));
944  p->RemoveHeader(hdr);
945  hdr.ClearRtes();
946  }
947  }
948  if (hdr.GetRteNumber() > 0)
949  {
950  p->AddHeader(hdr);
951  NS_LOG_DEBUG("SendTo: " << *p);
952  sendingSocket->SendTo(p, 0, InetSocketAddress(senderAddress, RIP_PORT));
953  }
954  }
955  }
956  }
957  else
958  {
959  // note: we got the request as a single packet, so no check is necessary for MTU limit
960 
961  Ptr<Packet> p = Create<Packet>();
962  SocketIpTtlTag tag;
963  p->RemovePacketTag(tag);
964  if (senderAddress == Ipv4Address(RIP_ALL_NODE))
965  {
966  tag.SetTtl(1);
967  }
968  else
969  {
970  tag.SetTtl(255);
971  }
972  p->AddPacketTag(tag);
973 
974  RipHeader hdr;
976 
977  for (auto iter = rtes.begin(); iter != rtes.end(); iter++)
978  {
979  bool found = false;
980  for (auto rtIter = m_routes.begin(); rtIter != m_routes.end(); rtIter++)
981  {
982  Ipv4InterfaceAddress rtDestAddr =
983  Ipv4InterfaceAddress(rtIter->first->GetDestNetwork(),
984  rtIter->first->GetDestNetworkMask());
985  if ((rtDestAddr.GetScope() == Ipv4InterfaceAddress::GLOBAL) &&
986  (rtIter->first->GetRouteStatus() == RipRoutingTableEntry::RIP_VALID))
987  {
988  Ipv4Address requestedAddress = iter->GetPrefix();
989  requestedAddress.CombineMask(iter->GetSubnetMask());
990  Ipv4Address rtAddress = rtIter->first->GetDestNetwork();
991  rtAddress.CombineMask(rtIter->first->GetDestNetworkMask());
992 
993  if (requestedAddress == rtAddress)
994  {
995  iter->SetRouteMetric(rtIter->first->GetRouteMetric());
996  iter->SetRouteTag(rtIter->first->GetRouteTag());
997  hdr.AddRte(*iter);
998  found = true;
999  break;
1000  }
1001  }
1002  }
1003  if (!found)
1004  {
1005  iter->SetRouteMetric(m_linkDown);
1006  iter->SetRouteTag(0);
1007  hdr.AddRte(*iter);
1008  }
1009  }
1010  p->AddHeader(hdr);
1011  NS_LOG_DEBUG("SendTo: " << *p);
1012  m_multicastRecvSocket->SendTo(p, 0, InetSocketAddress(senderAddress, senderPort));
1013  }
1014 }
1015 
1016 void
1018  Ipv4Address senderAddress,
1019  uint32_t incomingInterface,
1020  uint8_t hopLimit)
1021 {
1022  NS_LOG_FUNCTION(this << senderAddress << incomingInterface << int(hopLimit) << hdr);
1023 
1024  if (m_interfaceExclusions.find(incomingInterface) != m_interfaceExclusions.end())
1025  {
1026  NS_LOG_LOGIC(
1027  "Ignoring an update message from an excluded interface: " << incomingInterface);
1028  return;
1029  }
1030 
1031  std::list<RipRte> rtes = hdr.GetRteList();
1032 
1033  // validate the RTEs before processing
1034  for (auto iter = rtes.begin(); iter != rtes.end(); iter++)
1035  {
1036  if (iter->GetRouteMetric() == 0 || iter->GetRouteMetric() > m_linkDown)
1037  {
1038  NS_LOG_LOGIC("Ignoring an update message with malformed metric: "
1039  << int(iter->GetRouteMetric()));
1040  return;
1041  }
1042  if (iter->GetPrefix().IsLocalhost() || iter->GetPrefix().IsBroadcast() ||
1043  iter->GetPrefix().IsMulticast())
1044  {
1045  NS_LOG_LOGIC("Ignoring an update message with wrong prefixes: " << iter->GetPrefix());
1046  return;
1047  }
1048  }
1049 
1050  bool changed = false;
1051 
1052  for (auto iter = rtes.begin(); iter != rtes.end(); iter++)
1053  {
1054  Ipv4Mask rtePrefixMask = iter->GetSubnetMask();
1055  Ipv4Address rteAddr = iter->GetPrefix().CombineMask(rtePrefixMask);
1056 
1057  NS_LOG_LOGIC("Processing RTE " << *iter);
1058 
1059  uint32_t interfaceMetric = 1;
1060  if (m_interfaceMetrics.find(incomingInterface) != m_interfaceMetrics.end())
1061  {
1062  interfaceMetric = m_interfaceMetrics[incomingInterface];
1063  }
1064  uint64_t rteMetric = iter->GetRouteMetric() + interfaceMetric;
1065  if (rteMetric > m_linkDown)
1066  {
1067  rteMetric = m_linkDown;
1068  }
1069 
1070  RoutesI it;
1071  bool found = false;
1072  for (it = m_routes.begin(); it != m_routes.end(); it++)
1073  {
1074  if (it->first->GetDestNetwork() == rteAddr &&
1075  it->first->GetDestNetworkMask() == rtePrefixMask)
1076  {
1077  found = true;
1078  if (rteMetric < it->first->GetRouteMetric())
1079  {
1080  if (senderAddress != it->first->GetGateway())
1081  {
1082  auto route = new RipRoutingTableEntry(rteAddr,
1083  rtePrefixMask,
1084  senderAddress,
1085  incomingInterface);
1086  delete it->first;
1087  it->first = route;
1088  }
1089  it->first->SetRouteMetric(rteMetric);
1090  it->first->SetRouteStatus(RipRoutingTableEntry::RIP_VALID);
1091  it->first->SetRouteTag(iter->GetRouteTag());
1092  it->first->SetRouteChanged(true);
1093  it->second.Cancel();
1094  it->second =
1096  changed = true;
1097  }
1098  else if (rteMetric == it->first->GetRouteMetric())
1099  {
1100  if (senderAddress == it->first->GetGateway())
1101  {
1102  it->second.Cancel();
1103  it->second = Simulator::Schedule(m_timeoutDelay,
1105  this,
1106  it->first);
1107  }
1108  else
1109  {
1110  if (Simulator::GetDelayLeft(it->second) < m_timeoutDelay / 2)
1111  {
1112  auto route = new RipRoutingTableEntry(rteAddr,
1113  rtePrefixMask,
1114  senderAddress,
1115  incomingInterface);
1116  route->SetRouteMetric(rteMetric);
1117  route->SetRouteStatus(RipRoutingTableEntry::RIP_VALID);
1118  route->SetRouteTag(iter->GetRouteTag());
1119  route->SetRouteChanged(true);
1120  delete it->first;
1121  it->first = route;
1122  it->second.Cancel();
1123  it->second = Simulator::Schedule(m_timeoutDelay,
1125  this,
1126  route);
1127  changed = true;
1128  }
1129  }
1130  }
1131  else if (rteMetric > it->first->GetRouteMetric() &&
1132  senderAddress == it->first->GetGateway())
1133  {
1134  it->second.Cancel();
1135  if (rteMetric < m_linkDown)
1136  {
1137  it->first->SetRouteMetric(rteMetric);
1138  it->first->SetRouteStatus(RipRoutingTableEntry::RIP_VALID);
1139  it->first->SetRouteTag(iter->GetRouteTag());
1140  it->first->SetRouteChanged(true);
1141  it->second.Cancel();
1142  it->second = Simulator::Schedule(m_timeoutDelay,
1144  this,
1145  it->first);
1146  }
1147  else
1148  {
1149  InvalidateRoute(it->first);
1150  }
1151  changed = true;
1152  }
1153  }
1154  }
1155  if (!found && rteMetric != m_linkDown)
1156  {
1157  NS_LOG_LOGIC("Received a RTE with new route, adding.");
1158 
1159  auto route =
1160  new RipRoutingTableEntry(rteAddr, rtePrefixMask, senderAddress, incomingInterface);
1161  route->SetRouteMetric(rteMetric);
1162  route->SetRouteStatus(RipRoutingTableEntry::RIP_VALID);
1163  route->SetRouteChanged(true);
1164  m_routes.emplace_front(route, EventId());
1165  EventId invalidateEvent =
1167  (m_routes.begin())->second = invalidateEvent;
1168  changed = true;
1169  }
1170  }
1171 
1172  if (changed)
1173  {
1175  }
1176 }
1177 
1178 void
1180 {
1181  NS_LOG_FUNCTION(this << (periodic ? " periodic" : " triggered"));
1182 
1183  for (auto iter = m_unicastSocketList.begin(); iter != m_unicastSocketList.end(); iter++)
1184  {
1185  uint32_t interface = iter->second;
1186 
1187  if (m_interfaceExclusions.find(interface) == m_interfaceExclusions.end())
1188  {
1189  uint16_t mtu = m_ipv4->GetMtu(interface);
1190  uint16_t maxRte = (mtu - Ipv4Header().GetSerializedSize() -
1193 
1194  Ptr<Packet> p = Create<Packet>();
1195  SocketIpTtlTag tag;
1196  tag.SetTtl(1);
1197  p->AddPacketTag(tag);
1198 
1199  RipHeader hdr;
1201 
1202  for (auto rtIter = m_routes.begin(); rtIter != m_routes.end(); rtIter++)
1203  {
1204  bool splitHorizoning = (rtIter->first->GetInterface() == interface);
1205  Ipv4InterfaceAddress rtDestAddr =
1206  Ipv4InterfaceAddress(rtIter->first->GetDestNetwork(),
1207  rtIter->first->GetDestNetworkMask());
1208 
1209  NS_LOG_DEBUG("Processing RT " << rtDestAddr << " "
1210  << int(rtIter->first->IsRouteChanged()));
1211 
1212  bool isGlobal = (rtDestAddr.GetScope() == Ipv4InterfaceAddress::GLOBAL);
1213  bool isDefaultRoute =
1214  ((rtIter->first->GetDestNetwork() == Ipv4Address::GetAny()) &&
1215  (rtIter->first->GetDestNetworkMask() == Ipv4Mask::GetZero()) &&
1216  (rtIter->first->GetInterface() != interface));
1217 
1218  bool sameNetwork = false;
1219  for (uint32_t index = 0; index < m_ipv4->GetNAddresses(interface); index++)
1220  {
1221  Ipv4InterfaceAddress addr = m_ipv4->GetAddress(interface, index);
1222  if (addr.GetLocal().CombineMask(addr.GetMask()) ==
1223  rtIter->first->GetDestNetwork())
1224  {
1225  sameNetwork = true;
1226  }
1227  }
1228 
1229  if ((isGlobal || isDefaultRoute) && (periodic || rtIter->first->IsRouteChanged()) &&
1230  !sameNetwork)
1231  {
1232  RipRte rte;
1233  rte.SetPrefix(rtIter->first->GetDestNetwork());
1234  rte.SetSubnetMask(rtIter->first->GetDestNetworkMask());
1235  if (m_splitHorizonStrategy == POISON_REVERSE && splitHorizoning)
1236  {
1238  }
1239  else
1240  {
1241  rte.SetRouteMetric(rtIter->first->GetRouteMetric());
1242  }
1243  rte.SetRouteTag(rtIter->first->GetRouteTag());
1244  if (m_splitHorizonStrategy == SPLIT_HORIZON && !splitHorizoning)
1245  {
1246  hdr.AddRte(rte);
1247  }
1249  {
1250  hdr.AddRte(rte);
1251  }
1252  }
1253  if (hdr.GetRteNumber() == maxRte)
1254  {
1255  p->AddHeader(hdr);
1256  NS_LOG_DEBUG("SendTo: " << *p);
1257  iter->first->SendTo(p, 0, InetSocketAddress(RIP_ALL_NODE, RIP_PORT));
1258  p->RemoveHeader(hdr);
1259  hdr.ClearRtes();
1260  }
1261  }
1262  if (hdr.GetRteNumber() > 0)
1263  {
1264  p->AddHeader(hdr);
1265  NS_LOG_DEBUG("SendTo: " << *p);
1266  iter->first->SendTo(p, 0, InetSocketAddress(RIP_ALL_NODE, RIP_PORT));
1267  }
1268  }
1269  }
1270  for (auto rtIter = m_routes.begin(); rtIter != m_routes.end(); rtIter++)
1271  {
1272  rtIter->first->SetRouteChanged(false);
1273  }
1274 }
1275 
1276 void
1278 {
1279  NS_LOG_FUNCTION(this);
1280 
1282  {
1283  NS_LOG_LOGIC("Skipping Triggered Update due to cooldown");
1284  return;
1285  }
1286 
1287  // DoSendRouteUpdate (false);
1288 
1289  // note: The RFC states:
1290  // After a triggered
1291  // update is sent, a timer should be set for a random interval between 1
1292  // and 5 seconds. If other changes that would trigger updates occur
1293  // before the timer expires, a single update is triggered when the timer
1294  // expires. The timer is then reset to another random value between 1
1295  // and 5 seconds. Triggered updates may be suppressed if a regular
1296  // update is due by the time the triggered update would be sent.
1297  // Here we rely on this:
1298  // When an update occurs (either Triggered or Periodic) the "IsChanged ()"
1299  // route field will be cleared.
1300  // Hence, the following Triggered Update will be fired, but will not send
1301  // any route update.
1302 
1306 }
1307 
1308 void
1310 {
1311  NS_LOG_FUNCTION(this);
1312 
1314  {
1316  }
1317 
1318  DoSendRouteUpdate(true);
1319 
1320  Time delay =
1323 }
1324 
1325 std::set<uint32_t>
1327 {
1328  return m_interfaceExclusions;
1329 }
1330 
1331 void
1332 Rip::SetInterfaceExclusions(std::set<uint32_t> exceptions)
1333 {
1334  NS_LOG_FUNCTION(this);
1335 
1336  m_interfaceExclusions = exceptions;
1337 }
1338 
1339 uint8_t
1340 Rip::GetInterfaceMetric(uint32_t interface) const
1341 {
1342  NS_LOG_FUNCTION(this << interface);
1343 
1344  auto iter = m_interfaceMetrics.find(interface);
1345  if (iter != m_interfaceMetrics.end())
1346  {
1347  return iter->second;
1348  }
1349  return 1;
1350 }
1351 
1352 void
1353 Rip::SetInterfaceMetric(uint32_t interface, uint8_t metric)
1354 {
1355  NS_LOG_FUNCTION(this << interface << int(metric));
1356 
1357  if (metric < m_linkDown)
1358  {
1359  m_interfaceMetrics[interface] = metric;
1360  }
1361 }
1362 
1363 void
1365 {
1366  NS_LOG_FUNCTION(this);
1367 
1368  Ptr<Packet> p = Create<Packet>();
1369  SocketIpTtlTag tag;
1370  p->RemovePacketTag(tag);
1371  tag.SetTtl(1);
1372  p->AddPacketTag(tag);
1373 
1374  RipHeader hdr;
1376 
1377  RipRte rte;
1381 
1382  hdr.AddRte(rte);
1383  p->AddHeader(hdr);
1384 
1385  for (auto iter = m_unicastSocketList.begin(); iter != m_unicastSocketList.end(); iter++)
1386  {
1387  uint32_t interface = iter->second;
1388 
1389  if (m_interfaceExclusions.find(interface) == m_interfaceExclusions.end())
1390  {
1391  NS_LOG_DEBUG("SendTo: " << *p);
1392  iter->first->SendTo(p, 0, InetSocketAddress(RIP_ALL_NODE, RIP_PORT));
1393  }
1394  }
1395 }
1396 
1397 void
1398 Rip::AddDefaultRouteTo(Ipv4Address nextHop, uint32_t interface)
1399 {
1400  NS_LOG_FUNCTION(this << interface);
1401 
1402  AddNetworkRouteTo(Ipv4Address("0.0.0.0"), Ipv4Mask::GetZero(), nextHop, interface);
1403 }
1404 
1405 /*
1406  * RipRoutingTableEntry
1407  */
1408 
1410  : m_tag(0),
1411  m_metric(0),
1412  m_status(RIP_INVALID),
1413  m_changed(false)
1414 {
1415 }
1416 
1418  Ipv4Mask networkPrefix,
1419  Ipv4Address nextHop,
1420  uint32_t interface)
1422  Ipv4RoutingTableEntry::CreateNetworkRouteTo(network, networkPrefix, nextHop, interface)),
1423  m_tag(0),
1424  m_metric(0),
1425  m_status(RIP_INVALID),
1426  m_changed(false)
1427 {
1428 }
1429 
1431  Ipv4Mask networkPrefix,
1432  uint32_t interface)
1434  Ipv4RoutingTableEntry::CreateNetworkRouteTo(network, networkPrefix, interface)),
1435  m_tag(0),
1436  m_metric(0),
1437  m_status(RIP_INVALID),
1438  m_changed(false)
1439 {
1440 }
1441 
1443 {
1444 }
1445 
1446 void
1448 {
1449  if (m_tag != routeTag)
1450  {
1451  m_tag = routeTag;
1452  m_changed = true;
1453  }
1454 }
1455 
1456 uint16_t
1458 {
1459  return m_tag;
1460 }
1461 
1462 void
1464 {
1465  if (m_metric != routeMetric)
1466  {
1467  m_metric = routeMetric;
1468  m_changed = true;
1469  }
1470 }
1471 
1472 uint8_t
1474 {
1475  return m_metric;
1476 }
1477 
1478 void
1480 {
1481  if (m_status != status)
1482  {
1483  m_status = status;
1484  m_changed = true;
1485  }
1486 }
1487 
1490 {
1491  return m_status;
1492 }
1493 
1494 void
1496 {
1497  m_changed = changed;
1498 }
1499 
1500 bool
1502 {
1503  return m_changed;
1504 }
1505 
1506 std::ostream&
1507 operator<<(std::ostream& os, const RipRoutingTableEntry& rte)
1508 {
1509  os << static_cast<const Ipv4RoutingTableEntry&>(rte);
1510  os << ", metric: " << int(rte.GetRouteMetric()) << ", tag: " << int(rte.GetRouteTag());
1511 
1512  return os;
1513 }
1514 
1515 } // namespace ns3
a polymophic address class
Definition: address.h:101
bool IsNull() const
Check for null implementation.
Definition: callback.h:569
Hold variables of type enum.
Definition: enum.h:62
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:42
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:257
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:829
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:152
virtual void DoInitialize()
Initialize() implementation.
Definition: object.cc:359
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:352
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:967
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:960
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
RipHeader - see RFC 2453
Definition: rip-header.h:158
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
Definition: rip-header.cc:208
uint16_t GetRteNumber() const
Get the number of RTE included in the message.
Definition: rip-header.cc:294
void AddRte(RipRte rte)
Add a RTE to the message.
Definition: rip-header.cc:282
void SetCommand(Command_e command)
Set the command.
Definition: rip-header.cc:270
void ClearRtes()
Clear all the RTEs from the header.
Definition: rip-header.cc:288
std::list< RipRte > GetRteList() const
Get the list of the RTEs included in the message.
Definition: rip-header.cc:300
Command_e GetCommand() const
Get the command.
Definition: rip-header.cc:276
RIP Routing Protocol, defined in RFC 2453.
Definition: rip.h:176
void SetInterfaceMetric(uint32_t interface, uint8_t metric)
Set the metric for an interface.
Definition: rip.cc:1353
void DoSendRouteUpdate(bool periodic)
Send Routing Updates on all interfaces.
Definition: rip.cc:1179
void DoDispose() override
Dispose this object.
Definition: rip.cc:591
SplitHorizonType_e m_splitHorizonStrategy
Split Horizon strategy.
Definition: rip.h:424
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:49
Time m_startupDelay
Random delay before protocol startup.
Definition: rip.h:396
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:422
std::set< uint32_t > m_interfaceExclusions
Set of excluded interfaces.
Definition: rip.h:421
uint32_t m_linkDown
Link down value.
Definition: rip.h:427
void HandleRequests(RipHeader hdr, Ipv4Address senderAddress, uint16_t senderPort, uint32_t incomingInterface, uint8_t hopLimit)
Handle RIP requests.
Definition: rip.cc:842
void DeleteRoute(RipRoutingTableEntry *route)
Delete a route.
Definition: rip.cc:757
bool RouteInput(Ptr< const Packet > p, const Ipv4Header &header, Ptr< const NetDevice > idev, const UnicastForwardCallback &ucb, const MulticastForwardCallback &mcb, const LocalDeliverCallback &lcb, const ErrorCallback &ecb) override
Route an input packet (to be forwarded or locally delivered)
Definition: rip.cc:242
void InvalidateRoute(RipRoutingTableEntry *route)
Invalidate a route.
Definition: rip.cc:733
void Receive(Ptr< Socket > socket)
Receive RIP packets.
Definition: rip.cc:774
void NotifyInterfaceUp(uint32_t interface) override
Definition: rip.cc:321
EventId m_nextUnsolicitedUpdate
Next Unsolicited Update event.
Definition: rip.h:416
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:118
~Rip() override
Definition: rip.cc:57
EventId m_nextTriggeredUpdate
Next Triggered Update event.
Definition: rip.h:417
Ptr< Ipv4 > m_ipv4
IPv4 reference.
Definition: rip.h:395
void DoInitialize() override
Start protocol operation.
Definition: rip.cc:127
void SendRouteRequest()
Send Routing Request on all interfaces.
Definition: rip.cc:1364
Time m_timeoutDelay
Delay before invalidating a route.
Definition: rip.h:400
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:414
Time m_minTriggeredUpdateDelay
Min cooldown delay after a Triggered Update.
Definition: rip.h:397
@ SPLIT_HORIZON
Split Horizon.
Definition: rip.h:214
@ NO_SPLIT_HORIZON
No Split Horizon.
Definition: rip.h:213
@ POISON_REVERSE
Poison Reverse Split Horizon.
Definition: rip.h:215
Time m_unsolicitedUpdate
time between two Unsolicited Routing Updates
Definition: rip.h:399
std::set< uint32_t > GetInterfaceExclusions() const
Get the set of interface excluded from the protocol.
Definition: rip.cc:1326
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:208
uint8_t GetInterfaceMetric(uint32_t interface) const
Get the metric for an interface.
Definition: rip.cc:1340
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:413
Time m_garbageCollectionDelay
Delay before deleting an INVALID route.
Definition: rip.h:401
void SetIpv4(Ptr< Ipv4 > ipv4) override
Definition: rip.cc:498
static TypeId GetTypeId()
Get the type ID.
Definition: rip.cc:62
bool m_initialized
flag to allow socket's late-creation.
Definition: rip.h:426
void SetInterfaceExclusions(std::set< uint32_t > exceptions)
Set the set of interface excluded from the protocol.
Definition: rip.cc:1332
void AddDefaultRouteTo(Ipv4Address nextHop, uint32_t interface)
Add a default route to the router through the nextHop located on interface.
Definition: rip.cc:1398
std::list< std::pair< RipRoutingTableEntry *, EventId > >::iterator RoutesI
Iterator for container for the network routes.
Definition: rip.h:284
Routes m_routes
the forwarding table for network.
Definition: rip.h:394
Time m_maxTriggeredUpdateDelay
Max cooldown delay after a Triggered Update.
Definition: rip.h:398
void SendTriggeredRouteUpdate()
Send Triggered Routing Updates on all interfaces.
Definition: rip.cc:1277
void SendUnsolicitedRouteUpdate()
Send Unsolicited Routing Updates on all interfaces.
Definition: rip.cc:1309
void HandleResponses(RipHeader hdr, Ipv4Address senderAddress, uint32_t incomingInterface, uint8_t hopLimit)
Handle RIP responses.
Definition: rip.cc:1017
Ptr< UniformRandomVariable > m_rng
Rng stream.
Definition: rip.h:419
Rip Routing Table Entry.
Definition: rip.h:65
void SetRouteMetric(uint8_t routeMetric)
Set the route metric.
Definition: rip.cc:1463
Status_e m_status
route status
Definition: rip.h:157
RipRoutingTableEntry()
Definition: rip.cc:1409
bool m_changed
route has been updated
Definition: rip.h:158
void SetRouteStatus(Status_e status)
Set the route status.
Definition: rip.cc:1479
Status_e
Route status.
Definition: rip.h:71
@ RIP_INVALID
Definition: rip.h:73
@ RIP_VALID
Definition: rip.h:72
bool IsRouteChanged() const
Get the route changed status.
Definition: rip.cc:1501
Status_e GetRouteStatus() const
Get the route status.
Definition: rip.cc:1489
uint8_t GetRouteMetric() const
Get the route metric.
Definition: rip.cc:1473
void SetRouteTag(uint16_t routeTag)
Set the route tag.
Definition: rip.cc:1447
uint16_t GetRouteTag() const
Get the route tag.
Definition: rip.cc:1457
void SetRouteChanged(bool changed)
Set the route as changed.
Definition: rip.cc:1495
uint8_t m_metric
route metric
Definition: rip.h:156
virtual ~RipRoutingTableEntry()
Definition: rip.cc:1442
uint16_t m_tag
route tag
Definition: rip.h:155
Rip v2 Routing Table Entry (RTE) - see RFC 2453.
Definition: rip-header.h:39
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:571
static Time GetDelayLeft(const EventId &id)
Get the remaining time until this event will execute.
Definition: simulator.cc:217
void SetRecvPktInfo(bool flag)
Enable/Disable receive packet information to socket.
Definition: socket.cc:354
void SetRecvCallback(Callback< void, Ptr< Socket >> receivedData)
Notify application when new data is available to be read.
Definition: socket.cc:128
virtual void BindToNetDevice(Ptr< NetDevice > netdevice)
Bind a socket to specific device.
Definition: socket.cc:327
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:523
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:604
uint8_t GetTtl() const
Get the tag's TTL.
Definition: socket.cc:611
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:415
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:403
Unit
The unit to use to interpret a number representing time.
Definition: nstime.h:111
a unique identifier for an interface.
Definition: type-id.h:59
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:835
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
Packet header for UDP packets.
Definition: udp-header.h:41
uint32_t GetSerializedSize() const override
Definition: udp-header.cc:159
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
#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:305
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
Definition: first.py:1
address
Definition: first.py:47
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1414
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:704
Ptr< const AttributeChecker > MakeEnumChecker(T v, std::string n, Ts... args)
Make an EnumChecker pre-configured with a set of allowed values by name.
Definition: enum.h:194
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:533
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:159
Definition: second.py:1
#define RIP_ALL_NODE
Definition: rip.cc:39
#define RIP_PORT
Definition: rip.cc:40