home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.ee.lbl.gov
/
2014.05.ftp.ee.lbl.gov.tar
/
ftp.ee.lbl.gov
/
mrdebug.tar.Z
/
mrdebug.tar
/
dist_vect.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-25
|
29KB
|
892 lines
/*****************************************************************
PROGRAM: Network Distance Vector Routing Computer
DESCRIPTION:
This program assumes knowledge of the entire
network before starting. It uses Dijkstra's
algorithm to determine the shortest path tree
from the given source and fills in the appropriate
distance vector entries for that source in the
sites' distance vector tables.
METHOD:
Dijkstra's algorithm. The reverse direction edge weights
are used to determine the weight between any two sites.
The algorithm uses the relaxation method it starts with
all nodes being infinite distance except the source which
is zero distance. The graph is assumed to be stored as
an adjacency list. The program gradually investigates out
from the source always expanding the lowest cost node next.
Once a node has been investigated, it need not be looked at
again.
PROGRAMMER: Deb Agarwal 6/1993
*********************************************************************/
#include <stdio.h>
#include <string.h>
#include "types.h"
#include "mrhash.h"
#include "data_struct_proto.h"
#include "dist_vect_proto.h"
/********* EXTERNAL REFERENCES ***********/
extern int verbose;
extern int reverse_path;
/******************************************************************
FUNCTION: init_source( net, source )
DESCRIPTION:
This function initializes the data structures for Dijkstra's
algorithm which is used to create distance vector routing
tables.
**********************************************************************/
void init_source( Network *net, long source )
{
long v;
Interface *cur_ifc;
for( v=0; v< net->no_nodes; v++ )
{/*
** Start with all nodes at infinite distance and with
** no parent node.
*/
net->adj_list[v].dist_vects.distance = INFINITE_DIST;
net->adj_list[v].dist_vects.next_hop_subnet = NULL;
net->adj_list[v].dist_vects.next_hop_node = INVALID_NODE;
net->adj_list[v].dist_vects.in_tree = FALSE;
for( cur_ifc = net->adj_list[v].interfaces.first;
cur_ifc != NULL; cur_ifc = cur_ifc->next )
{
cur_ifc->type &= ~ROUTE_MASK; /* zero child and leaf */
cur_ifc->in_tree = FALSE; /* used by print_tree */
}
}
/*
** The distance of the source site is 0
*/
net->adj_list[source].dist_vects.distance = 0;
return;
}
/**********************************************************************
FUNCTION: relax_node( frm_node, to_node, weight )
DESCRIPTION:
This function relaxes the to_node of an edge by reassigning
the distance function if this path is shorter than the best
currently known path.
**********************************************************************/
void relax_node(Network *net, Interface *frm_ifc, long frm_node, long to_node, long weight )
{
DVTable *dvt1, *dvt2;
dvt1 = &net->adj_list[frm_node].dist_vects;
dvt2 = &net->adj_list[to_node].dist_vects;
/*
** Check if this new path is shorter distance or the same distance
** and through a lower address node.
*/
if( dvt2->distance >= (dvt1->distance + weight) )
{
/*
** If the node this path just came from is the same
** length as my previous path and the address of the
** previous node is higher than the one I have as prev,
** then do not relax this node.
*/
if( dvt2->next_hop_subnet != NULL )
if(dvt2->distance == (dvt1->distance + weight) &&
frm_ifc->to_addr > dvt2->next_hop_subnet->to_addr )
return;
/*
** If we got this far, then this path is shorter distance than the
** previous known one or through a lower address so remember it as
** the shortest distance path.
*/
dvt2->distance = dvt1->distance + weight;
dvt2->next_hop_subnet = frm_ifc;
dvt2->next_hop_node = frm_node;
}/* endif */
return;
}
/***********************************************************************
FUNCTION: dijkstra_tree( net, source )
DESCRIPTION:
This function performs the outer loop of Dijkstra's algorithm.
It initializes the node distance vector table entries, and then
investigates nodes one at a time starting always with the one
of shortest distance.
**********************************************************************/
void dijkstra_tree( Network *net, long source )
{
long cur_node;
Interface *cur_ifc, *back_ifc;
init_source( net, source );
while( (cur_node = extract_min_dist_node( net )) != INVALID_NODE )
{/*
** cur_node is the node that is the minimum distance from the source
** of all the remaining nodes. It's place in the tree has now stabilized
** because no shorter distance path will be found in the future so record
** it and relax the nodes on its outgoing edges that are not down.
*/
net->adj_list[cur_node].dist_vects.in_tree = TRUE;
for( cur_ifc = net->adj_list[cur_node].interfaces.first;
cur_ifc != NULL; cur_ifc = cur_ifc->next )
{
if( !(cur_ifc->type & (DOWN | DISABLED)))
{
/*
** The current mrouted uses the outgoing metric to determine
** the cost between this node and its parent in the source tree.
** We need to determine the reverse direction edge weight for
** use in the distance calculation since we are coming from the
** parent
*/
back_ifc = find_ifc( net, NULL, cur_ifc->to_name, cur_ifc->name );
if( back_ifc == NULL || back_ifc->type & (DOWN | DISABLED))
{/*
** For some reason this tunnel was not reported in both directions
** so, we will assume that the tunnel is actually down
*/
if( verbose )
printf( "reverse edge %s to %s not found or down, assuming this edge is down\n",
cur_ifc->to_name, cur_ifc->name );
cur_ifc->type |= DOWN;
}
else
{
if( reverse_path )
relax_node( net, back_ifc, cur_node, cur_ifc->to_node, cur_ifc->metric );
else
relax_node( net, back_ifc, cur_node, cur_ifc->to_node, back_ifc->metric );
}
}
}/* endfor */
}/* endwhile */
/*
** Now that the distance vector routing calculations are complete,
** calculate the child and leaf bits for the reverse path forwarding
** algorithm.
*/
find_child_leaf( net, source );
return;
}
/******************************************************************************
FUNCTION: extract_min_dist_node( net )
DESCRIPTION:
This function returns the node that has the minimum distance in
its distance vector table. It only searches through nodes that
are not yet marked as in tree. If all nodes are done, then it returns
INVALID_NODE. A simple linear search is performed each time the
function is called.
******************************************************************************/
long extract_min_dist_node( Network *net )
{
long i;
long cur_min;
long min_node;
min_node = INVALID_NODE;
cur_min = INFINITE_DIST;
for( i = 0; i < net->no_nodes; i++)
{
if( !net->adj_list[i].dist_vects.in_tree )
if( net->adj_list[i].dist_vects.distance < cur_min )
{
min_node = i;
cur_min = net->adj_list[i].dist_vects.distance;
}
}
return min_node;
}
/***********************************************************************
FUNCTION: find_child_leaf( net, source )
DESCRIPTION:
Fill in the child and leaf structures for each distance
vector routing table in the graph. It only fills in the
entries for routes to the current source. The child and
leaf bits are maintained at each interface. The calculation
is carried out as specified for reverse path forwarding.
***********************************************************************/
void find_child_leaf( Network *net, long source )
{
int v;
Interface *cur_ifc;
DVTable *to_dvtable;
Node *frm_node;
for( v = 0; v < net->no_nodes; v++ )
{
frm_node = &net->adj_list[v];
if( v != source && frm_node->dist_vects.next_hop_subnet == NULL )
/*
** This node is not in the spanning tree so we don't need
** to worry about its child interfaces.
*/
continue;
for( cur_ifc = frm_node->interfaces.first;
cur_ifc != NULL; cur_ifc = cur_ifc->next )
{
if( !(cur_ifc->type & (DOWN | DISABLED)))
{/*
** If this is the next_hop_subnet, then it is the
** parent so mark it as such.
*/
if( cur_ifc == frm_node->dist_vects.next_hop_subnet )
{
cur_ifc->type |= PARENT;
continue;
}
/*
** This is not the parent interface so start out
** assuming that it is a child and leaf and then
** determine if it is not.
*/
cur_ifc->type |= ( CHILD | LEAF );
/*
** For the neighbor (always only one) on this interface. Check if
** it has a shorter distance or same distance and
** lower address. If so, then this interface is not a
** child.
*/
to_dvtable = &net->adj_list[cur_ifc->to_node].dist_vects;
if( !(net->adj_list[cur_ifc->to_node].type & SUBNET ))
{
if( to_dvtable->distance <= frm_node->dist_vects.distance &&
!(cur_ifc->type & SUBNET))
{
if( to_dvtable->distance == frm_node->dist_vects.distance )
{
if( cur_ifc->to_addr < cur_ifc->address)
cur_ifc->type &= ~CHILD;
}
else
/*
** If this is a SUBNET node, then make everybody except
** the parent children because messages are broadcast on
** the subnet.
*/
cur_ifc->type &= ~CHILD;
}
}
else
{/*
** This is a connection to a subnet. The subnet is not a child if
** the subnet does not consider this node a parent.
*/
if( strcmp( to_dvtable->next_hop_subnet->to_name, cur_ifc->name ))
cur_ifc->type &= ~CHILD;
}
if( to_dvtable->next_hop_node == INVALID_NODE ||
to_dvtable->next_hop_node == v )
/*
** This interface is not a leaf if there is a neighbor
** that considers this node its parent (next_hop_subnet)
** or if it leads to the source.
*/
cur_ifc->type &= ~LEAF;
if( (cur_ifc->type & CHILD) && (cur_ifc->type & LEAF) &&
(cur_ifc->type & TUNNEL ))
/*
** This interface is a tunnel and the router at the
** other end does not consider this router to be its
** parent so do not mark it as a child or leaf.
*/
cur_ifc->type &= ~(CHILD|LEAF);
}
}
}
}
/************************************************************************
FUNCTION: print_entry( )
DESCRIPTION:
Print a particular entry of a path or a tree.
************************************************************************/
void print_entry( FILE *out, NAME name, long indent, long posn, long distance,
long threshold, long suspect, int print_out, u_long type )
{
long i;
if( !print_out )
return;
for( i=1; i <= (posn*indent); i++)
fprintf(out, " " );
fprintf(out, "%s, %ld/%ld/%ld", name, posn, distance, threshold );
if (type & SRCRT)
fprintf(out, "/srcrt");
if (type & DOWN)
fprintf(out, "/down");
if (type & DISABLED)
fprintf(out, "/disabled");
if( suspect )
fprintf(out, "/SUSPECT");
fprintf(out, "\n");
}
/************************************************************************
FUNCTION: print_tree( )
DESCRIPTION:
This function prints out the shortest path tree determined by
the distance vector routing protocol. It is called recursively.
Each time it finds another node in the tree, it calls the function
again with this node as the source. The branches of the tree will
follow those determined by the distance vector routing protocol
and the find child and leaf routine. Subnet nodes are not printed
unless they are the source or the destination.
*************************************************************************/
void print_tree( FILE *out, int indent, Network *net, long source, Interface *frm_ifc, long posn,
long hops, long threshold, long suspect, long max_thresh, int print_out )
{
int add_indent = 0;
long nxt_thresh;
Interface *cur_ifc, *back_ifc;
NAME last_name;
if( frm_ifc != net->adj_list[source].dist_vects.next_hop_subnet && threshold > 0 )
{/*
** The previous node is forwarding packets to me but I
** will not forward them because he is not my parent node.
** Just print my interfaces indicating receipt and return.
*/
if( !(net->adj_list[source].type & SUBNET ))
{
print_entry(out, frm_ifc->name, indent, posn, -1, threshold, suspect,
print_out, frm_ifc->type );
frm_ifc->in_tree = TRUE;
strcpy( last_name, "\0" );
for( cur_ifc = net->adj_list[source].interfaces.first;
cur_ifc != NULL; cur_ifc = cur_ifc->next )
if( !(cur_ifc->type & (DOWN|DISABLED)))
{
if( strcmp( cur_ifc->name, last_name ) &&
strcmp( cur_ifc->name, frm_ifc->name))
{/*
** This interface has not been printed out yet so lets do
** it now. The above if assumes all interfaces of the same
** name are together at a node and not separated by other
** interfaces.
*/
print_entry(out, cur_ifc->name, indent, posn+1, -1,
threshold, suspect, print_out, cur_ifc->type );
cur_ifc->in_tree = TRUE;
strcpy( last_name, cur_ifc->name );
}
}
}
return;
}
/*
** If I reached here, this packet came in on my parent interface
** so print all of my interfaces and forward it to all of my
** children.
*/
strcpy( last_name, "\0" );
if( net->adj_list[source].type & SUBNET )
posn--;
/*
** The following loop etc are to make sure before we print this
** interface out that there is at least one up interface with this
** name before we print it out.
*/
if( !(net->adj_list[source].type & SUBNET ))
{
print_entry(out, frm_ifc->name, indent, posn,
net->adj_list[source].dist_vects.distance,
threshold, suspect, print_out, frm_ifc->type );
hops++;
}
frm_ifc->in_tree = TRUE;
add_indent = 0;
for( cur_ifc = net->adj_list[source].interfaces.first;
cur_ifc != NULL; cur_ifc = cur_ifc->next )
if( !(cur_ifc->type & (DOWN|DISABLED)))
{
if( strcmp( cur_ifc->name, frm_ifc->name))
{
if( strcmp( cur_ifc->name, last_name ))
{/*
** This interface has not been printed out yet so lets do
** it now. The above if assumes all interfaces of the same
** name are together at a node and not separated by other
** interfaces.
*/
add_indent = 1;
if( !(net->adj_list[source].type & SUBNET ))
print_entry(out, cur_ifc->name, indent, posn+1,
net->adj_list[source].dist_vects.distance,
threshold, suspect, print_out, cur_ifc->type );
else
add_indent = 0;
cur_ifc->in_tree = TRUE;
}
strcpy( last_name, cur_ifc->name );
}
else
add_indent = 0;
if( cur_ifc->type & CHILD )
{
/*
** Forward the packet to all of the children. Also send
** a pointer to the interface the site is receiving this
** on so I can decide whether it received it from its parent.
** When determining the current ttl(threshold) needed,a packet must have
** a ttl of at least 2 to be forwarded.
*/
if( cur_ifc->threshold == 1 )
nxt_thresh = hops + 2;
else
nxt_thresh = hops + cur_ifc->threshold;
if( nxt_thresh < threshold )
nxt_thresh = threshold;
back_ifc = find_ifc( net, NULL, cur_ifc->to_name, cur_ifc->name );
/*
** If the reverse direction of this edge is down, do not
** continue out this edge.
*/
if( back_ifc->type & (DOWN | DISABLED))
continue;
/*
** The following if allows a ttl to be specified and only the
** portions of the tree that are within reach of that ttl will
** be printed. The max_thresh is specified when requesting a
** tree printout.
*/
if( max_thresh < 0 || nxt_thresh <= max_thresh )
{
/* printf( "calling print tree %s with posn %ld add_indent %d\n",
cur_ifc->to_name, posn+1, add_indent );*/
print_tree( out, indent, net, cur_ifc->to_node, back_ifc, (posn + 1 + add_indent),
hops, nxt_thresh, (cur_ifc->type & SUSPECT), max_thresh, print_out );
}
}
}
return;
}
/**************************************************************************
FUNCTION: print_unreach( net )
DESCRIPTION:
This function prints a list of the nodes that were found to be
unreachable when investigating the source's minimum spanning
tree. It will also print the nodes that were not reached due
to specification of a max_thresh (ttl) for the tree printout.
Subnets that are unreachable are not printed out, just the
unreachable interfaces on it.
**************************************************************************/
void print_unreach(FILE *out, Network *net, int print_out )
{
long v, j=0, found, found2, last_v = INVALID_NODE,
tot_unreach = 0;
Interface *cur_ifc;
NAME last_name;
strcpy( last_name, "\0" );
found = TRUE;
found2 = TRUE;
if( !print_out )
fprintf( out, "\nNumber of unreachable interfaces: " );
else
fprintf( out, "\nUnreachable interfaces:\n" );
for( v = 0; v < net->no_nodes; v++ )
{
if( !(net->adj_list[v].type & SUBNET ))
{
if( !net->adj_list[v].dist_vects.in_tree )
{/*
** If this node is not in the tree, it must have been
** unreachable when djkstra's algorithm was computed.
*/
for( cur_ifc = net->adj_list[v].interfaces.first; cur_ifc != NULL;
cur_ifc = cur_ifc->next )
{/*
** Print all of the interfaces at this node
*/
if( strcmp( last_name, cur_ifc->name ))
{
strcpy( last_name, cur_ifc->name );
if( print_out )
{
j++;
if( cur_ifc->type & (DOWN|DISABLED))
fprintf( out, "%s down, ", cur_ifc->name );
else
fprintf( out, "%s, ", cur_ifc->name );
if( j >= 4 )
{/* break the printout into separate lines */
fprintf(out, "\n" );
j = 0;
}
}
else
tot_unreach++;
}
}/*endfor*/
}/* endif */
else
{/*
** This node was found to be in the spanning tree
** but it may not have been printed because
** it was down or a max ttl was specified. If all of
** the interfaces of a specific name are down then print
** this interface as unreachable even though the node is
** reachable. Also print this interface name if none of
** the interfaces with this name were printed when the
** tree was printed out.
*/
for( cur_ifc = net->adj_list[v].interfaces.first; cur_ifc != NULL;
cur_ifc = cur_ifc->next )
{
if( strcmp( last_name, cur_ifc->name ))
{
if( !found || !found2 )
{
if( print_out )
{
j++;
if( !found )
fprintf( out, "%s down, ", last_name );
else
fprintf( out, "%s, ", last_name );
if( j >= 4 )
{
fprintf(out, "\n" );
j = 0;
}
}
else
tot_unreach++;
}
found = FALSE;
found2 = FALSE;
}/* end if */
strcpy( last_name, cur_ifc->name );
last_v = v;
if( !(cur_ifc->type & (DOWN|DISABLED)))
/*
** There is at least one interface with this name that is not
** down so don't print it.
*/
found = TRUE;
if( cur_ifc->in_tree )
/*
** There is at least one interface with this name that was
** printed with the latest source tree so don't print it
** here.
*/
found2 = TRUE;
}/* end for */
}/* end else */
}/* end if( SUBNET ) */
for( cur_ifc = net->adj_list[v].interfaces.first; cur_ifc != NULL;
cur_ifc = cur_ifc->next )
cur_ifc->in_tree = FALSE; /* reset for next round */
}/* end for each node */
if( !print_out )
fprintf( out, "%ld", tot_unreach );
fprintf(out, "\n" );
strcpy( last_name, "\0" );
return;
}
/*******************************************************************
FUNCTION: push_path_elem( Path_stack *stack, NAME name )
DESCRIPTION:
This function pushes a path element onto a stack for later
retrieval. It returns a pointer to the path element.
**********************************************************************/
Path_item *push_path_elem( Path_stack *stack, NAME name, long distance,
long threshold, int suspect, int same_node,
int print, u_long type )
{
Path_item *cur_elem;
cur_elem = (Path_item *)calloc(1, sizeof(Path_item));
strcpy( cur_elem->name, name );
cur_elem->distance = distance;
cur_elem->threshold = threshold;
cur_elem->same_node = same_node;
cur_elem->suspect = suspect;
cur_elem->print = print;
cur_elem->type = type;
if( stack->number == 0 )
{
stack->first = cur_elem;
cur_elem->next = NULL;
}
else
{
cur_elem->next = stack->first;
stack->first = cur_elem;
}
stack->number++;
return cur_elem;
}
/**************************************************************************
FUNCTION: pop_path_elem( Path_stack *stack )
DESCRIPTION:
This function deletes the top item in the path stack
and fixes the stack variables accordingly.
***************************************************************************/
void pop_path_elem( Path_stack *stack )
{
Path_item *cur_item;
if( stack->number > 0 )
{
cur_item = stack->first;
stack->first = cur_item->next;
free( cur_item );
stack->number--;
}
}
/*****************************************************************************
FUNCTION: print_path_stack( Path_stack *stack, FILE *out )
DESCRIPTION:
This function prints out the path saved in the stack. It is called
each time the source is reached to print the path taken to reach the
source.
***************************************************************************/
void print_path_stack( Path_stack *stack, long indent, FILE *out )
{
Path_item *cur_elem;
long i, cur_threshold = 0, hops=1;
long nxt_thresh;
/*
** For each element in the stack
*/
for( i = 1, cur_elem = stack->first; cur_elem != NULL; cur_elem = cur_elem->next )
{/*
** Calculate the ttl needed to reach this node from the source. A ttl of
** at least 2 is required to be forwarded out a link.
*/
nxt_thresh = (hops - 1) + cur_elem->threshold;
if( cur_elem->threshold == 1 )
nxt_thresh++;
if( nxt_thresh > cur_threshold )
cur_threshold = nxt_thresh;
/*
** This path element is in the stack but should not be printed out so
** go on to the next one. This is most likely a subnet node, it was
** placed in the stack to allow correct calculation of the thresholds.
*/
if( !cur_elem->print )
continue;
/*
** Indent the proper amount of spaces and print the node
*/
print_entry( out, cur_elem->name, indent, i,
cur_elem->distance, cur_threshold, cur_elem->suspect, TRUE,
cur_elem->type);
/*
** The same_node boolean is used to indicate when the next element in the
** stack will be an interface at the same site so don't increment
** the hop count.
*/
if( !cur_elem->same_node )
hops++;
i++;
}
return;
}
/************************************************************************
FUNCTION: print_path()
DESCRIPTION:
This function is called recursively to print a path from a
source to a destination. All paths of equal distance are
printed unless the branch is at a subnet connection. The
alternate paths are printed because the current version of
mrouted will not change paths if a new path appears that is
equal length so it is not always the low address path that wins.
The equal paths that branch at subnets will always use the
low address path because mrouted will always choose this way.
*************************************************************************/
void print_path( FILE *out, Network *net, int indent, NAME source, NAME cur,
long cur_node, Path_stack *stack )
{
long suspect, cur_metric;
Interface *cur_ifc, *back_ifc;
/*
** First, find out the parent interface of this node. If there
** is no parent interface, this must be the source so print out
** the path.
*/
cur_ifc = net->adj_list[cur_node].dist_vects.next_hop_subnet;
if( cur_ifc == NULL )
{
/*
** Although the source is at this node, I may not have entered the
** node on the source interface so I also need to print the interface
** I entered on.
*/
if(strcmp( source, cur ))
push_path_elem( stack, cur, 0, 0, FALSE, TRUE, TRUE, 0 );
if( verbose )
fprintf( out, "\nPath from specified source to destination:\n");
fprintf( out, "%s, 0/0/0\n", source );
print_path_stack( stack, indent, out );
if(strcmp( source, cur ))
pop_path_elem( stack );
return;
}
/*
** If this node is a subnet, I don't need to worry about equal
** distance path branching so simply push this node onto the
** path stack and investigate its parent node.
*/
if(net->adj_list[cur_node].type & SUBNET)
{
back_ifc = find_ifc( net, NULL, cur_ifc->to_name, cur_ifc->name );
suspect = FALSE;
if( back_ifc->type & SUSPECT )
suspect = TRUE;
push_path_elem( stack, cur, net->adj_list[cur_node].dist_vects.distance,
back_ifc->threshold, suspect, FALSE, FALSE,
back_ifc->type );
print_path( out, net, indent, source, cur_ifc->to_name,
cur_ifc->to_node, stack );
/*
** After returning, clean up the stack
*/
pop_path_elem( stack );
return;
}
/*
** If I have made it to here, then this is not a subnet node
** so I must investigate all paths of equal length that branch at
** this point.
*/
for( cur_ifc = net->adj_list[cur_node].interfaces.first; cur_ifc != NULL;
cur_ifc = cur_ifc->next )
if( !(cur_ifc->type & (DOWN | DISABLED)))
{
back_ifc = find_ifc( net, NULL, cur_ifc->to_name, cur_ifc->name );
if( back_ifc == NULL || (back_ifc->type & (DOWN | DISABLED)))
{/*
** For some reason this tunnel was not reported in both directions
** so, we will assume that the tunnel is actually down
*/
if( verbose )
printf( "reverse edge %s to %s not found or down, assuming edge is down\n",
cur_ifc->to_name, cur_ifc->name );
cur_ifc->type |= DOWN;
continue;
}
/*
** Determine the path length that would result if this edge were
** on the path and if it is greater than the distance
** to the source then this is not an alternate branch so go on to the
** next interface.
*/
if( reverse_path )
cur_metric = back_ifc->metric + net->adj_list[cur_ifc->to_node].dist_vects.distance;
else
cur_metric = cur_ifc->metric + net->adj_list[cur_ifc->to_node].dist_vects.distance;
if( cur_metric > net->adj_list[cur_node].dist_vects.distance )
continue;
suspect = FALSE;
if( back_ifc->type & SUSPECT )
suspect = TRUE;
/*
** If we have gotten this far, then this interface is on the current
** path so push it onto the path stack.
*/
push_path_elem( stack, cur, net->adj_list[cur_node].dist_vects.distance,
back_ifc->threshold, suspect, FALSE, TRUE,
back_ifc->type);
/*
** The interface that we are going out is different than the one we
** arrived on so also push the interface we are leaving on onto the stack.
*/
if(strcmp( cur_ifc->name, cur ))
push_path_elem( stack, cur_ifc->name, net->adj_list[cur_node].dist_vects.distance,
back_ifc->threshold, suspect, TRUE, TRUE,
back_ifc->type);
/*
** Now to find the rest of the path to the source starting from here.
*/
print_path( out, net, indent, source, cur_ifc->to_name,
cur_ifc->to_node, stack );
/*
** Clean up the path stack and remove my entries
*/
pop_path_elem( stack );
if(strcmp( cur_ifc->name, cur ))
pop_path_elem( stack );
}
return;
}