From fdfa55c298bad012989628e78ea32ea1b350d208 Mon Sep 17 00:00:00 2001 From: Josh Pelkey Date: Wed, 13 Jan 2010 09:58:37 -0500 Subject: [PATCH] Fix bug 779: NixVectorRouting ignores specified outgoing interface in RouteOutput --- .../ipv4-nix-vector-routing.cc | 310 +++++++++--------- .../ipv4-nix-vector-routing.h | 9 +- 2 files changed, 155 insertions(+), 164 deletions(-) diff --git a/src/routing/nix-vector-routing/ipv4-nix-vector-routing.cc b/src/routing/nix-vector-routing/ipv4-nix-vector-routing.cc index eb73bf89e..aa0c6936d 100644 --- a/src/routing/nix-vector-routing/ipv4-nix-vector-routing.cc +++ b/src/routing/nix-vector-routing/ipv4-nix-vector-routing.cc @@ -117,7 +117,7 @@ Ipv4NixVectorRouting::FlushIpv4RouteCache () } Ptr -Ipv4NixVectorRouting::GetNixVector (Ptr source, Ipv4Address dest) +Ipv4NixVectorRouting::GetNixVector (Ptr source, Ipv4Address dest, Ptr oif) { NS_LOG_FUNCTION_NOARGS (); @@ -146,7 +146,8 @@ Ipv4NixVectorRouting::GetNixVector (Ptr source, Ipv4Address dest) // otherwise proceed as normal // and build the nix vector std::vector< Ptr > parentVector; - BFS (NodeList::GetNNodes (), source, destNode, parentVector); + + BFS (NodeList::GetNNodes (), source, destNode, parentVector, oif); if (BuildNixVector (parentVector, source->GetId (), destNode->GetId (), nixVector)) { @@ -495,7 +496,7 @@ Ipv4NixVectorRouting::RouteOutput (Ptr p, const Ipv4Header &header, Ptr< NS_LOG_LOGIC ("Nix-vector not in cache, build: "); // Build the nix-vector, given this node and the // dest IP address - nixVectorInCache = GetNixVector (m_node, header.GetDestination ()); + nixVectorInCache = GetNixVector (m_node, header.GetDestination (), oif); // cache it m_nixCache.insert (NixMap_t::value_type (header.GetDestination (), nixVectorInCache)); @@ -523,18 +524,38 @@ Ipv4NixVectorRouting::RouteOutput (Ptr p, const Ipv4Header &header, Ptr< uint32_t numberOfBits = nixVectorForPacket->BitCount (m_totalNeighbors); uint32_t nodeIndex = nixVectorForPacket->ExtractNeighborIndex (numberOfBits); - // Possibly search here in a cache for this node index - // and look for a Ipv4Route. If we have it, don't - // need to do the next 3 lines. + // Search here in a cache for this node index + // and look for a Ipv4Route rtentry = GetIpv4RouteInCache (header.GetDestination ()); - // not in cache - if (!rtentry) + + if (!rtentry || !(rtentry->GetOutputDevice () == oif)) { + // not in cache or a different specified output + // device is to be used + + // first, make sure we erase existing (incorrect) + // rtentry from the map + if (rtentry) + { + m_ipv4RouteCache.erase(header.GetDestination ()); + } + NS_LOG_LOGIC ("Ipv4Route not in cache, build: "); Ipv4Address gatewayIp; uint32_t index = FindNetDeviceForNixIndex (nodeIndex, gatewayIp); + int32_t interfaceIndex = 0; + + if (!oif) + { + interfaceIndex = (m_ipv4)->GetInterfaceForDevice(m_node->GetDevice(index)); + } + else + { + interfaceIndex = (m_ipv4)->GetInterfaceForDevice(oif); + } + + NS_ASSERT_MSG (interfaceIndex != -1, "Interface index not found for device"); - uint32_t interfaceIndex = (m_ipv4)->GetInterfaceForDevice(m_node->GetDevice(index)); Ipv4InterfaceAddress ifAddr = m_ipv4->GetAddress (interfaceIndex, 0); // start filling in the Ipv4Route info @@ -543,7 +564,15 @@ Ipv4NixVectorRouting::RouteOutput (Ptr p, const Ipv4Header &header, Ptr< rtentry->SetGateway (gatewayIp); rtentry->SetDestination (header.GetDestination ()); - rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceIndex)); + + if (!oif) + { + rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceIndex)); + } + else + { + rtentry->SetOutputDevice (oif); + } sockerr = Socket::ERROR_NOTERROR; @@ -582,143 +611,50 @@ Ipv4NixVectorRouting::RouteInput (Ptr p, const Ipv4Header &header, // Get the nix-vector from the packet Ptr nixVector = p->GetNixVector(); - // make sure it exists, if not something - // went wrong - if (!nixVector) + // If nixVector isn't in packet, something went wrong + NS_ASSERT (nixVector); + + // Get the interface number that we go out of, by extracting + // from the nix-vector + if (m_totalNeighbors == 0) { - NS_LOG_ERROR ("Nix-vector wasn't in the packet! Rebuild."); - - Ptr nixVectorInCache; - - NS_LOG_DEBUG ("Dest IP from header: " << header.GetDestination ()); - - // check if cache - nixVectorInCache = GetNixVectorInCache(header.GetDestination ()); - - // not in cache - if (!nixVectorInCache) - { - NS_LOG_LOGIC ("RouteInput(): Nix-vector not in cache, build: "); - - // Build the nix-vector, given this node and the - // dest IP address - nixVectorInCache = GetNixVector (m_node, header.GetDestination ()); - } - - // path exists - if (nixVectorInCache) - { - NS_LOG_LOGIC ("Nix-vector contents: " << *nixVectorInCache); - - // cache it - m_nixCache.insert(NixMap_t::value_type(header.GetDestination (), nixVectorInCache)); - - // create a new nix vector to be used, - // we want to keep the cached version clean - Ptr nixVectorForPacket; - nixVectorForPacket = CreateObject (); - nixVectorForPacket = nixVectorInCache->Copy(); - - // Get the interface number that we go out of, by extracting - // from the nix-vector - if (m_totalNeighbors == 0) - { - m_totalNeighbors = FindTotalNeighbors (); - } - uint32_t numberOfBits = nixVectorForPacket->BitCount (m_totalNeighbors); - uint32_t nodeIndex = nixVectorForPacket->ExtractNeighborIndex (numberOfBits); - - rtentry = GetIpv4RouteInCache (header.GetDestination ()); - // not in cache - if (!rtentry) - { - NS_LOG_LOGIC ("Ipv4Route not in cache, build: "); - Ipv4Address gatewayIp; - uint32_t index = FindNetDeviceForNixIndex (nodeIndex, gatewayIp); - - uint32_t interfaceIndex = (m_ipv4)->GetInterfaceForDevice(m_node->GetDevice(index)); - Ipv4InterfaceAddress ifAddr = m_ipv4->GetAddress (interfaceIndex, 0); - - // start filling in the Ipv4Route info - rtentry = Create (); - rtentry->SetSource (ifAddr.GetLocal ()); - - rtentry->SetGateway (Ipv4Address(gatewayIp)); - rtentry->SetDestination (header.GetDestination ()); - rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceIndex)); - - // add rtentry to cache - m_ipv4RouteCache.insert(Ipv4RouteMap_t::value_type(header.GetDestination (), rtentry)); - } - - NS_LOG_LOGIC ("Nix-vector contents: " << *nixVectorInCache << " : Remaining bits: " << nixVectorForPacket->GetRemainingBits()); - - // Add nix-vector in the packet class - // have to copy the packet first b/c - // it is const - Ptr newPacket = Create (); - newPacket = p->Copy(); - - NS_LOG_LOGIC ("Adding Nix-vector to packet: " << *nixVectorForPacket); - newPacket->SetNixVector(nixVectorForPacket); - - // call the unicast callback - // local deliver is handled by Ipv4StaticRoutingImpl - // so this code is never even called if the packet is - // destined for this node. - ucb (rtentry, newPacket, header); - return true; - } - else // path doesn't exist - { - NS_LOG_ERROR ("No path to the dest: " << header.GetDestination ()); - return false; - } + m_totalNeighbors = FindTotalNeighbors (); } - else + uint32_t numberOfBits = nixVector->BitCount (m_totalNeighbors); + uint32_t nodeIndex = nixVector->ExtractNeighborIndex (numberOfBits); + + rtentry = GetIpv4RouteInCache (header.GetDestination ()); + // not in cache + if (!rtentry) { - // Get the interface number that we go out of, by extracting - // from the nix-vector - if (m_totalNeighbors == 0) - { - m_totalNeighbors = FindTotalNeighbors (); - } - uint32_t numberOfBits = nixVector->BitCount (m_totalNeighbors); - uint32_t nodeIndex = nixVector->ExtractNeighborIndex (numberOfBits); + NS_LOG_LOGIC ("Ipv4Route not in cache, build: "); + Ipv4Address gatewayIp; + uint32_t index = FindNetDeviceForNixIndex (nodeIndex, gatewayIp); + uint32_t interfaceIndex = (m_ipv4)->GetInterfaceForDevice(m_node->GetDevice(index)); + Ipv4InterfaceAddress ifAddr = m_ipv4->GetAddress (interfaceIndex, 0); - rtentry = GetIpv4RouteInCache (header.GetDestination ()); - // not in cache - if (!rtentry) - { - NS_LOG_LOGIC ("Ipv4Route not in cache, build: "); - Ipv4Address gatewayIp; - uint32_t index = FindNetDeviceForNixIndex (nodeIndex, gatewayIp); - uint32_t interfaceIndex = (m_ipv4)->GetInterfaceForDevice(m_node->GetDevice(index)); - Ipv4InterfaceAddress ifAddr = m_ipv4->GetAddress (interfaceIndex, 0); + // start filling in the Ipv4Route info + rtentry = Create (); + rtentry->SetSource (ifAddr.GetLocal ()); - // start filling in the Ipv4Route info - rtentry = Create (); - rtentry->SetSource (ifAddr.GetLocal ()); + rtentry->SetGateway (gatewayIp); + rtentry->SetDestination (header.GetDestination ()); + rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceIndex)); - rtentry->SetGateway (gatewayIp); - rtentry->SetDestination (header.GetDestination ()); - rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceIndex)); - - // add rtentry to cache - m_ipv4RouteCache.insert(Ipv4RouteMap_t::value_type(header.GetDestination (), rtentry)); - } - - NS_LOG_LOGIC ("At Node " << m_node->GetId() << ", Extracting " << numberOfBits << - " bits from Nix-vector: " << nixVector << " : " << *nixVector); - - // call the unicast callback - // local deliver is handled by Ipv4StaticRoutingImpl - // so this code is never even called if the packet is - // destined for this node. - ucb (rtentry, p, header); - - return true; + // add rtentry to cache + m_ipv4RouteCache.insert(Ipv4RouteMap_t::value_type(header.GetDestination (), rtentry)); } + + NS_LOG_LOGIC ("At Node " << m_node->GetId() << ", Extracting " << numberOfBits << + " bits from Nix-vector: " << nixVector << " : " << *nixVector); + + // call the unicast callback + // local deliver is handled by Ipv4StaticRoutingImpl + // so this code is never even called if the packet is + // destined for this node. + ucb (rtentry, p, header); + + return true; } // virtual functions from Ipv4RoutingProtocol @@ -744,7 +680,9 @@ Ipv4NixVectorRouting::NotifyRemoveAddress (uint32_t interface, Ipv4InterfaceAddr } bool -Ipv4NixVectorRouting::BFS (uint32_t numberOfNodes, Ptr source, Ptr dest, std::vector< Ptr > & parentVector) +Ipv4NixVectorRouting::BFS (uint32_t numberOfNodes, Ptr source, + Ptr dest, std::vector< Ptr > & parentVector, + Ptr oif) { NS_LOG_FUNCTION_NOARGS (); @@ -772,41 +710,36 @@ Ipv4NixVectorRouting::BFS (uint32_t numberOfNodes, Ptr source, Ptr d return true; } - - // Iterate over the current node's adjacent vertices - // and push them into the queue - for (uint32_t i = 0; i < (currNode->GetNDevices ()); i++) + // if this is the first iteration of the loop and a + // specific output interface was given, make sure + // we go this way + if (currNode == source && oif) { - // Get a net device from the node - // as well as the channel, and figure - // out the adjacent net device - Ptr localNetDevice = currNode->GetDevice (i); - // make sure that we can go this way if (ipv4) { - uint32_t interfaceIndex = (ipv4)->GetInterfaceForDevice(currNode->GetDevice(i)); + uint32_t interfaceIndex = (ipv4)->GetInterfaceForDevice(oif); if (!(ipv4->IsUp (interfaceIndex))) { NS_LOG_LOGIC ("Ipv4Interface is down"); - continue; + return false; } } - if (!(localNetDevice->IsLinkUp ())) - { - NS_LOG_LOGIC ("Link is down."); - continue; - } - Ptr channel = localNetDevice->GetChannel (); + if (!(oif->IsLinkUp ())) + { + NS_LOG_LOGIC ("Link is down."); + return false; + } + Ptr channel = oif->GetChannel (); if (channel == 0) { - continue; + return false; } // this function takes in the local net dev, and channnel, and // writes to the netDeviceContainer the adjacent net devs NetDeviceContainer netDeviceContainer; - GetAdjacentNetDevices (localNetDevice, channel, netDeviceContainer); + GetAdjacentNetDevices (oif, channel, netDeviceContainer); // Finally we can get the adjacent nodes // and scan through them. We push them @@ -827,6 +760,63 @@ Ipv4NixVectorRouting::BFS (uint32_t numberOfNodes, Ptr source, Ptr d } } } + else + { + // Iterate over the current node's adjacent vertices + // and push them into the queue + for (uint32_t i = 0; i < (currNode->GetNDevices ()); i++) + { + // Get a net device from the node + // as well as the channel, and figure + // out the adjacent net device + Ptr localNetDevice = currNode->GetDevice (i); + + // make sure that we can go this way + if (ipv4) + { + uint32_t interfaceIndex = (ipv4)->GetInterfaceForDevice(currNode->GetDevice(i)); + if (!(ipv4->IsUp (interfaceIndex))) + { + NS_LOG_LOGIC ("Ipv4Interface is down"); + continue; + } + } + if (!(localNetDevice->IsLinkUp ())) + { + NS_LOG_LOGIC ("Link is down."); + continue; + } + Ptr channel = localNetDevice->GetChannel (); + if (channel == 0) + { + continue; + } + + // this function takes in the local net dev, and channnel, and + // writes to the netDeviceContainer the adjacent net devs + NetDeviceContainer netDeviceContainer; + GetAdjacentNetDevices (localNetDevice, channel, netDeviceContainer); + + // Finally we can get the adjacent nodes + // and scan through them. We push them + // to the greyNode queue, if they aren't + // already there. + for (NetDeviceContainer::Iterator iter = netDeviceContainer.Begin (); iter != netDeviceContainer.End (); iter++) + { + Ptr remoteNode = (*iter)->GetNode (); + + // check to see if this node has been pushed before + // by checking to see if it has a parent + // if it doesn't (null or 0), then set its parent and + // push to the queue + if (parentVector.at (remoteNode->GetId ()) == 0) + { + parentVector.at (remoteNode->GetId ()) = currNode; + greyNodeList.push (remoteNode); + } + } + } + } // Pop off the head grey node. We have all its children. // It is now black. diff --git a/src/routing/nix-vector-routing/ipv4-nix-vector-routing.h b/src/routing/nix-vector-routing/ipv4-nix-vector-routing.h index e8213e82f..5de8ff999 100644 --- a/src/routing/nix-vector-routing/ipv4-nix-vector-routing.h +++ b/src/routing/nix-vector-routing/ipv4-nix-vector-routing.h @@ -78,9 +78,9 @@ class Ipv4NixVectorRouting : public Ipv4RoutingProtocol void ResetTotalNeighbors (void); /* takes in the source node and dest IP and calls GetNodeByIp, - * BFS, and BuildNixVector to finally return the built - * nix-vector */ - Ptr GetNixVector (Ptr, Ipv4Address); + * BFS, accounting for any output interface specified, and finally + * BuildNixVector to return the built nix-vector */ + Ptr GetNixVector (Ptr, Ipv4Address, Ptr); /* checks the cache based on dest IP for the nix-vector */ Ptr GetNixVectorInCache (Ipv4Address); @@ -124,7 +124,8 @@ class Ipv4NixVectorRouting : public Ipv4RoutingProtocol bool BFS (uint32_t numberOfNodes, Ptr source, Ptr dest, - std::vector< Ptr > & parentVector); + std::vector< Ptr > & parentVector, + Ptr oif); void DoDispose (void);