Commit 9ca9e1d9 authored by David Johnson's avatar David Johnson

* tmcd/common/ifdynconfig: New client side command, intended to be called

    from link-agent to provide dynamic link modification.  Calls
    liblocsetup::os_ifdynconfig_cmds to get a list of commands to change
    the iface config; if this function does not exist, it tries to do its
    best via ifconfig.

* tmcd/linux/liblocsetup.pm: Added support for dynamic configuration of
    ath and flex900 ifacetypes.  Also added more static support for both,
    including adhoc/monitor modes, rts threshold, etc, for ath; carrier
    threshold and rx gain for flex900 (sometimes these params really need
    to be set so our gnu radios can actually talk...).

* event/link-agent/link-agent.c: Do link up/down/modify by calling
    ifdynconfig with the event params.  Backwards compat with old
    functionality.
parent b8c6c2a1
......@@ -5,7 +5,9 @@
*/
/*
* Link Agent; very linux/wireless specific at the moment!
* Link Agent: supports up/down, parameterized modifications to interfaces.
* Commands are passed to a perl script and interpreted and executed in
* OS/device specific ways; this makes life easier for us all.
*/
#include <stdio.h>
......@@ -26,6 +28,7 @@
static char *progname;
static int debug = 0;
static int verbose = 0;
static char *ifdynconfig = "/usr/local/etc/emulab/ifdynconfig";
static void callback(event_handle_t handle,
event_notification_t notification, void *data);
......@@ -43,21 +46,6 @@ typedef struct ifmap {
} ifmap_t;
ifmap_t *mapping = (ifmap_t *) NULL;
/*
* List of allowed settings we can change. We do not worry about verifying
* the arguments; people are free to screw themselves.
*
* XXX Very iwconfig specific!
*/
char *settings[] = {
"sensitivity",
"txpower",
"channel",
"rate",
"bitrate",
"accesspoint"
};
void
usage()
{
......@@ -318,8 +306,6 @@ callback(event_handle_t handle, event_notification_t notification, void *data)
char eventtype[TBDB_FLEN_EVEVENTTYPE];
char args[2 * BUFSIZ];
char cmd[2 * BUFSIZ];
char updown[BUFSIZ];
int doupdown = 0; /* 1 = before, 2 = after */
ifmap_t *mp;
event_notification_get_objname(handle, notification,
......@@ -355,20 +341,23 @@ callback(event_handle_t handle, event_notification_t notification, void *data)
*/
if (strcmp(eventtype, TBDB_EVENTTYPE_UP) == 0) {
/* sprintf(cmd, "iwconfig %s txpower auto", mp->iface); */
sprintf(cmd, "ifconfig %s up", mp->iface);
sprintf(cmd, "%s %s up", ifdynconfig, mp->iface);
runcommand(cmd);
}
else if (strcmp(eventtype, TBDB_EVENTTYPE_DOWN) == 0) {
/* sprintf(cmd, "iwconfig %s txpower off", mp->iface); */
sprintf(cmd, "ifconfig %s down", mp->iface);
sprintf(cmd, "%s %s down", ifdynconfig, mp->iface);
runcommand(cmd);
}
else if (strcmp(eventtype, TBDB_EVENTTYPE_MODIFY) == 0) {
char *ap = args;
char *cp = cmd, *ecp = &cmd[sizeof(cmd)-1];
int cmdlen;
char cargs[2 * BUFSIZ];
char *cap = cargs, *ecap = &cargs[sizeof(cargs)-1];
int found_enable = 0;
cp += OUTPUT(cp, sizeof(cmd), "iwconfig %s ", mp->iface);
cp += OUTPUT(cp,sizeof(cmd),"%s %s ",ifdynconfig,mp->iface);
cmdlen = strlen(cmd);
/*
......@@ -429,82 +418,32 @@ callback(event_handle_t handle, event_notification_t notification, void *data)
* Alias for UP/DOWN events above. Note that
* we want to run this first/last.
*/
found_enable = 1;
if (! strcasecmp("yes", value)) {
doupdown = 2;
sprintf(updown,
"ifconfig %s up", mp->iface);
cp += OUTPUT(cp,ecp - cp, " up");
}
else if (! strcasecmp("no", value)) {
doupdown = 1;
sprintf(updown,
"ifconfig %s down", mp->iface);
cp += OUTPUT(cp,ecp - cp, " down");
}
else {
error("Ignoring setting: %s=%s\n",
setting, value);
found_enable = 0;
continue;
}
}
else if (! strcasecmp("sensitivity", setting)) {
cp += OUTPUT(cp, ecp - cp, " sens %s", value);
}
else if (! strcasecmp("txpower", setting)) {
if (*value == '\0')
value = "auto";
cp += OUTPUT(cp, ecp - cp, " txpower %s",
value);
}
else if (! strcasecmp("rate", setting) ||
! strcasecmp("bitrate", setting)) {
if (*value == '\0')
value = "auto";
cp += OUTPUT(cp, ecp - cp, " rate %s", value);
}
else if (! strcasecmp("channel", setting)) {
if (*value == '\0')
value = "3";
cp += OUTPUT(cp, ecp - cp, " channel %s",
value);
}
else if (! strcasecmp("accesspoint", setting)) {
char *mac = value;
if (! index(mac, ':')) {
mac = convertmac(mac);
if (mac == NULL)
continue;
}
if (strcasecmp(mac, mp->mac)) {
cp += OUTPUT(cp, ecp - cp,
" mode Managed ap %s",
mac);
}
else {
cp += OUTPUT(cp, ecp - cp,
" mode Master");
}
}
else {
error("Ignoring setting: %s=%s\n",
setting, value);
continue;
cap += OUTPUT(cap,ecap - cap," %s=%s",
setting,value);
}
info("%s\n", cmd);
}
if (doupdown == 1) {
runcommand(updown);
if (!found_enable) {
cp += OUTPUT(cp,ecp - cp," modify");
}
cp += OUTPUT(cp,ecp - cp," %s",cargs);
if (strlen(cmd) > cmdlen)
runcommand(cmd);
if (doupdown == 2) {
runcommand(updown);
}
}
else if (debug) {
info("Ignoring event: %s %s %s\n", objname, eventtype, args);
......
......@@ -77,6 +77,7 @@ common-script-install: dir-install
$(INSTALL) -m 755 $(SRCDIR)/runcvsup.sh $(BINDIR)/runcvsup.sh
$(INSTALL) -m 755 $(SRCDIR)/update $(BINDIR)/update
$(INSTALL) -m 755 $(SRCDIR)/ifsetup $(BINDIR)/ifsetup
$(INSTALL) -m 755 $(SRCDIR)/ifdynconfig $(BINDIR)/ifdynconfig
$(INSTALL) -m 755 $(SRCDIR)/vnodesetup $(BINDIR)/vnodesetup
$(INSTALL) -m 755 $(SRCDIR)/bootsubnodes $(BINDIR)/bootsubnodes
$(INSTALL) -m 755 $(SRCDIR)/bootvnodes $(BINDIR)/bootvnodes
......
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2007 University of Utah and the Flux Group.
# All rights reserved.
#
use English;
use Getopt::Std;
#
# Dynamically change the configuration of an interface. Since this is both
# OS- and interface type-dependent, it basically just calls into liblocsetup
# to get the appropriate commands to execute to perform the reconfig.
#
sub usage(;$) {
my $prog = shift;
if (!defined($prog)) {
$prog = '';
}
print "Usage: $prog iface up|down|modify [key1=val1 key2=val2 ... ]\n";
exit(1);
}
my $optlist = "d";
my $iface;
my $action;
# Drag in path stuff so we can find emulab stuff.
BEGIN { require "/etc/emulab/paths.pm"; import emulabpaths; }
# Only root.
if ($EUID != 0) {
die("*** $0:\n".
" Must be root to run this script!\n");
}
# Script specific goo.
my $IFCONFIG = "$BINDIR/rc/rc.ifconfig";
my $ROUTECONFIG = "$BINDIR/rc/rc.route";
my $TUNCONFIG = "$BINDIR/rc/rc.tunnels";
my $DELAYCONFIG = "$BINDIR/rc/rc.delays";
my $KEYCONFIG = "$BINDIR/rc/rc.keys";
my $TRACECONFIG = "$BINDIR/rc/rc.trace";
#
# Load the OS independent support library. It will load the OS dependent
# library and initialize itself.
#
use libsetup;
use libtmcc;
# Protos.
sub doboot();
sub doshutdown();
sub doreconfig();
sub docleanup();
my %options;
my $progname = $ARGV[0];
my $debug = 0;
my %modopts = ();
# Parse command line.
if (!getopts($optlist,\%options)) {
usage($progname);
}
if (defined($options{'d'})) {
$debug = 1;
}
# Allow default above.
if (@ARGV) {
$iface = shift @ARGV;
}
else {
usage();
}
if (@ARGV) {
$action = shift @ARGV;
$action = lc($action);
if ($action ne 'up' && $action ne 'down' && $action ne 'modify') {
print STDERR "ERROR: unknown action '$action'!\n";
exit(3);
}
}
else {
usage();
}
if ($action eq 'modify') {
if (!scalar(@ARGV)) {
print STDERR "ERROR: action modify, but no params!\n";
exit(4);
}
}
if (scalar(@ARGV)) {
# dump key=val params into a hash
foreach my $arg (@ARGV) {
my @ts = split(/=/,$arg);
if (scalar(@ts) != 2) {
# don't want the user to be fooled into thinking all configs
# happened, instead of only some...
print STDERR "ERROR: improper key=val pair '$arg'!\n";
exit(25);
}
else {
# NOTE: the event system changes these to uppercase; we want
# lowercase...
$modopts{lc($ts[0])} = $ts[1];
}
}
}
# grab the interface config data
my @ifacecfg;
libsetup::getifconfig(\@ifacecfg);
# find settings for our interface
my $iface_hashref;
foreach my $ifs (@ifacecfg) {
if ($ifs->{'IFACE'} eq $iface) {
$iface_hashref = $ifs;
last;
}
}
if (!defined($iface_hashref)) {
print STDERR "ERROR: could not find Emulab config data for " .
"interface '$iface'!\n";
exit(10);
}
# workaround until support is added to all osdep libs...
if (defined(&liblocsetup::os_ifdynconfig_cmds)) {
my @cmds = ();
my $retval = liblocsetup::os_ifdynconfig_cmds(\@cmds,$iface,$action,
\%modopts,$iface_hashref);
# execute...
foreach my $cmd (@cmds) {
print "cmd = '$cmd'\n";
system($cmd);
}
# we assume that these commands return 0 -- there's not a lot else we can
# do.
exit(0);
}
elsif ($action eq 'modify') {
print STDERR "ERROR: OS does not support parameterized " .
"link modification!\n";
exit(6);
}
else {
# best effort at up/down: ifconfig -- and assume it's in PATH
exit(system("ifconfig $iface $action"));
}
# should not get here
exit(0);
This diff is collapsed.
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