Fix bug 779: NixVectorRouting ignores specified outgoing interface in RouteOutput

This commit is contained in:
Josh Pelkey
2010-01-13 09:58:37 -05:00
parent 7623a960a5
commit fdfa55c298
2 changed files with 155 additions and 164 deletions

View File

@@ -117,7 +117,7 @@ Ipv4NixVectorRouting::FlushIpv4RouteCache ()
}
Ptr<NixVector>
Ipv4NixVectorRouting::GetNixVector (Ptr<Node> source, Ipv4Address dest)
Ipv4NixVectorRouting::GetNixVector (Ptr<Node> source, Ipv4Address dest, Ptr<NetDevice> oif)
{
NS_LOG_FUNCTION_NOARGS ();
@@ -146,7 +146,8 @@ Ipv4NixVectorRouting::GetNixVector (Ptr<Node> source, Ipv4Address dest)
// otherwise proceed as normal
// and build the nix vector
std::vector< Ptr<Node> > 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<Packet> 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<Packet> 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<Packet> 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<const Packet> p, const Ipv4Header &header,
// Get the nix-vector from the packet
Ptr<NixVector> 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<NixVector> 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<NixVector> nixVectorForPacket;
nixVectorForPacket = CreateObject<NixVector> ();
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<Ipv4Route> ();
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<Packet> newPacket = Create<Packet> ();
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<Ipv4Route> ();
rtentry->SetSource (ifAddr.GetLocal ());
// start filling in the Ipv4Route info
rtentry = Create<Ipv4Route> ();
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<Node> source, Ptr<Node> dest, std::vector< Ptr<Node> > & parentVector)
Ipv4NixVectorRouting::BFS (uint32_t numberOfNodes, Ptr<Node> source,
Ptr<Node> dest, std::vector< Ptr<Node> > & parentVector,
Ptr<NetDevice> oif)
{
NS_LOG_FUNCTION_NOARGS ();
@@ -772,41 +710,36 @@ Ipv4NixVectorRouting::BFS (uint32_t numberOfNodes, Ptr<Node> source, Ptr<Node> 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<NetDevice> 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> channel = localNetDevice->GetChannel ();
if (!(oif->IsLinkUp ()))
{
NS_LOG_LOGIC ("Link is down.");
return false;
}
Ptr<Channel> 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<Node> source, Ptr<Node> 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<NetDevice> 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> 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<Node> 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.

View File

@@ -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<NixVector> GetNixVector (Ptr<Node>, Ipv4Address);
* BFS, accounting for any output interface specified, and finally
* BuildNixVector to return the built nix-vector */
Ptr<NixVector> GetNixVector (Ptr<Node>, Ipv4Address, Ptr<NetDevice>);
/* checks the cache based on dest IP for the nix-vector */
Ptr<NixVector> GetNixVectorInCache (Ipv4Address);
@@ -124,7 +124,8 @@ class Ipv4NixVectorRouting : public Ipv4RoutingProtocol
bool BFS (uint32_t numberOfNodes,
Ptr<Node> source,
Ptr<Node> dest,
std::vector< Ptr<Node> > & parentVector);
std::vector< Ptr<Node> > & parentVector,
Ptr<NetDevice> oif);
void DoDispose (void);