Ipv4RoutingTableEntry issues with Gateway vs NextHop

115 views
Skip to first unread message

Judith Samson

unread,
Aug 21, 2023, 7:28:37 AM8/21/23
to ns-3-users
Hi all, I've been working on a new distance vector protocol and implementing it in ns-3. The protocol (called SCRIP) extends the Ipv4RoutingProtocol. I modeled much of the basic code on Ripv2, and then changed it to reflect Scrip.

Here is the constructor for a Scrip routing table entry:

ScripRoutingTableEntry::ScripRoutingTableEntry (Ipv4Address destination, Ipv4Mask destinationPrefix, Ipv4Address nextHop, uint32_t interface)
  : Ipv4RoutingTableEntry ( Ipv4RoutingTableEntry::CreateNetworkRouteTo (destination, destinationPrefix, nextHop, interface) ),
    m_destination(destination), m_destinationPrefix (destinationPrefix), m_tag (0), m_referenceDistance (LINKDOWN), m_optimalDistance (LINKDOWN), m_distanceVoucher (true), m_nextHop(nextHop), m_NumNeighborsDest(0), m_NumNeighborsLinkDown(0)
{
}


Node k creates a routing table entry with the first feasible distance it finds to destination d. This sets the gateway to be the next hop q. If another downstream neighbor n has a better path to d, n sends a message to k, advertising its better path distance. K then changes the routing table entry to reflect the new, better distance to d and changes the next hop from the original next hop q to the new, better next hop n. Here is an example:

Node: 2, Time: +2s, Local time: +2s, IPv4 SCRIP table
Destination    Gateway(NH)    NextHop    DV   Flags  RefDist.  OptDist.   Use Iface
10.0.13.0       10.0.2.1        10.0.2.1        1     UGS   4      4      2
10.0.10.0       10.0.2.1        10.0.2.1        1     UGS   4      4      2

Node: 2, Time: +6s, Local time: +6s, IPv4 SCRIP table
Destination    Gateway(NH)    NextHop    DV   Flags  RefDist.  OptDist.   Use Iface
10.0.13.0       10.0.2.1        10.0.2.1        1     UGS   4      4      2
10.0.10.0       10.0.2.1        10.0.6.2        1     UGS   3      3      2

Note that at Time 2, Node 2's routing table for destination 10.0.13.0 has 10.0.2.1 as the gateway and next hop with a distance of 4, but at Time 6, 10.0.6.2 has a better distance to 10.0.13.0 of 3. The next hop has changed to 10.0.6.2, but the gateway remains the same at 10.0.2.1.

I have not been able to figure out how to change the gateway, and what the significance is of gateway vs. next hop.

I saw that in the Internet module there are two classes: Ipv4Route and Ipv4RoutingTableEntry. The Ipv4RoutingTableEntry has a nextHop and
a Gateway. the Ipv4Route only has a Gateway. If a routing protocol changes
the next hop when it finds a better route to a destination, the next hop changes, but I can't figure out how to change the gateway.

This seems important because when the simulation goes to Scrip::Lookup() to find a route, the Ptr<Ipv4Route> it creates uses the original gateway from when the Ipv4RoutingTableEntry is created. There doesn’t appear to be any way to set the gateway again that works. When I created a new method Ipv4RoutingTableEntry::SetGateway() and then tried to set the Ipv4RoutingTableEntry to the new nextHop from the ScripRoutingTableEntry, all the packets dropped when I ran a simulation.

for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++)
    {
      ScripRoutingTableEntry* j = it->first;

     if (j->GetRouteStatus () == ScripRoutingTableEntry::SCRIP_VALID)
        {
          Ipv4Mask mask = j->GetDestNetworkMask ();
          uint16_t maskLen = mask.GetPrefixLength ();
          Ipv4Address entry = j->GetDestNetwork ();
          Ipv4Address gateway = j->GetNextHop();

          NS_LOG_LOGIC ("Searching for route to " << dst << ", mask length " << maskLen);

          if (mask.IsMatch (dst, entry))
            {
              NS_LOG_LOGIC ("Found global network route " << j << ", mask length " << maskLen);

              /* if interface is given, check the route will output on this interface */
              if (!interface || interface == m_ipv4->GetNetDevice (j->GetInterface ()))
                {
                  if (maskLen < longestMask)
                    {
                      NS_LOG_LOGIC ("Previous match longer, skipping");
                      continue;
                    }

                  longestMask = maskLen;

                  Ipv4RoutingTableEntry* route = j;
// I created a method called SetGateway(), but it breaks the simulation
               //   route->SetGateway (gateway);
                  uint32_t interfaceIdx = route->GetInterface ();
                  rtentry = Create<Ipv4Route> ();

                  if (route->GetDest ().IsAny ()) /* default route */
                    {
                      rtentry->SetSource (m_ipv4->SourceAddressSelection (interfaceIdx, route->GetGateway ()));
                    }
                  else
                    {
                      rtentry->SetSource (m_ipv4->SourceAddressSelection (interfaceIdx, route->GetDest ()));
                    }

                  rtentry->SetDestination (route->GetDest ());
                  rtentry->SetGateway (route->GetGateway ());
                //  rtentry->SetGateway (gateway);
                  rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceIdx));
                  NS_LOG_LOGIC ("Gateway for route is " << route->GetGateway() << ". Scrip next hop is " << gateway);
                }
            }


