Commit d85afe43 authored by Leigh B Stoller's avatar Leigh B Stoller
Browse files

Merge branch 'master' of git-public.flux.utah.edu:/flux/git/emulab-devel

parents 6a7a5a0b ba73e37b
......@@ -36,9 +36,21 @@ inline double loss_distance(double a,double b) {
class tb_delay_info {
public:
// TODO: Make a real constructor!
tb_delay_info() : bandwidth(0), delay(0), loss(0.0),
adjust_to_native_bandwidth(false) { ; } ;
// Note the adjust_to_native_bandwidth flag below
int bandwidth;
int delay;
double loss;
// If true, we just use the native bandwidth of the interface that gets
// picked; the bandwidth member gets updated on every assignment. This only
// makes sense on virtual links.
bool adjust_to_native_bandwidth;
// TODO: We don't actually use any of these; we should get 'em out of here.
int bw_under,bw_over;
int delay_under,delay_over;
double loss_under,loss_over;
......@@ -62,12 +74,14 @@ public:
friend ostream &operator<<(ostream &o, const tb_delay_info& delay)
{
o << "tb_delay_info: bw=" << delay.bandwidth << "+" <<
delay.bw_over << "-" << delay.bw_under << "/" << delay.bw_weight;
o << " delay=" << delay.delay << "+" << delay.delay_over <<
"-" << delay.delay_under << "/" << delay.delay_weight;
o << " loss=" << delay.loss << "+" << delay.loss_over << "-" <<
delay.loss_under << "/" << delay.loss_weight;
// Only print out the stuff that matters, not all of the pieces we don't
// use
o << "tb_delay_info: bw=" << delay.bandwidth;
if (delay.adjust_to_native_bandwidth) {
o << "(adjusted)";
}
o << " delay=" << delay.delay;
o << " loss=" << delay.loss;
o << endl;
return o;
}
......
......@@ -98,8 +98,8 @@ top file: <line>*
<desire> ::= <desire_type><desire_name>:<float>
<desire_type> ::= | "?+" | "&*" | "*!"
<link_line1> ::= link <link_name> <interface> <interface> <int> <float> <float>
<link_flag>*
<link_line1> ::= link <link_name> <interface> <interface> <int|'*'> <float>
<float> <link_flag>*
<link_line2> ::= link <link_name> <interface> <interface> <int> <float> <float>
<link_type> <link_flag*>
<link_flag> ::= nodelay | emulated | trivial_ok | fixsrciface:<string> |
......@@ -124,7 +124,9 @@ Interpretation:
<desire> - see <feature> in the ptop file
<desire_type> - see <feature_type> in the ptop file
<link_line1> and <link_line2> - see notes below for the difference between the
two line types. See <link_line> in the ptop file.
two line types. See <link_line> in the ptop file. The integer gives the
bandwidth for the link, but if the special value '*' is given, assign
simply uses the native bandwidth of the interfaces selected.
<link_type> - when present, a valid mapping must put this virtual link on a
physical link of the same type. For multi-hop link mappings (ie. those
that traverse multiple switches), *all* links used must be of this type. I
......
......@@ -18,6 +18,7 @@ static const char rcsid[] = "$Id: parse_request_rspec.cc,v 1.16 2009-10-21 20:49
#include <fstream>
#include <sstream>
#include <sys/time.h>
#include "anneal.h"
#include "vclass.h"
......
......@@ -242,8 +242,18 @@ int parse_top(tb_vgraph &vg, istream& input)
l->type = link_type;
put(vedge_pmap,e,l);
if ((sscanf(bw.c_str(),"%d",&(l->delay_info.bandwidth)) != 1) ||
(sscanf(bwunder.c_str(),"%d",&(l->delay_info.bw_under)) != 1) ||
// Special flag: treat a bandwidth of '*' specially
if (!strcmp(bw.c_str(),"*")) {
l->delay_info.bandwidth = -2; // Special flag
l->delay_info.adjust_to_native_bandwidth = true;
} else {
if (sscanf(bw.c_str(),"%d",&(l->delay_info.bandwidth)) != 1) {
top_error("Bad line line, bad bandwidth characteristics.");
}
}
// Scan in the rest of the delay_info structure
if ((sscanf(bwunder.c_str(),"%d",&(l->delay_info.bw_under)) != 1) ||
(sscanf(bwover.c_str(),"%d",&(l->delay_info.bw_over)) != 1) ||
(sscanf(bwweight.c_str(),"%lg",&(l->delay_info.bw_weight)) != 1) ||
(sscanf(delay.c_str(),"%d",&(l->delay_info.delay)) != 1) ||
......@@ -288,10 +298,10 @@ int parse_top(tb_vgraph &vg, istream& input)
parsed_line[i] << ".");
}
}
#ifdef PER_VNODE_TT
tb_vnode *vnode1 = get(vvertex_pmap,node1);
tb_vnode *vnode2 = get(vvertex_pmap,node2);
#ifdef PER_VNODE_TT
if (l->emulated) {
if (!l->allow_trivial) {
vnode1->total_bandwidth += l->delay_info.bandwidth;
......@@ -304,6 +314,14 @@ int parse_top(tb_vgraph &vg, istream& input)
vnode2->link_counts[link_type]++;
}
#endif
// Some sanity checks: this combination is illegal for now
if (l->delay_info.adjust_to_native_bandwidth && (l->allow_trivial ||
l->emulated)) {
top_error("Auto-assigning bandwidth on trivial or emulated links"
" not allowed!");
}
}
} else if (command == string("make-vclass")) {
if (parsed_line.size() < 4) {
......
......@@ -336,47 +336,95 @@ float find_link_resolutions(resolution_vector &resolutions, pvertex pv,
++dest_switch_it) {
if (*source_switch_it == *dest_switch_it) continue;
tb_link_info info(tb_link_info::LINK_INTERSWITCH);
if (find_interswitch_path(*source_switch_it,*dest_switch_it,vlink->delay_info.bandwidth,
info.plinks, info.switches) != 0) {
bool first_link, second_link;
/*
* Check to see if either, or both, pnodes are actually the
* switches we are looking for
*/
if ((pv == *source_switch_it) || (pv ==
*dest_switch_it)) {
first_link = false;
} else {
first_link = true;
}
if ((dest_pv == *source_switch_it) ||
(dest_pv == *dest_switch_it)) {
second_link = false;
} else {
second_link = true;
}
if (first_link) {
// Check only whether the source interface is fixed - this is the
// first link in a multi-hop path
if (!find_best_link(pv,*source_switch_it,vlink,first,true,false)) {
// No link to this switch
SDEBUG(cerr << " interswitch failed - no first link"
<< endl;)
continue;
}
}
/*
* Check to see if either, or both, pnodes are actually the
* switches we are looking for
*/
bool first_link, second_link;
if ((pv == *source_switch_it) || (pv ==
*dest_switch_it)) {
first_link = false;
} else {
first_link = true;
}
if ((dest_pv == *source_switch_it) ||
(dest_pv == *dest_switch_it)) {
second_link = false;
} else {
second_link = true;
}
if (second_link) {
// Check only whether the dest interface is fixed - this is the
// last link in a multi-hop path
if (!find_best_link(dest_pv,*dest_switch_it,vlink,second,false,true)) {
// No link to tshis switch
SDEBUG(cerr << " interswitch failed - no second link" << endl;)
// Get link objects
if (first_link) {
// Check only whether the source interface is fixed - this is the
// first link in a multi-hop path
if (!find_best_link(pv,*source_switch_it,vlink,first,true,false)) {
// No link to this switch
SDEBUG(cerr << " interswitch failed - no first link"
<< endl;)
continue;
}
}
if (second_link) {
// Check only whether the dest interface is fixed - this is the
// last link in a multi-hop path
if (!find_best_link(dest_pv,*dest_switch_it,vlink,second,false,true)) {
// No link to tshis switch
SDEBUG(cerr << " interswitch failed - no second link" << endl;)
continue;
}
}
// For regular links, we just grab the vlink's bandwidth; for links
// where we're matching the link speed to the 'native' one for the
// interface, we have to look up interface speeds on both ends.
int bandwidth;
if (vlink->delay_info.adjust_to_native_bandwidth) {
// Grab the actual plink objects for both pedges - it's possible for
// one or both to be missing if we're linking directly to a switch
// (as with a LAN)
tb_plink *first_plink = NULL;
tb_plink *second_plink = NULL;
if (first_link) {
first_plink = get(pedge_pmap,first);
}
if (second_link) {
second_plink = get(pedge_pmap,second);
}
if (first_plink != NULL && second_plink != NULL) {
// If both endpoints are not switches, we use the minimum
// bandwidth
bandwidth = min(first_plink->delay_info.bandwidth,
second_plink->delay_info.bandwidth);
} else if (first_plink == NULL) {
// If one end is a switch, use the bandwidth from the other
// end
bandwidth = second_plink->delay_info.bandwidth;
} else if (second_plink == NULL) {
bandwidth = first_plink->delay_info.bandwidth;
} else {
// Both endpoints are switches! (eg. this might be a link between
// two LANs): It is not at all clear what the right semantics
// for this would be, and unfortunately, we can't catch this
// earlier. So, exiting with an error is crappy, but it's
// unlikely to happen in our regular use, and it's the best we
// can do.
cerr << "*** Using bandwidth adjustment on virutal links " <<
"between switches not allowed " << endl;
exit(EXIT_FATAL);
}
} else {
// If not auto-adjusting, just use the specified bandwidth
bandwidth = vlink->delay_info.bandwidth;
}
// Find a path on the switch fabric between these two switches
if (find_interswitch_path(*source_switch_it,*dest_switch_it,bandwidth,
info.plinks, info.switches) != 0) {
// Okay, we found a real resolution!
if (flipped) { // Order these need to go in depends on flipped bit
if (second_link) {
info.plinks.push_front(second);
......@@ -491,6 +539,8 @@ void resolve_link(vvertex vv, pvertex pv, tb_vnode *vnode, tb_pnode *pnode,
* doesn't usually get called for trivial links, and
* letting them fall through into the 'normal' link code
* below is disatrous!
* Note: We can't get here when doing adjust_to_native_bandwidth,
* since it's illegal to allow trivial links when it's in use.
*/
score_link_info(edge,pnode,dest_pnode,vnode,dest_vnode);
} else {
......@@ -784,6 +834,12 @@ void unscore_link_info(vedge ve,tb_pnode *src_pnode,tb_pnode *dst_pnode, tb_vnod
}
#endif
// If auto-adjusting the vlink bandwidth, we set it to a sentinel value
// so that we can detect any problems next time we do a score_link_info()
if (vlink->delay_info.adjust_to_native_bandwidth) {
vlink->delay_info.bandwidth = -2;
}
}
/*
......@@ -1019,6 +1075,22 @@ void score_link_info(vedge ve, tb_pnode *src_pnode, tb_pnode *dst_pnode, tb_vnod
{
tb_vlink *vlink = get(vedge_pmap,ve);
tb_pnode *the_switch;
// If this link is to be adjusted to the native speed of the interface, go
// ahead and do that now - we use the minimum of the two endpoint interfaces
// Note! Not currently supported on trivial links! (it's illegal for
// adjust_to_native_bandwidth and trivial_ok to both be true)
if (vlink->delay_info.adjust_to_native_bandwidth &&
vlink->link_info.type_used != tb_link_info::LINK_TRIVIAL) {
// Check for special sentinel value to make sure we remembered to re-set
// the value before
assert(vlink->delay_info.bandwidth == -2);
tb_plink *front_plink = get(pedge_pmap, vlink->link_info.plinks.front());
tb_plink *back_plink = get(pedge_pmap, vlink->link_info.plinks.back());
vlink->delay_info.bandwidth =
min(front_plink->delay_info.bandwidth, back_plink->delay_info.bandwidth);
}
switch (vlink->link_info.type_used) {
case tb_link_info::LINK_DIRECT:
SADD(SCORE_DIRECT_LINK);
......@@ -1479,9 +1551,13 @@ bool find_best_link(pvertex pv,pvertex switch_pv,tb_vlink *vlink,
}
} else {
// For non-emulated links, we're just looking for links with few (0,
// actually) users, and enough bandwidth
// actually) users, and enough bandwidth (if we're adjusting the bw
// on the vlink to match what's on the interfaces selected, we don't
// even need to check bandwidth)
if ((users < best_users) &&
(plink->delay_info.bandwidth >= vlink->delay_info.bandwidth)) {
(vlink->delay_info.adjust_to_native_bandwidth ||
(plink->delay_info.bandwidth >= vlink->delay_info.bandwidth)
)) {
best_pedge = *pedge_it;
best_distance = distance;
found_best = true;
......
......@@ -60,11 +60,7 @@ sub runTest
my $num = $_[2];
startProgram($dest, "sh /local/bw-bottleneck-wavelet/multiplex-server.sh $serverPort /local/bw-bottleneck-wavelet", 0);
sleep(2);
<<<<<<< scan-multiplex.pl
startProgram($source, "sh /bw-bottleneck/multiplex-client.sh $serverPort /bw-bottleneck end-$dest $duration $source-to-$dest-run-$run-$num", 0);
=======
startProgram($source, "sh /local/bw-bottleneck-wavelet/multiplex-client.sh $serverPort /local/bw-bottleneck-wavelet node-$dest.$exp.$proj.emulab.net $duration $source-to-$dest-run-$run-$num", 0);
>>>>>>> 1.2
sleep($duration * 11);
stopProgram($dest);
......@@ -77,22 +73,11 @@ $count = 0;
srand($run);
<<<<<<< scan-multiplex.pl
#while (1)
#{
# $i = int(rand($nodeCount));
# $j = int(rand($nodeCount));
for ($i = 1; $i <= $nodeCount; ++$i)
=======
my %PairHash = ();
my $iterLimit = $nodeCount*($nodeCount-1);
while (1)
>>>>>>> 1.2
{
<<<<<<< scan-multiplex.pl
for ($j = 1; $j <= $nodeCount; ++$j)
=======
$i = int(rand($nodeCount)) + 1;
$j = int(rand($nodeCount)) + 1;
......@@ -102,16 +87,7 @@ while (1)
}
if ($i != $j)
>>>>>>> 1.2
{
<<<<<<< scan-multiplex.pl
if ($i != $j)
{
runTest($i, $j, $count);
++$count;
# runTest($nodes[$i], $nodes[$j]);
}
=======
my $nodeString = $i . ":" . $j;
if( not ( $PairHash{$nodeString} ) )
{
......@@ -125,7 +101,6 @@ while (1)
{
next;
}
>>>>>>> 1.2
}
}
# sleep(600);
......
......@@ -17,7 +17,7 @@ LIB_SCRIPTS = GeniDB.pm GeniUser.pm \
GeniComponent.pm GeniCH.pm GeniEmulab.pm \
GeniAuthority.pm GeniCertificate.pm GeniAggregate.pm \
GeniUtil.pm GeniRegistry.pm GeniUsage.pm GeniHRN.pm \
GeniSES.pm GeniResource.pm
GeniSES.pm GeniResource.pm GeniXML.pm
SBIN_SCRIPTS = plabnodewrapper plabslicewrapper
SCRIPTS = genischemacheck.pl
......
......@@ -27,6 +27,7 @@ use GeniUtil;
use GeniUser;
use GeniComponent;
use GeniHRN;
use GeniXML;
use emutil;
use Lan;
use Data::Dumper;
......@@ -647,29 +648,22 @@ sub GetManifest($$)
}
my ($xml) = $query_result->fetchrow_array();
my $manifest =
eval { XMLin($xml, KeyAttr => [],
ForceArray => ["node", "link", "interface",
"interface_ref", "linkendpoints"]) };
if ($@) {
print STDERR "XMLin error reading manifest: $@\n";
my $manifest = GeniXML::Parse($xml);
if (!defined($manifest)) {
return undef;
}
#
# Update the manifest ticket to reflect the current expiration time.
#
$manifest->{'valid_until'} =
POSIX::strftime("20%y-%m-%dT%H:%M:%S",
gmtime(str2time($slice->expires())));
my $valid_date = POSIX::strftime("20%y-%m-%dT%H:%M:%S",
gmtime(str2time($slice->expires())));
GeniXML::SetText("valid_until", $manifest, $valid_date);
return $manifest
if (!$asxml);
$xml = eval { XMLout($manifest, "NoAttr" => 1, RootName => "manifest") };
if ($@) {
print STDERR "XMLout error on manifest: $@\n";
return undef;
}
$xml = $manifest->toString();
return $xml;
}
......@@ -1236,10 +1230,11 @@ sub Create($$$$$$)
$linkrspec, $node1rspec, $node2rspec) = @_;
my $clearinghouse;
my $linkname = $linkrspec->{"nickname"} || $linkrspec->{"virtual_id"};
my $linkname = GeniXML::GetVirtualId($linkrspec);
return undef
if (!defined($linkname));
my @interfaces = @{ $linkrspec->{'interface_ref'} };
my @interfaces = GeniXML::FindNodes("n:interface_ref",
$linkrspec)->get_nodelist();
my $experiment = Experiment->Lookup($slice->uuid());
if (!defined($experiment)) {
......@@ -1270,8 +1265,8 @@ sub Create($$$$$$)
my $iface2ref = $interfaces[1];
# These are the ips of the tunnel.
my $ip1 = $iface1ref->{'tunnel_ip'};
my $ip2 = $iface2ref->{'tunnel_ip'};
my $ip1 = GeniXML::GetText("tunnel_ip", $iface1ref);
my $ip2 = GeniXML::GetText("tunnel_ip", $iface2ref);
my $ctrlip1;
my $ctrlip2;
my $iface1;
......@@ -1296,7 +1291,7 @@ sub Create($$$$$$)
}
}
else {
my $node_uuid = $node1rspec->{'component_uuid'};
my $node_uuid = GeniXML::GetNodeId($node1rspec);
my $component = GeniComponent->CreateFromRegistry($node_uuid);
if (!defined($component)) {
......@@ -1331,7 +1326,7 @@ sub Create($$$$$$)
}
}
else {
my $node_uuid = $node2rspec->{'component_uuid'};
my $node_uuid = GeniXML::GetNodeId($node2rspec);
my $component = GeniComponent->CreateFromRegistry($node_uuid);
if (!defined($component)) {
......
This diff is collapsed.
......@@ -19,6 +19,7 @@ use vars qw(@ISA @EXPORT);
use GeniDB;
use GeniCertificate;
use GeniUtil;
use GeniXML;
use emutil qw(TBGetUniqueIndex);
use English;
use XML::Simple;
......@@ -122,7 +123,7 @@ sub Create($$$)
$self->{'owner_cert'} = $owner->GetCertificate();
$self->{'string'} = undef;
$self->{'capabilities'} = undef;
$self->{'extensions'} = undef;
$self->{'extensions'} = XML::LibXML::NodeList->new();
$self->{'idx'} = undef; # Only set when stored to DB.
bless($self, $class);
......@@ -184,11 +185,8 @@ sub AddExtension($$$)
return -1
if (!ref($self));
if (!defined($self->extensions())) {
$self->{'extensions'} = {};
}
$self->{'extensions'}->{$key} = $value;
my $newNode = XML::LibXML::Element->new($key);
$newNode->appendText($value);
return 0;
}
......@@ -249,7 +247,7 @@ sub CreateFromSigned($$;$)
unlink($filename);
}
# Use XML::Simple to convert to something we can mess with.
# Use XML::LibXML to convert to something we can mess with.
my $parser = XML::LibXML->new;
my $doc;
eval {
......@@ -259,28 +257,10 @@ sub CreateFromSigned($$;$)
print STDERR "Failed to parse credential string: $@\n";
return undef;
}
# Dig out the capabilities
my ($cap_node) = $doc->getElementsByTagName("privileges");
return undef
if (!defined($cap_node));
my $rawcapabilities =
eval { XMLin($cap_node->toString(),
ForceArray => [ "privilege" ] ) };
if ($@) {
print STDERR "XMLin error on capabilities: $@\n";
return undef;
}
my $capabilities = $rawcapabilities->{ "privilege" };
my $root = $doc->documentElement();
# Dig out the extensions
my ($extensions_node) = $doc->getElementsByTagName("extensions");
my $extensions = eval { XMLin($extensions_node->toString()) }
if (defined($extensions_node));
if ($@) {
print STDERR "XMLin error on extensions: $@\n";
return undef;
}
my $extensions = GeniXML::FindNodes('//n:extensions/*', $root);
# UUID of the credential.
my ($uuid_node) = $doc->getElementsByTagName("uuid");
......@@ -351,7 +331,7 @@ sub CreateFromSigned($$;$)
}
my $self = {};
$self->{'capabilities'} = $capabilities;
$self->{'capabilities'} = undef;
$self->{'extensions'} = $extensions;
$self->{'uuid'} = $this_uuid;
$self->{'valid_until'} = $expires;
......@@ -363,9 +343,44 @@ sub CreateFromSigned($$;$)
$self->{'idx'} = undef; # Only set when stored to DB.
bless($self, $class);
# Dig out the capabilities
foreach my $cap (GeniXML::FindNodes('.//n:privileges/n:privilege',
$root)->get_nodelist()) {
my $name = GeniXML::FindElement('n:name', $cap);
my $delegate = GeniXML::FindElement('n:can_delegate', $cap);
if (defined($name) && defined($delegate)) {
$self->AddCapability($name->textContent(),
$delegate->textContent());
}
}
return $self;
}
# Returns a NodeList for a given XPath using a given node as
# context. 'n' is defined to be the prefix for the namespace of the
# node.
#sub findnodes_n($$)
#{
# my ($path, $node) = @_;
# my $xc = XML::LibXML::XPathContext->new();
# my $ns = $node->namespaceURI();
# if (defined($ns)) {
# $xc->registerNs('ns', $node->namespaceURI());
# } else {
# $path =~ s/\bn://g;
# }
# return $xc->findnodes($path, $node);
#}
# Returns the first Node which matches a given XPath against a given
# node. Works like findnodes_n.
#sub findfirst_n($$)
#{
# my ($path, $node) = @_;
# return findnodes_n($path, $node)->pop();
#}
#
# Might have to delete this from the DB.
#
......@@ -413,11 +428,10 @@ sub Sign($$)
}
$cap_xml .= "</privileges>\n";
if (defined($self->extensions())) {
if ($self->extensions()->size() > 0) {
$cap_xml .= "<extensions>\n";
foreach my $key (keys(%{ $self->extensions() })) {
my $value = $self->extensions()->{$key};
$cap_xml .= "<$key>$value</$key>\n";
foreach my $node ($self->extensions()->get_nodelist()) {
$cap_xml .= $node->toString();
}
$cap_xml .= "</extensions>\n";
}
......
......@@ -31,6 +31,7 @@ use GeniSlice;
use GeniSliver;
use GeniUser;