Commit 949d9709 authored by Leigh Stoller's avatar Leigh Stoller

Wrap up a vinterface in an object, and add methods to reserve and free

shared bandwidth for that interface in the interface_state table.
parent ed7889f2
......@@ -144,6 +144,7 @@ sub switch_port($) { return $_[0]->{'WIRES'}->{'port2'}; }
# Interface State table
sub enabled($) { return $_[0]->{'STATE'}->{'enabled'}; }
sub tagged($) { return $_[0]->{'STATE'}->{'tagged'}; }
sub remaining_bandwidth { return $_[0]->{'STATE'}->{'remaining_bandwidth'}; }
sub IsExperimental($)
{
......@@ -428,6 +429,202 @@ sub LookUpWideAreaSwitch($$)
return undef;
}
####################################################################################
package Interface::VInterface;
use libdb;
use libtestbed;
use English;
use overload ('""' => 'Stringify');
my $nextfake = 0;
#
# Lookup by node_id,unit
#
sub Lookup($$$$)
{
my ($class, $nodeid, $unit) = @_;
$nodeid = $nodeid->node_id()
if (ref($nodeid));
my $query_result =
DBQueryWarn("select * from vinterfaces ".
"where node_id='$nodeid' and unit='$unit'");
return undef
if (!$query_result);
return undef
if (!$query_result->numrows);
my $vinterface = {};
$vinterface->{"DBROW"} = $query_result->fetchrow_hashref();
bless($vinterface, $class);
}
# accessors
sub field($$) { return ((! ref($_[0])) ? -1 : $_[0]->{'DBROW'}->{$_[1]}); }
sub node_id($) { return field($_[0], 'node_id'); }
sub unit($) { return field($_[0], 'unit'); }
sub mac($) { return field($_[0], 'mac'); }
sub IP($) { return field($_[0], 'IP'); }
sub mask($) { return field($_[0], 'mask'); }
sub type($) { return field($_[0], 'type'); }
sub iface($) { return field($_[0], 'iface'); }
sub rtabid($) { return field($_[0], 'rtabid'); }
sub vnode_id($) { return field($_[0], 'vnode_id'); }
sub exptidx($) { return field($_[0], 'exptidx'); }
sub virtlanidx($) { return field($_[0], 'virtlanidx'); }
sub vlanid($) { return field($_[0], 'vlanid'); }
sub bandwidth($) { return field($_[0], 'bandwidth'); }
# The virtual iface name is $type$unit
sub viface($) { return $_[0]->type() . $_[0]->unit(); }
#
# Create a new vinterface
#
sub Create($$$)
{
my ($class, $nodeid, $argref) = @_;
$nodeid = $nodeid->node_id()
if (ref($nodeid));
$argref->{'node_id'} = $nodeid;
# This is generated by the insert.
delete($argref->{'unit'})
if (exists($argref->{'unit'}));
my $query = "insert into vinterfaces set ".
join(",", map("$_='" . $argref->{$_} . "'", keys(%{$argref})));
my $query_result = DBQueryWarn($query);
return undef
if (!defined($query_result));
my $unit = $query_result->insertid;
return Interface::VInterface->Lookup($nodeid, $unit);
}
#
# Create a fake object, as for the mapper (assign_wrapper) during debugging.
#
sub MakeFake($$$)
{
my ($class, $nodeid, $argref) = @_;
$nodeid = $nodeid->node_id()
if (ref($nodeid));
$argref->{'node_id'} = $nodeid;
# This is usually generated by the insert.
$argref->{'unit'} = $nextfake++;
my $self = {};
$self->{"DBROW"} = $argref;
bless($self, $class);
return $self;
}
#
# Stringify for output.
#
sub Stringify($)
{
my ($self) = @_;
my $nodeid = $self->node_id();
my $unit = $self->unit();
my $iface = (defined($self->iface()) ? ":" . $self->iface() : "");
my $vnodeid = (defined($self->vnode_id()) ? ":" . $self->vnode_id() : "");
return "[VInterface: $nodeid:${unit}${iface}${vnodeid}]";
}
#
# On a shared node, we have to "reserve" the required bandwidth on
# the physical interface.
#
sub ReserveSharedBandwidth($$)
{
my ($self, $bandwidth) = @_;
my $nodeid = $self->node_id();
my $unit = $self->unit();
my $iface = $self->iface();
# Must be a trivial link.
return 0
if (!defined($iface));
#
# A non-zero bandwidth in the vinterfaces table tells us what has
# bee reserved for each interface. These are combined in the
# interface_state table to ensure we do not oversubscribe the physical
# link. When releasing a node, we have to be careful to release the
# shared bandwidth for each vinterface on that node.
#
DBQueryWarn("lock tables vinterfaces write, interface_state write")
or return -1;
my $query_result =
DBQueryWarn("update interface_state set ".
" remaining_bandwidth=remaining_bandwidth-${bandwidth} ".
"where node_id='$nodeid' and iface='$iface' and ".
"remaining_bandwidth>=$bandwidth");
if (!$query_result || !$query_result->affectedrows) {
DBQueryWarn("unlock tables");
return -1;
}
if (!DBQueryWarn("update vinterfaces set bandwidth=$bandwidth ".
"where node_id='$nodeid' and unit='$unit'")) {
DBQueryWarn("update interface_state set ".
" remaining_bandwidth=remaining_bandwidth+${bandwidth} ".
"where node_id='$nodeid' and iface='$iface'");
DBQueryWarn("unlock tables");
return -1;
}
$self->{"DBROW"}->{'bandwidth'} = $bandwidth;
DBQueryWarn("unlock tables");
return 0;
}
sub ReleaseSharedBandwidth($)
{
my ($self) = @_;
my $nodeid = $self->node_id();
my $unit = $self->unit();
my $iface = $self->iface();
my $bandwidth = $self->bandwidth();
# Trivial link?
return 0
if (!$bandwidth);
DBQueryWarn("lock tables vinterfaces write, interface_state write")
or return -1;
if (!DBQueryWarn("update interface_state set ".
" remaining_bandwidth=remaining_bandwidth+${bandwidth} ".
"where node_id='$nodeid' and iface='$iface'")) {
DBQueryWarn("unlock tables");
return -1;
}
# If this fails we need to clean up by hand. I will add a section
# to the nightly DB check that scans for mismatches.
if (!DBQueryWarn("update vinterfaces set bandwidth=0 ".
"where node_id='$nodeid' and unit='$unit'")) {
DBQueryWarn("unlock tables");
return -1;
}
$self->{"DBROW"}->{'bandwidth'} = 0;
DBQueryWarn("unlock tables");
return 0;
}
# _Always_ make sure that this 1 is at the end of the file...
1;
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