Commit 2198e78b authored by Leigh B Stoller's avatar Leigh B 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;
......@@ -489,6 +489,7 @@ sub membershaped($$) {
sub setmembershaped($$) {
my ($self, $member) = @_;
$self->shapedmembers()->{"$member"} = 1;
$member->_shaped(1);
}
###############################################################################
......@@ -1099,6 +1100,7 @@ sub LoadVirtNodes($)
# Set below from a desire.
$vnode->_sharedokay(0);
$vnode->_fixedvm(undef);
$vnode->_isbridge(($vnode->role() eq "bridge" ? 1 : 0));
# For a list of interfaces on this node, as for rspec generation
$vnode->_virtifaces([]);
......@@ -1480,7 +1482,8 @@ sub LoadVirtLans($)
$virtlan->_geninodes(0);
$virtlan->_implemented_by($implemented_by);
$virtlan->_vpath(undef);
$virtlan->_bridged(0);
if (defined($encap) &&
($encap eq "vtun" || $encap eq "gre" || $encap eq "egre")) {
$virtlan->_tunnel(1);
......@@ -1534,7 +1537,9 @@ sub LoadVirtLans($)
# shaped, or because it is being traced or monitored.
#
$virtlan->shapedmembers()->{"$vlanmember"} = 0;
$vlanmember->_shaped(0);
$virtlan->_delayed(0);
$vlanmember->_bridged(undef);
#
# XXX - Whenever a delay node is inserted, port speeds are set to
......@@ -1569,6 +1574,35 @@ sub LoadVirtLans($)
$self->printdb(" Forcing $vlanmember to reserve shared bandwidth\n");
}
}
#
# Check the bridge requests and set the cross links.
#
foreach my $virtlan (values(%{ $self->vlans() })) {
foreach my $member ($virtlan->memberlist()) {
next
if (!defined($member->bridged_vname()));
my $bridged_vname = $member->bridged_vname();
my $bridged_vnode = $member->bridged_vnode();
my $bridged_vport = $member->bridged_vport();
my $bridged_member =
$self->memberof()->{"$bridged_vnode:$bridged_vport"};
if (!defined($bridged_member)) {
tberror("$member is bridged to nonexistent member\n");
return -1;
}
if (!$member->virt_node()->_isbridge()) {
tberror("$member is bridged but is not a bridge\n");
return -1;
}
$member->_bridged($bridged_member);
$virtlan->_bridged(1);
$self->printdb("$virtlan bridge: $member to $bridged_member\n");
}
}
#
# Load the virt paths.
#
......@@ -2543,7 +2577,7 @@ sub GenVirtLans($)
next;
}
}
elsif (@members == 2) {
elsif (@members == 2 && !$vlan->_bridged()) {
#
# We treat LANs with two members specially - they are just links
#
......@@ -2554,7 +2588,7 @@ sub GenVirtLans($)
my $virtnode1 = $member1->virt_node();
my $vname0 = $virtnode0->vname();
my $vname1 = $virtnode1->vname();
my ($delay0,$bw0,$ebw0,$backfill0,$loss0,
$rdelay0,$rbw0,$rebw0,$rbackfill0,$rloss0) =
@{$member0->_delayinfo()};
......@@ -2818,7 +2852,7 @@ sub GenVirtLans($)
my $plink = "linksimple/$vname/$member0,$member1";
my $bw = '';
my $others = {'isgeninode' => $vlan->_geninodes()};
if ($emulated) {
$bw = max($top_bw,$top_rbw);
}
......@@ -2936,6 +2970,8 @@ sub GenVirtLans($)
$mustdelay ||
# Global force, or per-lan force.
$self->option('forcelinkdelays') || $uselinkdelay) &&
# No shaping on bridged lans.
!$vlan->_bridged() &&
# No shaping for geni nodes.
$vlan->_geninodes() == 0) {
$shaped = 1;
......@@ -2984,6 +3020,8 @@ sub GenVirtLans($)
my $rbandwidth = $self->getbandwidth($member,$vlan,$rbw);
if (($shaped || ($traced && !$trace_endnode)) &&
# Ignore for bridged links.
!$vlan->_bridged() &&
# if we have 1 real node in the LAN, we may need to create
# a lan
($realnodes != 0)) {
......@@ -5025,30 +5063,32 @@ sub InterpLinks($)
if ($self->InterpLinksAux() != 0);
#
# Find all the layer 2 paths and add the bridges between them.
# Eventually this should be optional; the user should be free
# to set this up themselves.
# Go through and look for bridge nodes.
#
foreach my $pathname (keys(%{ $self->vpaths() })) {
my $vpath = $self->vpaths()->{$pathname};
foreach my $virtual (keys(%{ $self->solution_v2p() })) {
my $pnode = $self->pnodes()->{$self->solution_v2p()->{$virtual}};
my $virtnode = $self->vnodes()->{$virtual};
next
if ($vpath->layer() != 2);
if (!$virtnode->_isbridge());
my @members = $vpath->virtlanlist();
next
if (scalar(@members) < 2);
# Links that are connected to this bridge.
my @virtlans = $virtnode->memberlist();
# A list of virtlans (segments)
my $prev = shift(@members);
my $next = shift(@members);
while ($next) {
my (undef, $member0) = $prev->memberlist();
my ($member1, undef) = $next->memberlist();
$self->AddBridge($vpath, $member0, $member1);
$prev = $next;
$next = shift(@members);
# Find the members that are connected through this bridge.
my @members;
foreach my $virtlan (@virtlans) {
foreach my $member ($virtlan->memberlist()) {
if ($member->virt_node()->vname() eq $virtnode->vname()) {
push(@members, $member);
}
}
}
# Can only bridge two links.
my ($member0,$member1) = @members;
$self->AddBridge($member0, $member1);
}
#
......@@ -5735,7 +5775,7 @@ sub InterpLinksAux($)
my ($delay,$bandwidth,$backfill,$loss,
$rdelay,$rbandwidth,$rbackfill,$rloss,$trivial_ok) =
@{$self->delaylinks()->{$plink}};
if (!$trivial_ok || ($trivial_ok && $trivial)) {
#
# Two entries, one for each side of the duplex link.
......@@ -6228,6 +6268,11 @@ sub InitializePhysNode($$$)
elsif ($pnode->_needslinkdelay()) {
$cmdline = $self->osidbootcmd($osid, "linkdelay", "");
}
elsif ($virtnode->_isbridge()) {
$osid = ($self->option("delay_osid") || $pnode->delay_osid());
$cmdline = $self->osidbootcmd($osid, "delay", "");
$role = TBDB_RSRVROLE_DELAYNODE();
}
elsif (defined($inner_elab_role) &&
($inner_elab_role eq "boss" ||
$inner_elab_role eq "boss+router")) {
......@@ -6842,13 +6887,11 @@ sub AddLinkDelay($$$$$$)
}
#
# Add a bridge. The DB table for bridges allows for any number of
# interfaces, but in practice there are only two when creating them
# inside of libvtop.
# Add a bridge. At the moment, bridges are just delay nodes.
#
sub AddBridge($$$$)
sub AddBridge($$$)
{
my ($self, $vpath, $member0, $member1) = @_;
my ($self, $member0, $member1) = @_;
my $iface0 = $member0->_pport();
my $iface1 = $member1->_pport();
my $pnodename = $member0->_pnode();
......@@ -6858,27 +6901,125 @@ sub AddBridge($$$$)
my $bridgeidx = $pnode->_pipenumber();
$pnode->_pipenumber($bridgeidx + 1);
# ipfw pipe numbers.
my $pipe0 = $pnode->_pipenumber();
my $pipe1 = $pipe0 + 10;
$pnode->_pipenumber($pipe1 + 10);
my $vnodename0 = $member0->vnode();
my $vnodename1 = $member1->vnode();
my $experiment = $self->experiment();
my $pid = $experiment->pid();
my $eid = $experiment->eid();
my $idx = $experiment->idx();
my $vname = $vpath->pathname();
# The name of the bridge (as for the delay agent) is the name of node.
# Might have to change this if we want to use a pnode for more then
# one bridge.
my $vname = $pnodename;
$self->printdb(" Bridge:$bridgeidx $iface0:$pnodename:$iface1\n");
DBQueryWarn("insert into bridges " .
" (pid,eid,exptidx,node_id,bridx,iface,vname,vnode) ".
" values ('$pid','$eid','$idx','$pnodename','$bridgeidx', ".
" '$iface0','$vname','$vnodename0')")
or return -1 if (! ($self->impotent() || $self->alloconly()));
# Grab the queue info.
my ($q0_limit,$q0_maxthresh,$q0_minthresh,$q0_weight,$q0_linterm,
$q0_qinbytes,$q0_bytes,$q0_meanpsize,$q0_wait,$q0_setbit,
$q0_droptail,$q0_red,$q0_gentle) = @{ $member0->_queueinfo() };
DBQueryWarn("insert into bridges " .
" (pid,eid,exptidx,node_id,bridx,iface,vname,vnode) ".
" values ('$pid','$eid','$idx','$pnodename','$bridgeidx', ".
" '$iface1','$vname','$vnodename1')")
my ($q1_limit,$q1_maxthresh,$q1_minthresh,$q1_weight,$q1_linterm,
$q1_qinbytes,$q1_bytes,$q1_meanpsize,$q1_wait,$q1_setbit,
$q1_droptail,$q1_red,$q1_gentle) = @{ $member1->_queueinfo() };
#
# And the shaping params. Since this bridge mimics the delay for
# a duplex link, we only use the "forward" params from each
# member.
#
my ($delay,$bandwidth,undef,$backfill,$lossrate) =
@{ $member0->_delayinfo() };
my ($rdelay,$rbandwidth,undef,$rbackfill,$rlossrate) =
@{ $member1->_delayinfo() };
# See if the user wants the bw shaping to be disabled.
$bandwidth = 0
if ($member0->nobwshaping());
$rbandwidth = 0
if ($member1->nobwshaping());
#
# We are inserting the bridge, but it might not be for shaping.
# Maybe for tracing. We use the estimated bandwidth field to
# signal this, but need a better approach.
#
my $noshaping = (defined($member0->est_bandwidth()) ||
defined($member1->est_bandwidth()) ? 0 : 1);
$self->printdb(" Shaping: $pipe0,$delay,$bandwidth,$lossrate\n".
" $pipe1,$rdelay,$rbandwidth,$rlossrate\n")
if (!$noshaping);
DBQueryWarn("insert into delays " .
" (pid,eid,exptidx,node_id,vname,noshaping,iface0,iface1" .
",vnode0,pipe0,delay0,bandwidth0,backfill0,lossrate0" .
",vnode1,pipe1,delay1,bandwidth1,backfill1,lossrate1" .
",q0_limit,q0_maxthresh,q0_minthresh,q0_weight,q0_linterm" .
",q0_qinbytes,q0_bytes,q0_meanpsize,q0_wait,q0_setbit" .
",q0_droptail,q0_red,q0_gentle" .
",q1_limit,q1_maxthresh,q1_minthresh,q1_weight,q1_linterm" .
",q1_qinbytes,q1_bytes,q1_meanpsize,q1_wait,q1_setbit" .
",q1_droptail,q1_red,q1_gentle)" .
" values ('$pid','$eid','$idx','$pnodename','$vname' ".
",$noshaping,'$iface0','$iface1'".
",'$vnodename0',$pipe0,$delay,$bandwidth,$backfill,$lossrate".
",'$vnodename1',$pipe1,$rdelay,$rbandwidth,$rbackfill".
",$rlossrate".
",$q0_limit,$q0_maxthresh,$q0_minthresh,$q0_weight,$q0_linterm".
",$q0_qinbytes,$q0_bytes,$q0_meanpsize,$q0_wait,$q0_setbit".
",$q0_droptail,$q0_red,$q0_gentle".
",$q1_limit,$q1_maxthresh,$q1_minthresh,$q1_weight,$q1_linterm".
",$q1_qinbytes,$q1_bytes,$q1_meanpsize,$q1_wait,$q1_setbit".
",$q1_droptail,$q1_red,$q1_gentle)")
or return -1 if (! ($self->impotent() || $self->alloconly()));
#
# Check for tracing.
#
my ($traced0, $endnode0, $trace_type0, $trace_expr0,
$trace_snaplen0, $trace_db0) = @{ $member0->_traceinfo() };
if ($traced0) {
$self->printdb(" Trace: $member0, $pnodename, $iface0, $iface1\n");
my $vname = $member0->virt_lan()->vname();
DBQueryWarn("insert into traces ".
" (node_id, idx, iface0, iface1, pid, eid, exptidx, ".
" linkvname, vnode, trace_type, trace_expr, ".
" trace_snaplen, trace_db) ".
"values ".
" ('$pnodename', 0, '$iface0', '$iface1','$pid','$eid', ".
" '$idx', '$vname', '$vnodename0', ".
" '$trace_type0', '$trace_expr0', $trace_snaplen0, ".
" '$trace_db0')")
or return -1 if (! ($self->impotent() || $self->alloconly()));
}
my ($traced1, $endnode1, $trace_type1, $trace_expr1,
$trace_snaplen1, $trace_db1) = @{ $member1->_traceinfo() };
if ($traced1) {
$self->printdb(" Trace: $member1, $pnodename, $iface1, $iface0\n");
my $vname = $member1->virt_lan()->vname();
DBQueryWarn("insert into traces ".
" (node_id, idx, iface0, iface1, pid, eid, exptidx, ".
" linkvname, vnode, trace_type, trace_expr, ".
" trace_snaplen, trace_db) ".
"values ".
" ('$pnodename', 0, '$iface1', '$iface0','$pid','$eid', ".
" '$idx', '$vname', '$vnodename1', ".
" '$trace_type1', '$trace_expr1', $trace_snaplen1, ".
" '$trace_db1')")
or return -1 if (! ($self->impotent() || $self->alloconly()));
}
#
# XXX - Whenever a bridge node is inserted, port speeds are set to
......@@ -6918,6 +7059,10 @@ sub SetUpTracing($$$$$)
my ($self, $virtlan, $member, $pnodename, $iface0, $iface1) = @_;
my $vnodename = $member->vnode();
# Bridged links handled elsewhere.
return 0
if ($virtlan->_bridged());
#
# Handle virtual nodes - in some cases (ie. PlanetLab), we have to
# look in v2vmap to find out which node we got placed on.
......
# -*- 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