All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

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

Add static routing support:

	# Turn on manual routing.
	$ns rtproto Manual

	# Set manual routes
	$nodeA add-route $nodeC $nodeB
	$nodeC add-route $nodeA $nodeB

results in this information being returned from the tmcd routing
command:

	ROUTERTYPE=manual
	ROUTE DEST=192.168.2.3 DESTTYPE=host DESTMASK=255.255.255.0 \
		NEXTHOP=192.168.3.2 COST=0

The reason for DESTTYPE and DESTMASK is so that we can also support
routing to links and lans, since doing it on a per host basis if not
only hugely tedious, but plain impossible if the destination node has
multiple links; the add-route syntax takes a node, but we need the IP
of the relevant link in order to run the route add commands on the
nodes. So, I've "extended" the syntax of add-route so that you can
give it a Link or a Lan as the dest:

	$nodeA add-route $link0 $nodeB
	$nodeA add-route [$ns link $nodeB $nodeC] $nodeB

In this case, the DESTTYPE=net, and the netmask is no longer ignored;
it is used in the route add command. Currently, the mask is hardwired
in the DB to 255.255.255.0, but by providing it in the tmcd command,
we change it later if needed.

I did not implement add-route-to-adj-node since that is not really
useful in our context, and we definitely do not want the user to
change the default routes on his nodes. But, its easy to add if we
need to.

