Commit a72fd9f8 authored by Leigh B. Stoller's avatar Leigh B. Stoller

Move the ddijkstra from common/libsetup.pm (revision 1.107) into here,

but now it is based on the topomap file (see tbsetup/gentopofile).
When the router type is static-ddijk, and there is a topomap file
present (gettopmap() returns valid) turn the topomap into input to
feed into the ddijkstra program. Take the output and feed that into
the parsing code.

NB: If we change the output of tmcd routing call, we have to change
the output of this program too. This will likely become a problem at
some point.
parent 8fd5c467
......@@ -62,6 +62,7 @@ sub doboot();
sub doshutdown();
sub doreconfig();
sub docleanup();
sub ddijkstra($);
# Parse command line.
if (! getopts($optlist, \%options)) {
......@@ -139,6 +140,15 @@ sub doboot()
return 0;
}
# Special case for distributed route calculation.
if ($type eq "static-ddijk") {
if (ddijkstra(\@routes)) {
close(RC);
fatal("Could not get routes from ddijkstra!");
}
$type = "static";
}
#
# Now convert static route info into OS route commands
# Also check for use of gated/manual and remember it.
......@@ -328,3 +338,156 @@ sub gatedsetup ()
return os_routing_enable_gated(TMGATEDCONFIG);
}
#
# Special case. If the routertype is "static-ddijk" then we run our
# dijkstra program on the linkmap, and use that to feed the code
# below (it outputs exactly the same goo).
#
# XXX: If we change the return from tmcd, the output of dijkstra will
# suddenly be wrong. Yuck, need a better solution.
#
# We have to generate the input file from the topomap.
#
sub ddijkstra ($)
{
my ($rptr) = @_;
my @routes = ();
my $linkmap = "$BOOTDIR/linkmap";
my $topomap;
my ($pid, $eid, $vname) = check_nickname();
if (gettopomap(\$topomap)) {
return -1;
}
# Gather up all the link info from the topomap
my %lans = ();
# The nodes section tells us the name of each node, and all its links.
foreach my $noderef (@{ $topomap->{"nodes"} }) {
my $vname = $noderef->{"vname"};
my $links = $noderef->{"links"};
# Links is a string of "$lan1:$ip1 $lan2:$ip2 ..."
foreach my $link (split(" ", $links)) {
my ($lan,$ip) = split(":", $link);
if (! defined($lans{$lan})) {
$lans{$lan} = {};
$lans{$lan}->{"members"} = {};
}
$lans{$lan}->{"members"}->{"$vname:$ip"} = $ip;
}
}
# The lans section tells us the masks and the costs.
foreach my $lanref (@{ $topomap->{"lans"} }) {
my $vname = $lanref->{"vname"};
my $cost = $lanref->{"cost"};
my $mask = $lanref->{"mask"};
$lans{$vname}->{"cost"} = $cost;
$lans{$vname}->{"mask"} = $mask;
}
#
# Construct input for Jon's dijkstra program.
#
if (! open(MAP, ">$linkmap")) {
warn("*** WARNING: Could not create $linkmap!\n");
@$rptr = ();
return -1;
}
# Count edges, but just once each.
my $edges = 0;
foreach my $lan (keys(%lans)) {
my @members = sort(keys(%{ $lans{$lan}->{"members"} }));
for (my $i = 0; $i < scalar(@members); $i++) {
for (my $j = $i; $j < scalar(@members); $j++) {
my $member1 = $members[$i];
my $member2 = $members[$j];
$edges++
if ($member1 ne $member2);
}
}
}
# Header line for Jon. numnodes numedges
print MAP scalar(@{ $topomap->{"nodes"} }) . " $edges\n";
# And then a list of edges: node1 ip1 node2 ip2 cost
foreach my $lan (keys(%lans)) {
my @members = sort(keys(%{ $lans{$lan}->{"members"} }));
my $cost = $lans{$lan}->{"cost"};
my $mask = $lans{$lan}->{"mask"};
for (my $i = 0; $i < scalar(@members); $i++) {
for (my $j = $i; $j < scalar(@members); $j++) {
my $member1 = $members[$i];
my $member2 = $members[$j];
if ($member1 ne $member2) {
my ($node1,$ip1) = split(":", $member1);
my ($node2,$ip2) = split(":", $member2);
print MAP "$node1 " . $ip1 . " " .
"$node2 " . $ip2 . " $cost\n";
}
}
}
}
close(MAP);
#
# Now run the dijkstra program on the input.
#
if (!open(DIJK, "cat $linkmap | $BINDIR/dijkstra $vname |")) {
warn("*** WARNING: Could not invoke dijkstra on linkmap!\n");
@$rptr = ();
return -1;
}
my $pat = q(ROUTE DEST=([0-9\.]*) DESTTYPE=(\w*) DESTMASK=([0-9\.]*) );
$pat .= q(NEXTHOP=([0-9\.]*) COST=([0-9]*) SRC=([0-9\.]*));
while (<DIJK>) {
if ($_ =~ /ROUTERTYPE=(.+)/) {
next;
}
if ($_ =~ /$pat/) {
my $dip = $1;
my $rtype = $2;
my $dmask = $3;
my $gate = $4;
my $cost = $5;
my $sip = $6;
my $rconfig = {};
$rconfig->{"IPADDR"} = $dip;
$rconfig->{"TYPE"} = $rtype;
$rconfig->{"IPMASK"} = $dmask;
$rconfig->{"GATEWAY"} = $gate;
$rconfig->{"COST"} = $cost;
$rconfig->{"SRCIPADDR"}= $sip;
push(@routes, $rconfig);
}
else {
warn("*** WARNING: Bad route config line: $_\n");
}
}
if (! close(DIJK)) {
if ($?) {
warn("*** WARNING: dijkstra exited with status $?!\n");
}
else {
warn("*** WARNING: Error closing dijkstra pipe: $!\n");
}
@$rptr = ();
return -1;
}
@$rptr = @routes;
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment