r4893 - in developers/werner/wlan: . freeze

werner at docs.openmoko.org werner at docs.openmoko.org
Thu Jan 22 03:49:43 CET 2009


Author: werner
Date: 2009-01-22 03:49:42 +0100 (Thu, 22 Jan 2009)
New Revision: 4893

Added:
   developers/werner/wlan/freeze/
   developers/werner/wlan/freeze/README
   developers/werner/wlan/freeze/r1.pl
   developers/werner/wlan/freeze/r2.pl
   developers/werner/wlan/freeze/tst
Log:
Collection of scripts to try to reproduce the frozen station list and to
analyze the results.



Added: developers/werner/wlan/freeze/README
===================================================================
--- developers/werner/wlan/freeze/README	                        (rev 0)
+++ developers/werner/wlan/freeze/README	2009-01-22 02:49:42 UTC (rev 4893)
@@ -0,0 +1,118 @@
+Test setup:
+
+- Access point running OpenWrt "Kamikaze" or compatible
+
+- Give the Neo password-less SSH access to the access point, e.g., with
+
+  host# scp .ssh/id_rsa.pub neo:.ssh/
+  host# scp .ssh/id_rsa.pub access-point:/etc/dropbear/authorized_keys
+
+- The Neo must be able to connect to the access point over USB without
+  relying on a default route. This can be accomplished by port forwarding
+  on the host to which the Neo's USB is connected:
+
+  host# ssh -L *:2222:localhost:22 access-point
+
+- Boot the Neo, wait until the system has settled, then connect to the
+  serial console and log all the output:
+
+  host# neocon -T -l log -t 10 /dev/ttyUSB{1,2,3}
+
+  The -T option is optional. The timestamps may be used for further
+  analysis in the future.
+
+  It is important that this includes all printks. If necessary, increase
+  the loglevel with
+
+  neo# dmesg -n 8
+
+- Edit the configuration variables at the beginning of "tst".
+
+- Copy the test script to the Neo and run the test:
+
+  host# cp tst neo:
+  neo# ./tst
+
+  Optionally, the number of test runs can be passed as an argument to
+  "tst". 100 rounds take roughly one hour.
+
+
+What the test script does:
+
+- It simulates roaming by changing the frequency of the access point
+
+- Before each frequency change, connectivity is checked by pinging the
+  access point. Then, after the change, connectivity is checked again.
+  
+- In case of a communication failure before the frequency change, the
+  WLAN module is reset and a new test round is started.
+
+- In case of a communication failure after the frequency change, one
+  of the following three resolution strategies is randomly selected:
+
+  1) Perform an access point scan. If this is unsuccessful, perform
+     two scans in a row. Then three.
+
+  2) Re-issue the iwconfig command to configure the WLAN interface,
+     thereby manually forcing a re-association.
+
+  3) Remain idle for a random amount of time, up to five minutes,
+     then try communicating again. Repeat up to three times.
+
+  If the resolution is unsuccessful, do three times "iwlist scan",
+  reset the interface, then start a new round.
+
+
+The data we collect:
+
+- Kernel messages to track the state of the WLAN module
+
+- Many "iwlist scan" results. A telltale sign of the frozen access point
+  list problem is that only the access point we previously associated
+  with remains on the list and subsequent attempts to "iwlist scan" are
+  ignored.
+
+- Detailed ping results. Some abnormal situations may cause marginal
+  performance without not breaking communication completely. We keep the
+  data for later mining.
+
+
+Evaluation:
+
+- There are about 10kB of log data per round. The script r1.pl extracts
+  all state transitions and the most important events, and outputs them
+  in the following normalized format:
+
+  <type> <parameter> ...
+
+  Examples:
+
+  - STATE HOP 1 to 11
+    A frequency change from channels 1 to 11 is being attempted. Channel
+    1 is at 2412MHz.
+
+  - STATE ASSOC 6
+    WLAN has associated to the currently selected channel.
+
+  - STATE LATE 10
+    WLAN has associated to the previously selected channel.
+
+  - STATE WRONG 8
+    WLAN has associated to a channel that's neither the current nor the
+    previous.
+
+  - TIME 949864524
+    Timestamp, seconds since the beginning of the epoch. (In this example,
+    with a clock that's off by a few years :)
+
+- The script r2.pl further condenses the information into the chain of
+  events of individual runs, one run per line. The output can be modified
+  with the following options:
+
+  -v  include some parameters, such as the round number
+  -t  prefix each chain with the number of seconds it took till the next
+      round
+
+- Chains can be sorted by frequency with:
+
+  ./r1.pl log | ./r2.pl | sort | uniq -c | sort -rn

Added: developers/werner/wlan/freeze/r1.pl
===================================================================
--- developers/werner/wlan/freeze/r1.pl	                        (rev 0)
+++ developers/werner/wlan/freeze/r1.pl	2009-01-22 02:49:42 UTC (rev 4893)
@@ -0,0 +1,168 @@
+#!/usr/bin/perl
+#
+# r1.pl - reductor #1
+#
+# This reductor performs the following operations on a test session log:
+#
+# - remove "noise" messages
+# - compact ping and iwconfig sessions
+# - normalize state messages
+#
+
+
+$strict = 0;	# fail if input is incomprehensible
+
+$cc = 1;	# current channel
+$pc = undef;	# previous channel
+undef $special;	# special parser state
+
+
+sub scan
+{
+    local ($t) = @_;
+
+    if ($t =~ /^\s*$/) {
+	print "SCAN $tmp\n";
+	undef *special;
+	return;
+    }
+    if ($t =~ /ESSID:"([^"]*)"/) {
+	$tmp .= " " if defined $tmp;
+	$tmp .= $1;
+	return;
+    }
+    if ($t =~ /Frequency:.*Channel (\d+)/) {
+	# Note: when in trouble, the channel number may be reported as 0 !
+	$c = $1;
+	if ($c == $cc) {
+	    $tmp .= "(cur)";
+	} elsif ($c == $pc) {
+	    $tmp .= "(last)";
+	} else {
+	    $tmp .= "($c)";
+	}
+	return;
+    }
+}
+
+
+sub ping
+{
+    local ($t) = @_;
+
+    return if $t =~ /^64 bytes/;
+    return if $t =~ /^\s*$/;
+    return if $t =~ /^--- 192/;
+    if ($t =~ /^ping: sendmsg/) {
+	$tmp = "E ";
+	return;
+    }
+    if ($t =~ /^(\d+) packets transmitted, (\d+) received/) {
+	$tmp .= "$1/$2";
+	if (!$2) {
+	    print "PING $tmp\n";
+	    undef *special;
+	}
+	return;
+    }
+    if ($t =~ /^rtt[^,]*/) {
+	print "PING $tmp $&\n";
+	undef *special;
+	return;
+    }
+    die;
+}
+
+
+$scan = $ping = 1;
+
+while (1) {
+    $l = <>;
+    last unless defined $l;
+    $l =~ s/^\d+\.\d+ //;
+    if (defined $back) {
+	$l = $back.$l;
+	undef $back;
+    }
+    next if $l =~ /^\+/;
+
+    # asynchronous notifications
+
+    if ($l =~ /\[[^]]+\] (.*)\n/) {
+	$back = $`;
+	$t = $1;
+	next if $t =~ /^pcf/;
+	next if $t =~ /^power/;
+	next if $t =~ /^Network: Infrastructure/;
+	next if $t =~ /^s3c2440-sdi/;
+	next if $t =~ /^mmc0:/;
+	next if $t =~ /^ar6000_wow/;
+	next if $t =~ /^BMI Get/;
+	next if $t =~ /^mapped channel/;
+	if ($t =~ /^Target debug interrupt/) {
+	    print "STATE CRASH\n";
+	    next;
+	}
+	if ($t !~ /^AR6000 /) {
+	    die if $strict;
+	    next;
+	}
+	$t = $';
+	next if $t =~ /^Reg/;
+	if ($t =~ /^disconnected/) {
+	    print "STATE DISC\n";
+	    next;
+	}
+	if ($t !~ /connected.*freq (\d+)/) {
+	    die if $strict;
+	    next;
+	}
+	$c = ($1-2412)/5+1;
+	if ($c == $cc) {
+	    print "STATE ASSOC $c\n";
+	} elsif ($c == $pc) {
+	    print "STATE LATE $c\n";
+	} else {
+	    print "STATE WRONG $c\n";
+	}
+	next;
+    }
+
+    # special parsing states
+
+    if (defined $special) {
+	&special($l);
+	next;
+    }
+    if ($l =~ /^eth0\s+Scan completed/) {
+	*special = *scan;
+	undef $tmp;
+	next;
+    }
+    if ($l =~ /^PING/) {
+	*special = *ping;
+	undef $tmp;
+	next;
+    }
+
+    # synchronous notifications
+
+    if ($l =~ /^=== (.*) === (\d+)/) {
+	print "TIME $2\n";
+	$t = $1;
+	print "STATE $t\n";
+	if ($t =~ /RESET/) {
+	    undef $pc;
+	    $cc = 1;
+	    next;
+	}
+	if ($t =~ /HOP (\d+) to (\d+)/) {
+	    die if $cc != $1;
+	    $pc = $1;
+	    $cc = $2;
+	    next;
+	}
+	next;
+    }
+#print "$l";
+}


Property changes on: developers/werner/wlan/freeze/r1.pl
___________________________________________________________________
Name: svn:executable
   + *

Added: developers/werner/wlan/freeze/r2.pl
===================================================================
--- developers/werner/wlan/freeze/r2.pl	                        (rev 0)
+++ developers/werner/wlan/freeze/r2.pl	2009-01-22 02:49:42 UTC (rev 4893)
@@ -0,0 +1,60 @@
+#!/usr/bin/perl
+#
+# r2.pl - reductor #2
+#
+# This reductor takes a normalized session log and constructs the chains of
+# state transitions between visits to ROUND.
+#
+# The default output format omits all parameters so that one can easily do a
+# statistical analysis of the distinct chains.
+#
+
+$verbose = 0;
+$time = 0;
+
+while ($ARGV[0] =~ /^-/) {
+    if ($ARGV[0] eq "-v") {
+	shift(@ARGV);
+	$verbose = 1;
+    } elsif ($ARGV[0] eq "-t") {
+	shift(@ARGV);
+	$time = 1;
+    } else {
+	print STDERR "usage: $0 [-t] [-v]\n";
+	exit(1);
+    }
+}
+
+while (<>) {
+    $t = $1 if /^TIME (\d+)/;
+    next unless /^STATE/;
+    @s = split(/\s+/);
+    if ($s[1] eq "RESET") {
+	# if we enter RESET before HOP, this is in fact a problem that wasn't
+	# completely resolved in the previous round.
+	if ($last eq "ROUND") {
+	    $out[$#out-1] .= " + RESET";
+	}
+    }
+    $last = $s[1];
+    if ($s[1] eq "ROUND") {
+	$out[$#out] = ($t-$t0)." ".$out[$#out] if $time && defined $t0;
+	$t0 = $t;
+	if ($verbose) {
+	    $out[@out] = "#".$s[2];
+	} else {
+	    $out[@out] = "ROUND";
+	}
+    } elsif ($s[1] eq "HOP") {
+	if ($verbose) {
+	    $out[$#out] .= " -> HOP".$s[4];
+	} else {
+	    $out[$#out] .= " -> HOP";
+	}
+    } else {
+	next unless @out;
+	$out[$#out] .= " -> $s[1]";
+    }
+  
+}
+print join("\n", @out), "\n";


Property changes on: developers/werner/wlan/freeze/r2.pl
___________________________________________________________________
Name: svn:executable
   + *

Added: developers/werner/wlan/freeze/tst
===================================================================
--- developers/werner/wlan/freeze/tst	                        (rev 0)
+++ developers/werner/wlan/freeze/tst	2009-01-22 02:49:42 UTC (rev 4893)
@@ -0,0 +1,155 @@
+#!/bin/bash
+
+#
+# tst - try to force a WLAN failure by changing the frequency of the access
+#       point
+#
+
+# PING_IP is the addess we ping to check that we have a good WLAN connection
+# AP_IP is the address of the access point running OpenWRT
+# AP_PORT is the port we connect to
+# ESSID is the ESSID of the network we try to connect to
+# IWCONFIG is the configuration command we issue locally
+
+PING_IP=192.168.2.1
+AP_IP=192.168.0.200
+AP_PORT=2222
+ESSID=wgl
+IWCONFIG="key A4BEB3B8EC essid wgl"
+
+
+state()
+{
+    echo === "$@" === `date +"%s"`
+}
+
+
+channel()
+{
+    ssh -p $AP_PORT $AP_IP \
+      'uci set wireless.wl0.channel='$1' && \
+        uci commit wireless && \
+	PATH=$PATH:/usr/sbin wifi'
+    chan=$1
+}
+
+
+hop()
+{
+    while true; do
+	c=`expr $RANDOM % 11 + 1`
+	[ $c != $chan ] && break
+    done
+    state HOP $chan to $c
+    channel $c
+}
+
+
+ping_n()
+{
+    ping -A -n -c $1 $PING_IP
+}
+
+
+ping_nt()
+{
+    ping -A -n -c $1 -w $2 $PING_IP
+}
+
+
+reset()
+{
+    state RESET
+    channel 1
+    echo s3c2440-sdi >/sys/bus/platform/drivers/s3c2440-sdi/unbind
+    echo s3c2440-sdi >/sys/bus/platform/drivers/s3c2440-sdi/bind
+    sleep 10
+    iwlist scan
+    iwconfig eth0 $IWCONFIG
+    dhclient eth0
+    ping_n 50
+}
+
+
+try_iwconfig()
+{
+    state IWCONFIG
+    iwconfig eth0 $IWCONFIG
+    if ping_nt 100 60; then
+	return
+    fi
+    iwlist scan
+    iwlist scan
+    iwlist scan
+    reset
+}
+
+
+try_iwscan()
+{
+    try=1
+    while [ $try -le 3 ]; do
+    	state SCAN $try
+	i=$try
+	while [ $i -gt 0 ]; do
+	    iwlist scan
+	    i=`expr $i - 1`
+	done
+	if ping_nt 100 60; then
+	    return
+	fi
+	try=`expr $try + 1`
+    done
+    reset
+}
+
+
+try_idle()
+{
+    tries=3
+    while [ $tries -gt 0 ]; do
+	s=`expr $RANDOM % 300`
+	state IDLE $s
+	sleep $s
+	if ping_nt 100 60; then
+	    return
+	fi
+	tries=`expr $tries - 1`
+    done
+    iwlist scan
+    iwlist scan
+    iwlist scan
+    reset
+}
+
+
+round()
+{
+    state ROUND $n
+    if ! ping_nt 20 30; then
+	reset
+	return
+    fi
+    hop
+    if ping_nt 100 120; then
+	return
+    fi
+    state TROUBLE
+    case `expr $RANDOM % 3` in
+#    case 1 in
+	0)	try_iwconfig;;
+	1)	try_iwscan;;
+	2)	try_idle;;
+    esac
+}
+
+
+# kill the default route
+route del default
+
+reset
+n=0
+while [ $n != ${1:-100} ]; do
+    n=`expr $n + 1`
+    round $n
+done


Property changes on: developers/werner/wlan/freeze/tst
___________________________________________________________________
Name: svn:executable
   + *




More information about the commitlog mailing list