Is changing the gateway important when the next hop changes, and if so, can you point me in the right direction?

Judith Samson

unread,
Aug 21, 2023, 7:34:11 AM8/21/23
to ns-3-users
Sorry, I missed some of the code when copying Scrip::Lookup:

Ptr<Ipv4Route> Scrip::Lookup (Ipv4Address dst, Ptr<NetDevice> interface)
{
  NS_LOG_FUNCTION (this << dst << interface);

  Ptr<Ipv4Route> rtentry = 0;
  uint16_t longestMask = 0;

  /* when sending on local multicast, there have to be interface specified */
  if (dst.IsLocalMulticast ())
    {
      NS_ASSERT_MSG (interface, "Try to send on local multicast address, and no interface index is given!");

      rtentry = Create<Ipv4Route> ();
      rtentry->SetSource (m_ipv4->SourceAddressSelection (m_ipv4->GetInterfaceForDevice (interface), dst));
      rtentry->SetDestination (dst);
      rtentry->SetGateway (Ipv4Address::GetZero ());
      rtentry->SetOutputDevice (interface);
      return rtentry;

    }
for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++)
    {
      ScripRoutingTableEntry* j = it->first;

     if (j->GetRouteStatus () == ScripRoutingTableEntry::SCRIP_VALID)
        {
          Ipv4Mask mask = j->GetDestNetworkMask ();
          uint16_t maskLen = mask.GetPrefixLength ();
          Ipv4Address entry = j->GetDestNetwork ();
          Ipv4Address gateway = j->GetNextHop();

          NS_LOG_LOGIC ("Searching for route to " << dst << ", mask length " << maskLen);

          if (mask.IsMatch (dst, entry))
            {
              NS_LOG_LOGIC ("Found global network route " << j << ", mask length " << maskLen);

              /* if interface is given, check the route will output on this interface */
              if (!interface || interface == m_ipv4->GetNetDevice (j->GetInterface ()))
                {
                  if (maskLen < longestMask)
                    {
                      NS_LOG_LOGIC ("Previous match longer, skipping");
                      continue;
                    }

                  longestMask = maskLen;

                  Ipv4RoutingTableEntry* route = j;

Tommaso Pecorella

unread,
Aug 31, 2023, 6:05:08 AM8/31/23
to ns-3-users
Hi,

I don't see any NextHop in Ipv4RoutingTableEntry... except for the function parameters names (which might be misleading).

Let me clarify this a bit, perhaps it will help.

First and foremost: I'm not the responsible for cleaning up a mess made my years of history. And I'm not talking about ns-3, I'm talking about *everything*. We can just see the mess, ¯\_(ツ)_/¯, and say "oh, well".
  • First fact: there's no "Gateway". Technically speaking, a Gateway is a L7 appliance, here we're talking about L3, so they're Routers. However, historically, they're called Gateway, mostly because it looked simpler in the configuration interfaces of computers. I't's easier to tell the user to set the Gateway (to Internet) than to explain them what's a Router, so the name did stick. And this also did reflect in the Linux programming APIs.
  • Second fact: ns-3 heavily re-uses Linux APIs conventions and naming, so that it's easier (?) for users that are used to Linux.
  • Third fact: there's no "NextHop" - unless you're in a mesh network.

And now the lengthy one... mind I'll use a language that applies both to IPv4 and IPv6, so I'll not write "subnet", I'll write "link-level domain".

If you're in a non-mesh network your host (or router) needs to find the next device to send the packet to. This can be seen as the "next hop", but if you look at it it's just another router: the next one toward the destination. This "next router" can be responsible for forwarding packets to a single IP, to a group of them, or to the whole Internet - it doesn't really matter. From the point of view of a device, we can (colloquially) call it the Gateway toward this (or these) addresses. So "Next Hop" and "Gateway" are synonyms.

Now, if we look at it from the point of view of code, when you ask the routing protocol for a Route, it will return it, and the Route will have a Gateway (again, it's the Next Hop). If it's zero, it means that either you can deliver the packet directly, or that you're in trouble.
If it's a valid node, you take its IP address, you convert the IP address into a MAC address, and you send the packet to it - simple as that.

In a mesh network this is slightly different, but I guess you're not interested into that complication (it depends on if the mesh is made at L3 or L2).

So, to summarise... Next Hop === Gateway.

About why your simulation breaks if you use "route->SetGateway (gateway)"... no idea, but typically the Lookup function is a lookup, so it shouldn't change the routing table entry. It *might*, as you could want to use late-invalidation, so it's not marked as const, but that's it.

Judith Samson

unread,
Sep 3, 2023, 6:31:14 AM9/3/23
to ns-3-users
Thanks very much Tommaso! That makes total sense. I was trying to change the Gateway value in Lookup, which isn't right.

I went back to the original rip.cc code that you wrote and found that you had already written how to change the routing table entry in HandleResponses()   :-)

So I think I have the right way to do it now...
Reply all
Reply to author
Forward
0 new messages