Fix bug 779: NixVectorRouting ignores specified outgoing interface in RouteOutput
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user