diff --git a/files/etc/crontabs/root b/files/etc/crontabs/root
index 756221ae..0293c59c 100644
--- a/files/etc/crontabs/root
+++ b/files/etc/crontabs/root
@@ -1,4 +1,5 @@
*/5 * * * * /usr/local/bin/fccid
* * * * * /usr/local/bin/rssi_monitor
* * * * * /usr/local/bin/snrlog
+* * * * * /usr/local/bin/clean_zombie.sh
diff --git a/files/usr/local/bin/clean_zombie.sh b/files/usr/local/bin/clean_zombie.sh
new file mode 100755
index 00000000..f30935a7
--- /dev/null
+++ b/files/usr/local/bin/clean_zombie.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+<<'LICENSE'
+ Part of AREDN -- Used for creating Amateur Radio Emergency Data Networks
+ Copyright (C) 2018 Joe Ayers AE6XE
+ See Contributors file for additional contributors
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation version 3 of the License.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+ Additional Terms:
+
+ Additional use restrictions exist on the AREDN(TM) trademark and logo.
+ See AREDNLicense.txt for more info.
+
+ Attributions to the AREDN Project must be retained in the source code.
+ If importing this code into a new or existing project attribution
+ to the AREDN project must be added to the source code.
+
+ You must not misrepresent the origin of the material contained within.
+
+ Modified versions must be modified to attribute to the original source
+ and be marked in reasonable ways as differentiate it from the original
+ version.
+
+LICENSE
+
+# Look for hung 'iw' zombie processes prone to hang
+# when available memory is low.
+
+# wait for rssi_monitor and snrlog to run
+sleep 10
+
+for pid in `ps 2>/dev/null | egrep "^\s*\d+\s+root\s+\d+\s+Z\s+\[iw\]"| sed -e "s/^\s*//"| cut -f1 -d\ `
+do
+
+ # found an "iw" zombie
+ sleep 10 # give time in case process is naturally closing and needs more time
+ if [ -d /proc/$pid ] ; then
+ date >> /tmp/zombie.log
+ ps | egrep "^\s*${pid}" | grep -v grep | tail -1 >> /tmp/zombie.log
+ ppid=`cat /proc/$pid/status | grep -i ppid | cut -f2`
+ if [ -d /proc/$ppid ] ; then
+ ps | egrep "\s*${ppid}" | grep -v grep | tail -1 >> /tmp/zombie.log
+ if ( ! `grep crond /proc/$ppid/status 2>&1 > /dev/null` ) then
+ if [ $ppid -gt 1 ] ; then
+
+ # kill the zombie's parent process to free up resources
+ kill -9 $ppid 2>&1 >> /tmp/zombie.log
+ echo "Killed $ppid" >> /tmp/zombie.log
+ if [ `wc -l /tmp/zombie.log | cut -f1 -d\ ` -gt 100 ] ; then
+
+ # keep file size in check
+ cp /tmp/zombie.log /tmp/zombie.tmp
+ tail -80 /tmp/zombie.tmp > /tmp/zombie.log
+ rm -f /tmp/zombie.tmp
+ fi
+ fi
+ fi
+ fi
+ echo "" >> /tmp/zombie.log
+ fi
+done
diff --git a/files/usr/local/bin/rssi_monitor b/files/usr/local/bin/rssi_monitor
index 2e21a166..c790c673 100755
--- a/files/usr/local/bin/rssi_monitor
+++ b/files/usr/local/bin/rssi_monitor
@@ -57,34 +57,39 @@ sub getRSSI
delete $rssi{$_};
}
- open(FILE, "/usr/sbin/iw $iface station dump 2>&1 |") or die "/usr/sbin/iw failed $!";
+ chomp ($stationCount = `ls -1 /sys/kernel/debug/ieee80211/phy0/netdev:${iface}/stations | wc -l`);
- $neighborCount = 0;
- while($line = )
+ if ($stationCount >= 1)
{
- if($line =~ /Station (\S+) \(on $iface\)/) { $mac = $1;}
- if($antnum and $line =~ /signal:[ \t]+[-\d]+[ \t]*\[([-\d]+),[ \t]*([-\d]+)/)
- {
- $H = $1;
- $V = $2;
- }
+ open(FILE, "/usr/sbin/iw $iface station dump 2>&1 |") or die "/usr/sbin/iw failed $!";
- if ((not $antnum) and $line =~ /signal:[ \t]+[-\d]+[ \t]*\[([-\d]+)\]/)
+ $neighborCount = 0;
+ while($line = )
{
- $H = $1;
- }
- if ($H)
- {
- if ($H < -95) { $rssi{$mac}{"Hrssi"}=-96 ; }
- else { $rssi{$mac}{"Hrssi"}=$H ; }
- undef $H;
- $neighborCount += 1;
- }
- if ($V)
- {
- if ($V < -95) { $rssi{$mac}{"Vrssi"}=-96 ; }
- else { $rssi{$mac}{"Vrssi"}=$V ; }
- undef $V;
+ if($line =~ /Station (\S+) \(on $iface\)/) { $mac = $1;}
+ if($antnum and $line =~ /signal:[ \t]+[-\d]+[ \t]*\[([-\d]+),[ \t]*([-\d]+)/)
+ {
+ $H = $1;
+ $V = $2;
+ }
+
+ if ((not $antnum) and $line =~ /signal:[ \t]+[-\d]+[ \t]*\[([-\d]+)\]/)
+ {
+ $H = $1;
+ }
+ if ($H)
+ {
+ if ($H < -95) { $rssi{$mac}{"Hrssi"}=-96 ; }
+ else { $rssi{$mac}{"Hrssi"}=$H ; }
+ undef $H;
+ $neighborCount += 1;
+ }
+ if ($V)
+ {
+ if ($V < -95) { $rssi{$mac}{"Vrssi"}=-96 ; }
+ else { $rssi{$mac}{"Vrssi"}=$V ; }
+ undef $V;
+ }
}
}
}
@@ -95,14 +100,13 @@ sub getChannelScan
$chnum += 1;
if ($chnum == 8 or $chnum == 12 or $chnum == 100 or $chnum == 185) { $chnum -= 2; }
if ($chnum == 0) { $chnum = 1; }
- $freq = `iw list | grep "\\\[$chnum\\\]" | head -1`;
- $freq =~ /([\d]+)[ \t]+MHz[ \t]+/;
+ $freq = `iwinfo $iface freqlist | grep "Channel $chnum" | head -1 | sed -e "s/\\.//"`;
+ $freq =~ /([\d]+)[ \t]+GHz/;
$freq = $1;
}
-$antnum=`iw list | grep "Configured Antennas: TX" | cut -f6 -d" "`;
-chomp $antnum;
-if ($antnum eq "0x1")
+$antnum=`cat /sys/kernel/debug/ieee80211/phy0/ath9k/tx_chainmask`;
+if ($antnum == "1")
{
$antnum=0;
}
@@ -241,75 +245,69 @@ for (keys %rssi)
}
}
-if ($amac or not $neighborCount)
+if ($amac)
{
getChannelScan();
- if ($amac)
- {
- $datestring = localtime();
- if ($antnum) {print $lfh "$datestring: before $amac [ $rssi{$amac}{'Hrssi'}, $rssi{$amac}{'Vrssi'} ]\n";}
- else {print $lfh "$datestring: before $amac [ $rssi{$amac}{'Hrssi'}]\n";}
- }
+ $datestring = localtime();
+ if ($antnum) {print $lfh "$datestring: before $amac [ $rssi{$amac}{'Hrssi'}, $rssi{$amac}{'Vrssi'} ]\n";}
+ else {print $lfh "$datestring: before $amac [ $rssi{$amac}{'Hrssi'}]\n";}
system("/usr/sbin/iw $iface scan freq $freq passive > /dev/null");
- if ($amac)
+ sleep 5;
+
+ $beforeH = $rssi{$amac}{"Hrssi"};
+ if ($antnum) { $beforeV = $rssi{$amac}{"Vrssi"}; }
+
+ getRSSI() ;
+ $datestring = localtime();
+ if ($antnum) {print $lfh "$datestring: after $amac [ $rssi{$amac}{'Hrssi'}, $rssi{$amac}{'Vrssi'} ]\n";}
+ else {print $lfh "$datestring: after $amac [ $rssi{$amac}{'Hrssi'}]\n";}
+
+ $falpos = 0;
+ if ($antnum)
{
- sleep 5;
+ if (abs ( $beforeH - $rssi{$amac}{"Hrssi"} ) <= 2 and
+ abs ( $beforeV - $rssi{$amac}{"Vrssi"} ) <= 2 ) { $falpos = 1; }
+ }
+ elsif (abs ( $beforeH - $rssi{$amac}{"Hrssi"} ) <= 2 ) { $falpos = 1; }
- $beforeH = $rssi{$amac}{"Hrssi"};
- if ($antnum) { $beforeV = $rssi{$amac}{"Vrssi"}; }
+ if ( $falpos )
+ {
+ # if a false-positive (within 2dB change after a reset), then add data point to statistics
+ $aveH = (($rssiHist{$amac}{"aveH"}*$rssiHist{$amac}{"num"})+ $beforeH )
+ / ($rssiHist{$amac}{"num"} + 1 );
+ $sdH = sqrt((($rssiHist{$amac}{"num"}-1)*($rssiHist{$amac}{"sdH"}**2) +
+ (($beforeH-$aveH)*($beforeH-$rssiHist{$amac}{"aveH"})))
+ /$rssiHist{$amac}{"num"});
+ chomp $aveH;
+ chomp $sdH;
+ $rssiHist{$amac}{"aveH"} = $aveH;
+ $rssiHist{$amac}{"sdH"} = $sdH;
- getRSSI() ;
- $datestring = localtime();
- if ($antnum) {print $lfh "$datestring: after $amac [ $rssi{$amac}{'Hrssi'}, $rssi{$amac}{'Vrssi'} ]\n";}
- else {print $lfh "$datestring: after $amac [ $rssi{$amac}{'Hrssi'}]\n";}
-
- $falpos = 0;
if ($antnum)
{
- if (abs ( $beforeH - $rssi{$amac}{"Hrssi"} ) <= 2 and
- abs ( $beforeV - $rssi{$amac}{"Vrssi"} ) <= 2 ) { $falpos = 1; }
+ $aveV = (($rssiHist{$amac}{"aveV"}*$rssiHist{$amac}{"num"})+ $beforeV ) /
+ ($rssiHist{$amac}{"num"} + 1 );
+ $sdV = sqrt((($rssiHist{$amac}{"num"}-1)*($rssiHist{$amac}{"sdV"}**2) +
+ (($beforeV-$aveV)*($beforeV-$rssiHist{$amac}{"aveV"}))) /
+ $rssiHist{$amac}{"num"});
+ chomp $aveV;
+ chomp $sdV;
+ $rssiHist{$amac}{"aveV"} = $aveV;
+ $rssiHist{$amac}{"sdV"} = $sdV;
}
- elsif (abs ( $beforeH - $rssi{$amac}{"Hrssi"} ) <= 2 ) { $falpos = 1; }
- if ( $falpos )
+ if ($rssiHist{$amac}{"num"} < 60 )
{
- # if a false-positive (within 2dB change after a reset), then add data point to statistics
- $aveH = (($rssiHist{$amac}{"aveH"}*$rssiHist{$amac}{"num"})+ $beforeH )
- / ($rssiHist{$amac}{"num"} + 1 );
- $sdH = sqrt((($rssiHist{$amac}{"num"}-1)*($rssiHist{$amac}{"sdH"}**2) +
- (($beforeH-$aveH)*($beforeH-$rssiHist{$amac}{"aveH"})))
- /$rssiHist{$amac}{"num"});
- chomp $aveH;
- chomp $sdH;
- $rssiHist{$amac}{"aveH"} = $aveH;
- $rssiHist{$amac}{"sdH"} = $sdH;
-
- if ($antnum)
- {
- $aveV = (($rssiHist{$amac}{"aveV"}*$rssiHist{$amac}{"num"})+ $beforeV ) /
- ($rssiHist{$amac}{"num"} + 1 );
- $sdV = sqrt((($rssiHist{$amac}{"num"}-1)*($rssiHist{$amac}{"sdV"}**2) +
- (($beforeV-$aveV)*($beforeV-$rssiHist{$amac}{"aveV"}))) /
- $rssiHist{$amac}{"num"});
- chomp $aveV;
- chomp $sdV;
- $rssiHist{$amac}{"aveV"} = $aveV;
- $rssiHist{$amac}{"sdV"} = $sdV;
- }
-
- if ($rssiHist{$amac}{"num"} < 60 )
- {
- # keep statistics to 60 sample (minute) moving window
- $rssiHist{$amac}{"num"} += 1;
- }
- $rssiHist{$amac}{"last"} = $now + 5 ;
-
- $datestring = localtime();
- print $lfh "$datestring: $amac Possible valid data point, adding to statistics.\n";
+ # keep statistics to 60 sample (minute) moving window
+ $rssiHist{$amac}{"num"} += 1;
}
+ $rssiHist{$amac}{"last"} = $now + 5 ;
+
+ $datestring = localtime();
+ print $lfh "$datestring: $amac Possible valid data point, adding to statistics.\n";
}
}
diff --git a/files/www/cgi-bin/perlfunc.pm b/files/www/cgi-bin/perlfunc.pm
index b4cd836b..658f7170 100644
--- a/files/www/cgi-bin/perlfunc.pm
+++ b/files/www/cgi-bin/perlfunc.pm
@@ -607,29 +607,29 @@ sub get_wifi_signal
chomp $wifiintf;
my ($SignalLevel) = "N/A";
my ($NoiseFloor) = "N/A";
- foreach(`iw dev $wifiintf station dump`)
+ foreach(`iwinfo $wifiintf assoclient`)
{
- next unless /.+signal:\s+([-]?[\d]+)/;
+ next unless /.+[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}\s+([-]?[\d]+)/;
if ( $SignalLevel <= "$1" || $SignalLevel == "N/A" )
{
$SignalLevel=$1;
}
}
- foreach(`iw dev $wifiintf survey dump|grep -A 1 \"\\[in use\\]\"`)
- {
- next unless /([\d\-]+) dBm/;
+ open( my $NoiseFH , "<" , "/sys/kernel/debug/ieee80211/phy0/ath9k/dump_nfcal") or return ("N/A","N/A");
+ while (<$NoiseFH>) {
+ next unless /Channel Noise Floor : ([-]?[0-9]+)/;
$NoiseFloor=$1;
}
+ close($NoiseFH);
if ( $NoiseFloor == "N/A" )
{
- open( my $NoiseFH , "<" , "/sys/kernel/debug/ieee80211/phy0/ath9k/dump_nfcal") or return ("N/A","N/A");
- while (<$NoiseFH>) {
- next unless /Channel Noise Floor : ([-]?[0-9]+)/;
+ foreach(`iwinfo $wifiintf info | grep Signal`)
+ {
+ next unless /([\d\-]+) dBm/;
$NoiseFloor=$1;
}
- close($NoiseFH);
}
if ( $SignalLevel == "N/A" || $NoiseFloor == "N/A" )