Commit 2198e78b authored by Leigh Stoller's avatar Leigh Stoller

Checkpoint initial version of my latest bridge code.

parent 86b9fe1b
......@@ -127,6 +127,7 @@ $EXPT_RESOURCESHOSED = 0;
"virt_user_environment",
"virt_parameters",
"virt_paths",
"virt_bridges",
# vis_nodes is locked during update in prerender, so we
# will get a consistent dataset when we backup.
"vis_nodes",
......
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2009-2010 University of Utah and the Flux Group.
# Copyright (c) 2009-2011 University of Utah and the Flux Group.
# All rights reserved.
#
package VirtExperiment;
......@@ -63,6 +63,7 @@ my $debug = 0;
"virt_vtypes" => [ "name" ],
"virt_programs" => [ "vname", "vnode" ],
"virt_user_environment" => [ "name", "value" ],
"virt_bridges" => [ "vname", "vlink", "vnode", "vport"],
"nseconfigs" => [ "vname" ],
"eventlist" => [ "idx" ],
"event_groups" => [ "group_name", "agent_name" ],
......@@ -1225,5 +1226,10 @@ use vars qw(@ISA);
@ISA = "VirtExperiment::VirtTableRow";
use VirtExperiment;
package VirtExperiment::VirtTableRow::virt_bridges;
use vars qw(@ISA);
@ISA = "VirtExperiment::VirtTableRow";
use VirtExperiment;
# _Always_ make sure that this 1 is at the end of the file...
1;
......@@ -4029,6 +4029,23 @@ CREATE TABLE `virt_blobs` (
PRIMARY KEY (`exptidx`,`vblob_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
--
-- Table structure for table `virt_bridges`
--
DROP TABLE IF EXISTS `virt_bridges`;
CREATE TABLE `virt_bridges` (
`pid` varchar(12) NOT NULL default '',
`eid` varchar(32) NOT NULL default '',
`exptidx` int(11) NOT NULL default '0',
`vname` varchar(32) NOT NULL default '',
`vlink` varchar(32) NOT NULL default '',
`vnode` varchar(32) NOT NULL default '',
`vport` tinyint(3) NOT NULL default '0',
PRIMARY KEY (`exptidx`,`vname`,`vlink`,`vnode`,`vport`),
KEY `pideid` (`pid`,`eid`,`vname`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
--
-- Table structure for table `virt_client_service_ctl`
--
......@@ -4214,6 +4231,9 @@ CREATE TABLE `virt_lans` (
`implemented_by_link` tinytext,
`ofenabled` tinyint(1) default '0',
`ofcontroller` tinytext,
`bridged_vname` varchar(32) default NULL,
`bridged_vnode` varchar(32) default NULL,
`bridged_vport` tinyint(3) default NULL,
PRIMARY KEY (`exptidx`,`vname`,`vnode`,`vport`),
UNIQUE KEY `vport` (`pid`,`eid`,`vname`,`vnode`,`vport`),
KEY `pid` (`pid`,`eid`,`vname`),
......@@ -4296,6 +4316,7 @@ CREATE TABLE `virt_nodes` (
`plab_plcnet` varchar(32) NOT NULL default 'none',
`numeric_id` int(11) default NULL,
`sharing_mode` varchar(32) default NULL,
`role` enum('node','bridge') NOT NULL default 'node',
PRIMARY KEY (`exptidx`,`vname`),
UNIQUE KEY `pideid` (`pid`,`eid`,`vname`),
KEY `pid` (`pid`,`eid`,`vname`)
......
......@@ -904,6 +904,9 @@ REPLACE INTO table_regex VALUES ('location_info','phone','text','regex','^[-\\d\
REPLACE INTO table_regex VALUES ('location_info','room','text','redirect','default:tinytext',0,0,NULL);
REPLACE INTO table_regex VALUES ('virt_lans','vnode','text','redirect','virt_nodes:vname',0,0,NULL);
REPLACE INTO table_regex VALUES ('virt_lans','vport','int','redirect','default:tinyint',0,99,NULL);
REPLACE INTO table_regex VALUES ('virt_lans','bridged_vname','text','redirect','virt_lans:vname',0,0,NULL);
REPLACE INTO table_regex VALUES ('virt_lans','bridged_vnode','text','redirect','virt_nodes:vname',0,0,NULL);
REPLACE INTO table_regex VALUES ('virt_lans','bridged_vport','int','redirect','virt_lans:vport',0,0,NULL);
REPLACE INTO table_regex VALUES ('virt_lans','ip','text','regex','^(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})$',0,15,NULL);
REPLACE INTO table_regex VALUES ('experiments','usemodelnet','int','redirect','default:boolean',0,0,NULL);
REPLACE INTO table_regex VALUES ('experiments','modelnet_cores','int','redirect','default:tinyint',0,5,NULL);
......@@ -922,6 +925,7 @@ REPLACE INTO table_regex VALUES ('firewall_rules','eid','text','redirect','exper
REPLACE INTO table_regex VALUES ('firewall_rules','fwname','text','redirect','virt_nodes:vname',0,0,NULL);
REPLACE INTO table_regex VALUES ('firewall_rules','ruleno','int','redirect','default:int',0,50000,NULL);
REPLACE INTO table_regex VALUES ('firewall_rules','rule','text','regex','^\\w[-\\w \\t,/\\{\\}\\(\\)!:\\.]*$',0,1024,NULL);
REPLACE INTO table_regex VALUES ('virt_nodes','role','text','regex','^(node|bridge)$',0,0,NULL);
REPLACE INTO table_regex VALUES ('virt_nodes','inner_elab_role','text','regex','^(boss|boss\\+router|router|ops|ops\\+fs|fs|node)$',0,0,NULL);
REPLACE INTO table_regex VALUES ('virt_nodes','plab_role','text','regex','^(plc|node|none)$',0,0,NULL);
REPLACE INTO table_regex VALUES ('experiments','elab_in_elab','int','redirect','default:boolean',0,0,NULL);
......@@ -1078,7 +1082,12 @@ REPLACE INTO table_regex VALUES ('virt_paths','pathname','text','redirect','virt
REPLACE INTO table_regex VALUES ('virt_paths','segmentname','text','redirect','virt_nodes:vname',0,0,NULL);
REPLACE INTO table_regex VALUES ('virt_paths','segmentindex','int','redirect','default:tinyuint',0,0,NULL);
REPLACE INTO table_regex VALUES ('virt_paths','layer','int','redirect','default:tinyint',0,0,NULL);
REPLACE INTO table_regex VALUES ('virt_bridges','pid','text','redirect','projects:pid',0,0,NULL);
REPLACE INTO table_regex VALUES ('virt_bridges','eid','text','redirect','experiments:eid',0,0,NULL);
REPLACE INTO table_regex VALUES ('virt_bridges','vname','text','redirect','virt_nodes:vname',0,0,NULL);
REPLACE INTO table_regex VALUES ('virt_bridges','vlink','text','redirect','virt_lans:vname',0,0,NULL);
REPLACE INTO table_regex VALUES ('virt_bridges','vnode','text','redirect','virt_nodes:vname',0,0,NULL);
REPLACE INTO table_regex VALUES ('virt_bridges','vport','int','redirect','default:tinyint',0,99,NULL);
REPLACE INTO table_regex VALUES ('virt_lans','implemented_by_path','text','redirect','virt_paths:pathname',1,128,NULL);
REPLACE INTO table_regex VALUES ('virt_lans','implemented_by_link','text','redirect','default:tinytext',0,0,NULL);
......
#
# Add "role" to virt_nodes, for supporting alternate node roles, like
# as a bridge (delay, trace, etc). Add other slots to the virt_lans
# table to support bridges between links and lans.
#
use strict;
use libdb;
sub DoUpdate($$$)
{
my ($dbhandle, $dbname, $version) = @_;
if (!DBSlotExists("virt_nodes", "role")) {
DBQueryFatal("alter table virt_nodes add ".
" `role` enum('node','bridge') NOT NULL default 'node'");
}
if (!DBSlotExists("virt_lans", "bridge_vname")) {
print " *** Updating virt_lans ... please be patient.\n";
DBQueryFatal("alter table virt_lans add ".
" `bridged_vname` varchar(32) default NULL");
}
if (!DBSlotExists("virt_lans", "bridged_vnode")) {
print " *** Updating virt_lans ... please be patient.\n";
DBQueryFatal("alter table virt_lans add ".
" `bridged_vnode` varchar(32) default NULL");
}
if (!DBSlotExists("virt_lans", "bridged_vport")) {
print " *** Updating virt_lans ... please be patient.\n";
DBQueryFatal("alter table virt_lans add ".
" `bridged_vport` tinyint(3) default NULL");
}
if (!DBTableExists("virt_bridges")) {
DBQueryFatal("CREATE TABLE `virt_bridges` ( ".
" `pid` varchar(12) NOT NULL default '', ".
" `eid` varchar(32) NOT NULL default '', ".
" `exptidx` int(11) NOT NULL default '0', ".
" `vname` varchar(32) NOT NULL default '', ".
" `vlink` varchar(32) NOT NULL default '', ".
" `vnode` varchar(32) NOT NULL default '', ".
" `vport` tinyint(3) NOT NULL default '0', ".
" PRIMARY KEY (`exptidx`,`vname`,`vlink`,`vnode`,`vport`),".
" KEY `pideid` (`pid`,`eid`,`vname`) ".
") ENGINE=MyISAM DEFAULT CHARSET=latin1");
}
DBQueryFatal("replace into table_regex VALUES ".
" ('virt_bridges','pid','text','redirect',".
" 'projects:pid',0,0,NULL)");
DBQueryFatal("replace into table_regex VALUES ".
" ('virt_bridges','eid','text','redirect',".
" 'experiments:eid',0,0,NULL)");
DBQueryFatal("replace into table_regex VALUES ".
" ('virt_bridges','vname','text','redirect',".
" 'virt_nodes:vname',0,0,NULL)");
DBQueryFatal("replace into table_regex VALUES ".
" ('virt_bridges','vlink','text','redirect',".
" 'virt_lans:vname',0,0,NULL)");
DBQueryFatal("replace into table_regex VALUES ".
" ('virt_bridges','vnode','text','redirect',".
" 'virt_nodes:vname',0,0,NULL)");
DBQueryFatal("replace into table_regex VALUES ".
" ('virt_bridges','vport','int','redirect',".
" 'default:tinyint',0,99,NULL)");
DBQueryFatal("replace into table_regex VALUES ".
" ('virt_nodes','role','text','regex', ".
" '^(node|bridge)\$',0,0,NULL)");
DBQueryFatal("replace into table_regex VALUES ".
" ('virt_lans','bridged_vname','text','redirect',".
" 'virt_lans:vname',0,0,NULL)");
DBQueryFatal("replace into table_regex VALUES ".
" ('virt_lans','bridged_vnode','text','redirect',".
" 'virt_nodes:vname',0,0,NULL)");
DBQueryFatal("replace into table_regex VALUES ".
" ('virt_lans','bridged_vport','int','redirect',".
" 'virt_lans:vport',0,0,NULL)");
return 0;
}
1;
This diff is collapsed.
# -*- tcl -*-
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2010 University of Utah and the Flux Group.
# Copyright (c) 2000-2011 University of Utah and the Flux Group.
# All rights reserved.
#
......@@ -272,6 +272,7 @@ LanLink instproc init {s nodes bw d type} {
$self instvar cost
$self instvar linkq
$self instvar fixed_iface
$self instvar bridge_links
$self instvar iscloud
$self set iscloud 0
......@@ -459,35 +460,193 @@ LanLink instproc get_port {node} {
return {}
}
# Set the bridge link field
LanLink instproc bridge {srcport link node dstport} {
$self instvar bridge_links
set nodepair [list $node $srcport]
set bridge_links($nodepair) [list $link $node $dstport]
}
#
# Bridge from a LanLink to another Lanlink via node.
#
LanLink instproc bridge_with {link node} {
set srcvport [$self get_port $node]
set dstvport [$link get_port $node]
if {$srcvport == {}} {
perror "bridge_with: $node is not a member of $self";
return
}
if {$dstvport == {}} {
perror "bridge_with: $node is not a member of $link";
return
}
# Cross link
$self bridge $srcvport $link $node $dstvport
$link bridge $dstvport $self $node $srcvport
$node set_role "bridge"
}
#
# Find the queue object for a node on a link.
#
Link instproc Queue {node} {
$self instvar toqueue
$self instvar fromqueue
if {$node == [$self set src_node]} {
return $toqueue
} elseif {$node == [$self set dst_node]} {
return $fromqueue
} else {
perror "Queue: $node is not a member of $self"
return {}
}
}
#
# Ditto for a node in a lan.
#
LanLink instproc Queue {node} {
$self instvar nodelist
$self instvar linkq
set vport [$self get_port $node]
if {$vport == {}} {
perror "SetDelayParams: $node is not a member of $self";
return
}
set nodepair [list $node $vport]
return $linkq($nodepair)
}
#
# Set the delay params for a node on a link. This should be used
# ONLY in conjunction with the bridge code since it completely violates
# all rules about how the delay params in the virt_lans table are used.
#
LanLink instproc SetDelayParams {node todelay tobw toloss} {
$self instvar bandwidth
$self instvar rbandwidth
$self instvar nodelist
set vport [$self get_port $node]
set role [$node set role]
# Node better be a bridge
if {$role != "bridge"} {
perror "SetDelayParams: $node is not a bridge!\n"
return
}
if {$vport == {}} {
perror "SetDelayParams: $node is not a member of $self";
return
}
# This is the original bandwidth when the link is created.
# Remember it, for the mapper. Needs more thought.
foreach nodeport $nodelist {
$self set ebandwidth($nodeport) $bandwidth($nodeport)
$self set rebandwidth($nodeport) $rbandwidth($nodeport)
}
set realtodelay [parse_delay $todelay]
set realtobw [parse_bw $tobw]
$self set delay([list $node $vport]) $realtodelay
$self set loss([list $node $vport]) $toloss
$self set bandwidth([list $node $vport]) $realtobw
}
#
# Ditto for tracing.
#
Link instproc SetTraceParams {node {ttype "header"} {snaplen 0} {texpr ""}} {
$self instvar toqueue
$self instvar fromqueue
if {$node == [$self set src_node]} {
$toqueue trace $ttype $texpr
if {$snaplen > 0} {
$toqueue set trace_snaplen $snaplen
}
} elseif {$node == [$self set dst_node]} {
$fromqueue trace $ttype $texpr
if {$snaplen > 0} {
$fromqueue set trace_snaplen $snaplen
}
} else {
perror "SetTraceParams: $node is not a member of $self"
}
}
Lan instproc SetTraceParams {node {ttype "header"} {snaplen 0} {texpr ""}} {
$self instvar nodelist
$self instvar linkq
set vport [$self get_port $node]
set nodepair [list $node $vport]
set linkqueue $linkq($nodepair)
$linkqueue trace $ttype $texpr
if {$snaplen > 0} {
$linkqueue set trace_snaplen $snaplen
}
}
# fill_ips
# This fills out the IP addresses (see README). It determines a
# subnet, either from already assigned IPs or by asking the Simulator
# for one, and then fills out unassigned node:port's with free IP
# addresses.
LanLink instproc fill_ips {} {
$self instvar nodelist
$self instvar sim
$self instvar widearea
$self instvar netmask
set isremote 0
set netmaskint [inet_atohl $netmask]
#
# Find the entire set of nodeports that are reachable because of
# bridged links/lans.
#
set lanlist [list $self]
while {$lanlist != {}} {
set lan [lindex $lanlist 0]
lpop lanlist
set reachable($lan) 1
$lan instvar bridge_links
foreach nodeport [array names bridge_links] {
set linkage $bridge_links($nodeport)
set nextlan [lindex $linkage 0]
if {! [info exists reachable($nextlan)]} {
lappend lanlist $nextlan
}
}
}
# Determine a subnet (if possible) and any used IP addresses in it.
# ips is a set which contains all used IP addresses in this LanLink.
set subnet {}
foreach nodeport $nodelist {
set node [lindex $nodeport 0]
set port [lindex $nodeport 1]
set ip [$node ip $port]
set isremote [expr $isremote + [$node set isremote]]
if {$ip != {}} {
if {$isremote} {
perror "Not allowed to specify IP subnet of a remote link!"
foreach {lan num} [array get reachable] {
set nodelist [$lan set nodelist]
foreach nodeport $nodelist {
set node [lindex $nodeport 0]
set port [lindex $nodeport 1]
set ip [$node ip $port]
set isremote [expr $isremote + [$node set isremote]]
if {$ip != {}} {
if {$isremote} {
perror "Not allowed to specify IP subnet of a remote link!"
}
set ipint [inet_atohl $ip]
set subnet [inet_hltoa [expr $ipint & $netmaskint]]
set ips($ip) 1
$sim use_subnet $subnet $netmask
}
set ipint [inet_atohl $ip]
set subnet [inet_hltoa [expr $ipint & $netmaskint]]
set ips($ip) 1
$sim use_subnet $subnet $netmask
}
}
if {$isremote && [$self info class] != "Link"} {
......@@ -511,7 +670,7 @@ LanLink instproc fill_ips {} {
if {$subnet == {}} {
if {$isremote} {
set subnet [$sim get_subnet_remote]
} else {
} else
set subnet [$sim get_subnet $netmask]
}
}
......@@ -519,27 +678,30 @@ LanLink instproc fill_ips {} {
# Now we assign IP addresses to any node:port's without them.
set ip_counter 2
set subnetint [inet_atohl $subnet]
foreach nodeport $nodelist {
set node [lindex $nodeport 0]
set port [lindex $nodeport 1]
if {[$node ip $port] == {}} {
set ip {}
set max [expr ~ $netmaskint]
for {set i $ip_counter} {$i < $max} {incr i} {
set nextip [inet_hltoa [expr $subnetint | $i]]
if {! [info exists ips($nextip)]} {
set ip $nextip
set ips($ip) 1
set ip_counter [expr $i + 1]
break
foreach {lan num} [array get reachable] {
set nodelist [$lan set nodelist]
foreach nodeport $nodelist {
set node [lindex $nodeport 0]
set port [lindex $nodeport 1]
if {[$node ip $port] == {}} {
set ip {}
set max [expr ~ $netmaskint]
for {set i $ip_counter} {$i < $max} {incr i} {
set nextip [inet_hltoa [expr $subnetint | $i]]
if {! [info exists ips($nextip)]} {
set ip $nextip
set ips($ip) 1
set ip_counter [expr $i + 1]
break
}
}
if {$ip == {}} {
perror "Ran out of IP addresses in subnet $subnet."
set ip "255.255.255.255"
}
$node ip $port $ip
}
if {$ip == {}} {
perror "Ran out of IP addresses in subnet $subnet."
set ip "255.255.255.255"
}
$node ip $port $ip
}
}
}
......@@ -779,6 +941,7 @@ Link instproc updatedb {DB} {
$self instvar implemented_by
$self instvar ofenabled
$self instvar ofcontroller
$self instvar bridge_links
set vindex 0
$sim spitxml_data "virt_lan_lans" [list "vname" "failureaction"] [list $self $failureaction]
......@@ -926,6 +1089,23 @@ Link instproc updatedb {DB} {
lappend values ""
}
#
# Look for a bridge to a nodepair in another link or lan.
#
if { [info exists bridge_links($nodeport)] } {
set dest $bridge_links($nodeport)
set bridge_vname [lindex $dest 0]
set bridge_vnode [lindex $dest 1]
set bridge_vport [lindex $dest 2]
lappend fields "bridged_vname"
lappend values $bridge_vname
lappend fields "bridged_vnode"
lappend values $bridge_vnode
lappend fields "bridged_vport"
lappend values $bridge_vport
}
lappend fields "vindex"
lappend values $vindex
set vindex [expr $vindex + 1]
......@@ -969,6 +1149,7 @@ Lan instproc updatedb {DB} {
$self instvar fixed_iface
$self instvar ofenabled
$self instvar ofcontroller
$self instvar bridge_links
set vindex 0
if {$modelnet_cores > 0 || $modelnet_edges > 0} {
......@@ -1114,6 +1295,23 @@ Lan instproc updatedb {DB} {
lappend values ""
}
#
# Look for a bridge to a nodepair in another link or lan.
#
if { [info exists bridge_links($nodeport)] } {
set dest $bridge_links($nodeport)
set bridge_vname [lindex $dest 0]
set bridge_vnode [lindex $dest 1]
set bridge_vport [lindex $dest 2]
lappend fields "bridged_vname"
lappend values $bridge_vname
lappend fields "bridged_vnode"
lappend values $bridge_vnode
lappend fields "bridged_vport"
lappend values $bridge_vport
}
lappend fields "vindex"
lappend values $vindex
set vindex [expr $vindex + 1]
......
# -*- tcl -*-
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2010 University of Utah and the Flux Group.
# Copyright (c) 2000-2011 University of Utah and the Flux Group.
# All rights reserved.
#
......@@ -91,6 +91,7 @@ Node instproc init {s} {
$self set fixed ""
$self set nseconfig ""
$self set sharing_mode ""
$self set role ""
$self set topo ""
......@@ -158,6 +159,7 @@ Node instproc updatedb {DB} {
$self instvar failureaction
$self instvar inner_elab_role
$self instvar plab_role
$self instvar role
$self instvar plab_plcnet
$self instvar routertype
$self instvar fixed
......@@ -310,6 +312,11 @@ Node instproc updatedb {DB} {
lappend values $inner_elab_role
}
if { $role != "" } {
lappend fields "role"
lappend values $role
}
if { $plab_role != "none" } {
lappend fields "plab_role"
lappend values $plab_role
......@@ -685,3 +692,10 @@ Node instproc set_numeric_id {myid} {
set numeric_id $myid
}
Node instproc set_role {newrole} {
$self instvar role
set role $newrole
}
......@@ -719,7 +719,7 @@ while (($node,$type,$physnode,$class,$issubnode,$def_boot_osid,$reserved,
# features
#
$result = DBQueryFatal("SELECT DISTINCT node_id1, node_id2 " .
" FROM wires where logical=0");
" FROM wires where logical=0 and type!='Unused'");
my %connections = ();
while (my ($node_id1, $node_id2) = $result->fetchrow()) {
foreach my $nodes ([$node_id1, $node_id2], [$node_id2, $node_id1]) {
......
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