The client side stuff is not done yet.
parent 3fc9e424
...@@ -212,6 +212,19 @@ LanLink instproc fill_ips {} { ...@@ -212,6 +212,19 @@ LanLink instproc fill_ips {} {
} }
} }
#
# Return the subnet of a lan. Actually, just return one of the IPs.
#
LanLink instproc get_subnet {} {
$self instvar nodelist
set nodeport [lindex $nodelist 0]
set node [lindex $nodeport 0]
set port [lindex $nodeport 1]
return [$node ip $port]
}
Link instproc rename {old new} { Link instproc rename {old new} {
$self next $old $new $self next $old $new
......
...@@ -32,6 +32,10 @@ Node instproc init {s} { ...@@ -32,6 +32,10 @@ Node instproc init {s} {
# {} indicates an unassigned IP address for that port. # {} indicates an unassigned IP address for that port.
$self set iplist {} $self set iplist {}
# A route list.
$self instvar routelist
array set routelist {}
# The type of the node. # The type of the node.
$self set type "pc" $self set type "pc"
...@@ -88,6 +92,8 @@ Node instproc updatedb {DB} { ...@@ -88,6 +92,8 @@ Node instproc updatedb {DB} {
$self instvar routertype $self instvar routertype
$self instvar fixed $self instvar fixed
$self instvar agentlist $self instvar agentlist
$self instvar routelist
$self instvar sim
var_import ::GLOBALS::pid var_import ::GLOBALS::pid
var_import ::GLOBALS::eid var_import ::GLOBALS::eid
var_import ::GLOBALS::default_ip_routing_type var_import ::GLOBALS::default_ip_routing_type
...@@ -119,6 +125,8 @@ Node instproc updatedb {DB} { ...@@ -119,6 +125,8 @@ Node instproc updatedb {DB} {
sql exec $DB "insert into nseconfigs (pid,eid,vname,nseconfig) values ('$pid','$eid','$self','$nseconfig')"; sql exec $DB "insert into nseconfigs (pid,eid,vname,nseconfig) values ('$pid','$eid','$self','$nseconfig')";
} }
$self add_routes_to_DB $DB
# Update the DB # Update the DB
sql exec $DB "insert into virt_nodes (pid,eid,vname,type,ips,osname,cmd_line,rpms,deltas,startupcmd,tarfiles,failureaction,routertype,fixed) values (\"$pid\",\"$eid\",\"$self\",\"$type\",\"$ipraw\",\"$osid\",\"$cmdline\",\"$rpms\",\"$deltas\",\"$startup\",\"$tarfiles\",\"$failureaction\",\"$default_ip_routing_type\",\"$fixed\")"; sql exec $DB "insert into virt_nodes (pid,eid,vname,type,ips,osname,cmd_line,rpms,deltas,startupcmd,tarfiles,failureaction,routertype,fixed) values (\"$pid\",\"$eid\",\"$self\",\"$type\",\"$ipraw\",\"$osid\",\"$cmdline\",\"$rpms\",\"$deltas\",\"$startup\",\"$tarfiles\",\"$failureaction\",\"$default_ip_routing_type\",\"$fixed\")";
} }
...@@ -175,3 +183,62 @@ Node instproc next_portnumber {} { ...@@ -175,3 +183,62 @@ Node instproc next_portnumber {} {
set next_port [incr next_portnumber_] set next_port [incr next_portnumber_]
return $next_port return $next_port
} }
#
# Add a route.
# The nexthop to <dst> from this node is <target>.
#
Node instproc add-route {dst nexthop} {
$self instvar routelist
if {[info exists routelist($dst)]} {
perror "\[add-route] route from $self to $dst already exists!"
}
set routelist($dst) $nexthop
}
#
# Update DB with routes
#
Node instproc add_routes_to_DB {DB} {
var_import ::GLOBALS::pid
var_import ::GLOBALS::eid
$self instvar routelist
$self instvar sim
foreach dst [lsort [array names routelist]] {
set hop $routelist($dst)
#
# Convert hop IP address.
#
set hopip [$hop ip [$hop find_port [$sim find_link $self $hop]]]
switch -- [$dst info class] {
"Node" {
if {[llength [$dst set portlist]] != 1} {
perror "\[add-route] $dst must have only one link."
}
set dstip [$dst ip 0]
set type "host"
}
"SimplexLink" {
set link [$dst set mylink]
set src [$link set src_node]
set dstip [$src ip [$src find_port $link]]
set type "net"
}
"Link" {
set dstip [$dst get_subnet]
set type "net"
}
unknown {
perror "\[add-route] Bad argument. Must be a node or a link."
return
}
}
puts stderr "'$pid','$eid','$self','$dstip','$hopip','$type'"
sql exec $DB "insert into virt_routes (pid,eid,vname,dst,nexthop,dst_type) values ('$pid','$eid','$self','$dstip','$hopip','$type')";
}
}
...@@ -511,6 +511,8 @@ Simulator instproc rtproto {type args} { ...@@ -511,6 +511,8 @@ Simulator instproc rtproto {type args} {
if {($type == "Session") || ($type == "ospf")} { if {($type == "Session") || ($type == "ospf")} {
set default_ip_routing_type "ospf" set default_ip_routing_type "ospf"
} elseif {($type == "Manual")} {
set default_ip_routing_type "manual"
} else { } else {
punsup "rtproto: unsupported routing protocol ignored: $type" punsup "rtproto: unsupported routing protocol ignored: $type"
return return
...@@ -584,8 +586,6 @@ Simulator instproc link {src dst} { ...@@ -584,8 +586,6 @@ Simulator instproc link {src dst} {
set name sl[incr new_counter] set name sl[incr new_counter]
return [SimplexLink $name $reallink $dir] return [SimplexLink $name $reallink $dir]
return $reallink
} }
# get_subnet # get_subnet
...@@ -619,4 +619,3 @@ Simulator instproc add_program {prog} { ...@@ -619,4 +619,3 @@ Simulator instproc add_program {prog} {
$self instvar prog_list $self instvar prog_list
set prog_list($prog) {} set prog_list($prog) {}
} }
...@@ -85,6 +85,8 @@ DBQueryWarn("DELETE from virt_trafgens where pid='$pid' and eid='$eid'") or ...@@ -85,6 +85,8 @@ DBQueryWarn("DELETE from virt_trafgens where pid='$pid' and eid='$eid'") or
$errors++; $errors++;
DBQueryWarn("DELETE from virt_agents where pid='$pid' and eid='$eid'") or DBQueryWarn("DELETE from virt_agents where pid='$pid' and eid='$eid'") or
$errors++; $errors++;
DBQueryWarn("DELETE from virt_routes where pid='$pid' and eid='$eid'") or
$errors++;
DBQueryWarn("DELETE from nseconfigs where pid='$pid' and eid='$eid'") or DBQueryWarn("DELETE from nseconfigs where pid='$pid' and eid='$eid'") or
$errors++; $errors++;
DBQueryWarn("DELETE from eventlist where pid='$pid' and eid='$eid'") or DBQueryWarn("DELETE from eventlist where pid='$pid' and eid='$eid'") or
......
...@@ -8,6 +8,14 @@ use English; ...@@ -8,6 +8,14 @@ use English;
# is to interpret the NS file and create the appropriate entries in # is to interpret the NS file and create the appropriate entries in
# virt_nodes and virt_lans. After this script ends successfully the # virt_nodes and virt_lans. After this script ends successfully the
# NS file is no longer necessary. # NS file is no longer necessary.
#
sub usage()
{
print STDERR "Usage: $0 [-force] pid eid nsfile\n";
exit(-1);
}
my $force = 0;
my $state;
# #
# Configure variables # Configure variables
...@@ -30,32 +38,36 @@ use libtestbed; ...@@ -30,32 +38,36 @@ use libtestbed;
# #
$| = 1; $| = 1;
if ($#ARGV != 2) { #
print STDERR "Syntax: $0 pid eid ns_file\n"; # Check for -force, and ignore experiment state.
exit(1); #
if ($ARGV[0] eq "-force") {
$force = 1;
shift;
}
if (@ARGV != 3) {
usage();
} }
my ($pid,$eid,$nsfile) = @ARGV; my ($pid,$eid,$nsfile) = @ARGV;
if (! -r $nsfile) { if (! -r $nsfile) {
print STDERR "*** NS File '$nsfile' does not exist!\n"; die("*** $0:\n".
exit(1); " NS File '$nsfile' does not exist!\n");
} }
my $state;
print "Beginning pre run for $pid/$eid. " . TBTimeStamp() . "\n"; print "Beginning pre run for $pid/$eid. " . TBTimeStamp() . "\n";
if (! ($state = ExpState($pid, $eid))) { if (! ($state = ExpState($pid, $eid))) {
print STDERR "*** No such experiment $pid/$eid\n"; die("*** $0:\n".
exit(1); " No such experiment $pid/$eid\n");
} }
if ($state ne EXPTSTATE_NEW) { if (!$force && $state ne EXPTSTATE_NEW) {
print STDERR "*** Experiment is not in the proper state: $state\n"; die("*** $0:\n".
exit(1); " Experiment is not in the proper state: $state\n");
} }
if (! SetExpState($pid, $eid, EXPTSTATE_PRERUN)) { if (! SetExpState($pid, $eid, EXPTSTATE_PRERUN)) {
print STDERR "*** Failed to set intermediate experiment state.\n"; die("*** $0:\n".
exit(1); " Failed to set intermediate experiment state.\n");
} }
# #
...@@ -67,6 +79,7 @@ sub cleanup { ...@@ -67,6 +79,7 @@ sub cleanup {
DBQueryWarn("DELETE from virt_lans where pid='$pid' and eid='$eid'"); DBQueryWarn("DELETE from virt_lans where pid='$pid' and eid='$eid'");
DBQueryWarn("DELETE from virt_trafgens where pid='$pid' and eid='$eid'"); DBQueryWarn("DELETE from virt_trafgens where pid='$pid' and eid='$eid'");
DBQueryWarn("DELETE from virt_agents where pid='$pid' and eid='$eid'"); DBQueryWarn("DELETE from virt_agents where pid='$pid' and eid='$eid'");
DBQueryWarn("DELETE from virt_routes where pid='$pid' and eid='$eid'");
DBQueryWarn("DELETE from nseconfigs where pid='$pid' and eid='$eid'"); DBQueryWarn("DELETE from nseconfigs where pid='$pid' and eid='$eid'");
DBQueryWarn("DELETE from eventlist where pid='$pid' and eid='$eid'"); DBQueryWarn("DELETE from eventlist where pid='$pid' and eid='$eid'");
SetExpState($pid, $eid, EXPTSTATE_NEW); SetExpState($pid, $eid, EXPTSTATE_NEW);
...@@ -76,16 +89,16 @@ sub cleanup { ...@@ -76,16 +89,16 @@ sub cleanup {
# and tb-* handling. # and tb-* handling.
print "Running parser ... " . TBTimeStamp() . "\n"; print "Running parser ... " . TBTimeStamp() . "\n";
if (system("parse-ns $pid $eid $nsfile")) { if (system("parse-ns $pid $eid $nsfile")) {
print STDERR "*** Parsing failed.\n";
cleanup(); cleanup();
exit(1); die("*** $0:\n".
" Parsing failed!\n");
} }
print "Parser done! Marking as prerunned. " . TBTimeStamp() . "\n"; print "Parser done! " . TBTimeStamp() . "\n";
if (!SetExpState($pid, $eid, EXPTSTATE_SWAPPED)) { if (!SetExpState($pid, $eid, EXPTSTATE_SWAPPED)) {
print STDERR "*** Failed to set experiment state!\n";
cleanup(); cleanup();
exit(1); die("*** $0:\n".
" Failed to set experiment state!\n");
} }
print "Pre run finished. " . TBTimeStamp() . "\n"; print "Pre run finished. " . TBTimeStamp() . "\n";
......
...@@ -7,13 +7,14 @@ ...@@ -7,13 +7,14 @@
# #
sub usage { sub usage {
print "Usage: $0 [-h] [-n] [-l] [-m] [-e] [-d] [-v] pid eid\n"; print "Usage: $0 [-h] [-n] [-l] [-m] [-e] [-d] [-r] [-v] pid eid\n";
print "-h Shows this message\n"; print "-h Shows this message\n";
print "-n Show node info\n"; print "-n Show node info\n";
print "-m Show node mapping\n"; print "-m Show node mapping\n";
print "-l Show link info\n"; print "-l Show link info\n";
print "-d Show traffic shapping info\n"; print "-d Show traffic shapping info\n";
print "-e Show event listing\n"; print "-e Show event listing\n";
print "-r Show routes\n";
print "-b Show most things\n"; print "-b Show most things\n";
print "-v Show everything!\n"; print "-v Show everything!\n";
return 1; return 1;
...@@ -23,6 +24,7 @@ my $TBROOT = "@prefix@"; ...@@ -23,6 +24,7 @@ my $TBROOT = "@prefix@";
my $DOMAIN = "@OURDOMAIN@"; my $DOMAIN = "@OURDOMAIN@";
use lib '@prefix@/lib'; use lib '@prefix@/lib';
use libtestbed;
use libdb; use libdb;
require exitonwarn; require exitonwarn;
use Getopt::Std; use Getopt::Std;
...@@ -42,6 +44,7 @@ my $showmap = 0; ...@@ -42,6 +44,7 @@ my $showmap = 0;
my $showlinks = 0; my $showlinks = 0;
my $showdelays = 0; my $showdelays = 0;
my $showevents = 0; my $showevents = 0;
my $showroutes = 0;
my %v2pmap; my %v2pmap;
my %p2type; my %p2type;
my %p2osid; my %p2osid;
...@@ -58,6 +61,7 @@ if ($opt{v}) { ...@@ -58,6 +61,7 @@ if ($opt{v}) {
$showdelays = 1; $showdelays = 1;
$showlinks = 1; $showlinks = 1;
$showevents = 1; $showevents = 1;
$showroutes = 1;
} }
if ($opt{b}) { if ($opt{b}) {
$shownodes = 1; $shownodes = 1;
...@@ -65,6 +69,7 @@ if ($opt{b}) { ...@@ -65,6 +69,7 @@ if ($opt{b}) {
$showdelays = 1; $showdelays = 1;
$showlinks = 1; $showlinks = 1;
$showevents = 1; $showevents = 1;
$showroutes = 1;
} }
if ($opt{n}) { if ($opt{n}) {
$shownodes = 1; $shownodes = 1;
...@@ -81,6 +86,9 @@ if ($opt{l}) { ...@@ -81,6 +86,9 @@ if ($opt{l}) {
if ($opt{e}) { if ($opt{e}) {
$showevents = 1; $showevents = 1;
} }
if ($opt{r}) {
$showroutes = 1;
}
if (@ARGV != 2) { if (@ARGV != 2) {
exit &usage; exit &usage;
} }
...@@ -255,6 +263,35 @@ if ($showdelays && ...@@ -255,6 +263,35 @@ if ($showdelays &&
} }
} }
#
# Print route list.
#
if ($showroutes) {
my $result =
DBQueryFatal("select vname,dst,dst_type,dst_mask,nexthop,cost ".
" from virt_routes where ".
"pid='$pid' and eid='$eid' order by vname");
if ($result->numrows) {
print "Route List:\n";
printf "%-15s %-15s %-15s %-15s %-8s \n",
"Node", "Dest", "Type/Mask", "Nexthop", "Cost";
print "--------------- --------------- --------------- ".
"--------------- --------\n";
while (($vname,$dst,$dst_type,$dst_mask,$nexthop,$cost) =
$result->fetchrow_array()) {
if ($dst_type eq "host") {
$dst_mask = "host";
}
printf "%-15s %-15s %-15s %-15s %-10s \n",
$vname, $dst, $dst_mask, $nexthop, $cost;
}
print "\n";
}
}
# #
# Print event list or summary # Print event list or summary
# #
......
...@@ -7,11 +7,34 @@ set node3 [$ns node] ...@@ -7,11 +7,34 @@ set node3 [$ns node]
set node4 [$ns node] set node4 [$ns node]
set node5 [$ns node] set node5 [$ns node]
$ns duplex-link $node0 $node1 100Mb .1ms DropTail set link0 [$ns duplex-link $node0 $node1 100Mb .1ms DropTail]
$ns duplex-link $node0 $node2 100Mb .1ms DropTail set link1 [$ns duplex-link $node0 $node2 100Mb .1ms DropTail]
$ns duplex-link $node0 $node3 10Mb 100ms DropTail set link2 [$ns duplex-link $node0 $node3 10Mb 100ms DropTail]
$ns duplex-link $node3 $node4 100Mb .1ms DropTail set link3 [$ns duplex-link $node3 $node4 100Mb .1ms DropTail]
$ns duplex-link $node3 $node5 100Mb .1ms DropTail set link4 [$ns duplex-link $node3 $node5 100Mb .1ms DropTail]
$ns run # Turn on manual routing.
$ns rtproto Manual
# Set manual routes
$node0 add-route $node4 $node3
$node0 add-route $node5 $node3
$node1 add-route $node2 $node0
$node1 add-route $link2 $node0
$node1 add-route $node4 $node0
$node1 add-route $node5 $node0
$node2 add-route $node1 $node0
$node2 add-route [$ns link $node3 $node0] $node0
$node2 add-route $node4 $node0
$node3 add-route $node1 $node0
$node3 add-route $node2 $node0
$node4 add-route $link2 $node3
$node4 add-route $node1 $node3
$node4 add-route $node2 $node3
$node4 add-route $node5 $node3
$node5 add-route [$ns link $node0 $node3] $node3
$node5 add-route $node1 $node3
$node5 add-route $node2 $node3
$node5 add-route $node4 $node3
$ns run
...@@ -1978,6 +1978,7 @@ COMMAND_PROTOTYPE(dorouting) ...@@ -1978,6 +1978,7 @@ COMMAND_PROTOTYPE(dorouting)
char eid[64]; char eid[64];
char gid[64]; char gid[64];
char buf[MYBUFSIZE]; char buf[MYBUFSIZE];
int nrows;
/* /*
* Now check reserved table * Now check reserved table
...@@ -2019,6 +2020,39 @@ COMMAND_PROTOTYPE(dorouting) ...@@ -2019,6 +2020,39 @@ COMMAND_PROTOTYPE(dorouting)
client_writeback(sock, buf, strlen(buf), tcp); client_writeback(sock, buf, strlen(buf), tcp);
info("ROUTES: %s", buf); info("ROUTES: %s", buf);
/*
* Get the routing type from the nodes table.
*/
res = mydb_query("select dst,dst_type,dst_mask,nexthop,cost "
"from virt_routes as vi "
"left join reserved as r on r.vname=vi.vname "
"where r.node_id='%s' and "
" vi.pid='%s' and vi.eid='%s'",
5, nodeid, pid, eid);
if (!res) {
error("ROUTES: %s: DB Error getting manual routes!\n", nodeid);
return 1;
}
if ((nrows = (int)mysql_num_rows(res)) == 0) {
mysql_free_result(res);
return 0;
}
while (nrows) {
row = mysql_fetch_row(res);
sprintf(buf, "ROUTE DEST=%s DESTTYPE=%s DESTMASK=%s "
"NEXTHOP=%s COST=%s\n",
row[0], row[1], row[2], row[3], row[4]);
client_writeback(sock, buf, strlen(buf), tcp);
nrows--;
info("ROUTES: %s", buf);
}
mysql_free_result(res);
return 0; 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