Commit 022436b0 authored by Gary Wong's avatar Gary Wong

Add attenuator control daemon, for PhantomNet.

parent f777e59c
......@@ -657,6 +657,7 @@ TBROBOCOPSEMAIL
TBOPSEMAIL_NOSLASH
TBOPSEMAIL
BS_IQN_PREFIX
ATTENUATOR
AMD_ROOT
WITHAMD
ZFS_NOEXPORT
......@@ -5146,6 +5147,7 @@ INCREMENTAL_MOUNTD=0
WITHAMD=0
AMD_ROOT=/.amd_mnt
BS_IQN_PREFIX=iqn.2000-10.net.emulab
ATTENUATOR=""
#
# XXX You really don't want to change these!
......
......@@ -311,6 +311,7 @@ AC_SUBST(INCREMENTAL_MOUNTD)
AC_SUBST(WITHAMD)
AC_SUBST(AMD_ROOT)
AC_SUBST(BS_IQN_PREFIX)
AC_SUBST(ATTENUATOR)
#
# Offer both versions of the email addresses that have the @ escaped
......@@ -472,6 +473,7 @@ INCREMENTAL_MOUNTD=0
WITHAMD=0
AMD_ROOT=/.amd_mnt
BS_IQN_PREFIX=iqn.2000-10.net.emulab
ATTENUATOR=""
#
# XXX You really don't want to change these!
......@@ -1334,6 +1336,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
utils/remove_old_www utils/epmodeset \
utils/mkblob utils/rmblob utils/ctrladdr utils/tcppd \
utils/mktestbedtest utils/pxelinux_makeconf \
utils/addvpubaddr utils/attend utils/atten \
www/GNUmakefile www/defs.php3 www/dbdefs.php3 www/xmlrpc.php3 \
www/xmlrpcpipe.php3 \
www/swish.conf www/websearch \
......
......@@ -194,3 +194,6 @@ INCREMENTAL_MOUNTD=1
# Blockstores
BS_IQN_PREFIX=iqn.2000-10.net.emulab
# Programmable RF attenuator (for PhantomNet).
ATTENUATOR=patten1
......@@ -137,6 +137,11 @@ case "$1" in
@prefix@/sbin/apt_daemon
fi
if [ -n "@ATTENUATOR@" -a -x @prefix@/sbin/attend ]; then
echo -n " attend"
@prefix@/sbin/attend &
fi
#
# Could trigger experiment creation, so make sure everything
# else is setup first; i.e., run this last!
......@@ -225,6 +230,9 @@ case "$1" in
if [ -r /var/run/apt_daemon.pid ]; then
kill `cat /var/run/apt_daemon.pid`
fi
if [ -r /var/run/attend.pid ]; then
kill `cat /var/run/attend.pid`
fi
;;
*)
......
......@@ -54,7 +54,7 @@ SBIN_SCRIPTS = vlandiff vlansync withadminprivs export_tables cvsupd.pl \
update_sitevars delete_image sitecheckin sitecheckin_client \
mktestbedtest fixrootcert addservers poolmonitor \
node_exclude managetaint shutdown-shared imagerelease \
runsonxen pxelinux_makeconf imagetodir
runsonxen pxelinux_makeconf imagetodir attend atten
WEB_SBIN_SCRIPTS= webnewnode webdeletenode webspewconlog webarchive_list \
webwanodecheckin webspewimage webdumpdescriptor \
......
#!/usr/bin/perl -w
#
# Copyright (c) 2015 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
# This file is part of the Emulab network testbed software.
#
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this file. If not, see <http://www.gnu.org/licenses/>.
#
# }}}
#
use English;
use strict;
use IO::Socket::INET;
#
# Configure variables
#
my $TB = "@prefix@";
my $RTPORT = 0x10db; # 10 dB hex = 4315 decimal
my $SETUPPORT = 0x11db; # 11 dB hex = 4571 decimal
my $VERSION = 1;
#
# Turn off line buffering on output
#
$| = 1;
#
# Untaint the path
#
$ENV{'PATH'} = "$TB/bin:$TB/sbin:/bin:/usr/bin:/sbin:/usr/sbin";
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
#
# Testbed Support libraries
#
use lib "@prefix@/lib";
use libdb;
use libtestbed;
#
# Handle command-line options.
#
sub usage() {
print STDERR "Usage: $0 [-r] atten val\n" .
" where atten is the attenuator to control,\n" .
" val is the value (in dB) to use.\n" .
" if -r is specified, the request has real-time priority.\n";
exit( 1 );
}
my $rt;
if( $ARGV[ 0 ] eq "-r" ) {
$rt = 1;
shift;
}
usage() unless @ARGV == 2;
my $atten = $ARGV[ 0 ];
my $val = $ARGV[ 1 ];
my $daemon = new IO::Socket::INET( PeerAddr => '127.0.0.1',
PeerPort => $rt ? $RTPORT : $SETUPPORT,
Proto => 'tcp' )
or die "socket: $!\n";
$daemon->write( pack( "CCC", $VERSION, $atten, $val ), 3 )
or die "write: $!\n";
$daemon->close();
exit( 0 );
#!/usr/bin/perl -w
#
# Copyright (c) 2015 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
# This file is part of the Emulab network testbed software.
#
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this file. If not, see <http://www.gnu.org/licenses/>.
#
# }}}
#
use English;
use strict;
use IO::Select;
use IO::Socket::INET;
use POSIX;
#
# Configure variables
#
my $TB = "@prefix@";
my $RTPORT = 0x10db; # 10 dB hex = 4315 decimal
my $SETUPPORT = 0x11db; # 11 dB hex = 4571 decimal
my $ATTEN_ADDR = "@ATTENUATOR@";
my $ATTEN_PORT = 3001;
my $VERSION = 1;
my $pidfile = "/var/run/attend.pid";
#
# Socket state constants
#
my $TYPE_MASK = 0x8000;
my $STATE_MASK = 0x7FFF;
my $REAL_TIME = 0x8000;
my $SETUP = 0;
my $LISTENER = 0;
my $WAITING_VERSION = 1;
my $IDLE = 2;
my $ATTEN_LINK = 0x7FFF;
#
# Turn off line buffering on output
#
$| = 1;
#
# Untaint the path
#
$ENV{'PATH'} = "$TB/bin:$TB/sbin:/bin:/usr/bin:/sbin:/usr/sbin";
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
#
# Testbed Support libraries
#
use lib "@prefix@/lib";
use libdb;
use libtestbed;
$ATTEN_ADDR or die "No attenuator defined!\n";
$SIG{PIPE} = 'IGNORE';
# Listen ONLY on loopback interface -- don't accept control connections
# from remote hosts.
my $rt = new IO::Socket::INET( LocalAddr => '127.0.0.1',
LocalPort => "$RTPORT", Proto => 'tcp',
Listen => 10, ReuseAddr => 1,
Blocking => 0 )
or die "socket: $!\n";
my $setup = new IO::Socket::INET( LocalAddr => '127.0.0.1',
LocalPort => "$SETUPPORT", Proto => 'tcp',
Listen => 10, ReuseAddr => 1,
Blocking => 0 )
or die "socket: $!\n";
my $atten;
# Write our PID to a known location (to assist those who would kill us).
# Don't bother attempting to use the PID file as a lock -- the sockets
# we just listened on make a better mutex than a file would.
sysopen( PIDFILE, $pidfile, O_WRONLY | O_CREAT)
or die "Couldn't create '$pidfile': $? $!\n";
print PIDFILE "$$";
close PIDFILE;
my $selectlist = IO::Select->new( $rt, $setup )
or die "select: $!\n";
my @rtqueue = ();
my @setupqueue = ();
my %states = ( $rt->fileno => $REAL_TIME | $LISTENER,
$setup->fileno => $SETUP | $LISTENER );
sub atten_connect() {
do {
$atten = IO::Socket::INET->new( PeerAddr => $ATTEN_ADDR,
PeerPort => $ATTEN_PORT,
Proto => 'tcp' )
} until( defined( $atten ) );
$states{ $atten->fileno } = $ATTEN_LINK;
$selectlist->add( $atten );
}
sub cleanup($) {
my ($fh) = @_;
$selectlist->remove( $fh );
delete( $states{ $fh->fileno } );
$fh->close();
}
sub handle($) {
my ($fh) = @_;
my $state = $states{ $fh->fileno };
if( ( $state & $STATE_MASK ) == $LISTENER ) {
my $new = $fh->accept();
$new->blocking( 0 );
$states{ $new->fileno } = ( $state & $TYPE_MASK ) | $WAITING_VERSION;
$selectlist->add( $new );
} elsif( ( $state & $STATE_MASK ) == $WAITING_VERSION ) {
my $buf;
if( sysread( $fh, $buf, 1 ) ) {
# you can have whatever version you want, as long as it's 1
$fh->write( pack( "C", $VERSION ), 1 );
$states{ $fh->fileno }++;
} else {
cleanup( $fh );
}
} elsif( ( $state & $STATE_MASK ) == $IDLE ) {
my $buf;
my $len;
$len = sysread( $fh, $buf, 2 );
if( defined( $len ) && $len == 2 ) {
my $link;
my $val;
($link,$val) = unpack( "CC", $buf );
if( ( $state & $TYPE_MASK ) == $REAL_TIME ) {
$rtqueue[ ++$#rtqueue ] = "$link $val";
} else {
$setupqueue[ ++$#setupqueue ] = "$link $val";
}
} else {
cleanup( $fh );
}
} elsif( ( $state & $STATE_MASK ) == $ATTEN_LINK ) {
my $buf;
my $len;
do {
$len = sysread( $fh, $buf, 0xFFFF );
} while( defined( $len ) && $len == 0xFFFF );
if( !$len ) {
$selectlist->remove( $atten );
delete( $states{ $atten->fileno } );
$atten->close();
atten_connect();
}
}
}
sub update($) {
my ($pair) = @_;
print $atten "sa $pair\n";
}
atten_connect();
while( 1 ) {
while( my $pair = shift( @rtqueue ) ) {
# Handle ALL outstanding real-time updates, since they're our
# highest priority.
update( $pair );
}
if( my $pair = shift( @setupqueue ) ) {
# Handle ONE outstanding setup update, and then check for higher
# priority tasks.
update( $pair );
}
if( my @ready = $selectlist->can_read ) {
# Handle ONE ready setup socket, and then check for higher
# priority tasks.
handle( $ready[ 0 ] );
}
}
exit( 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