#!/bin/sh # Git tracking hash: 173904c1f969093cb659b252b6ba10b7eddb3ce7 # © 2018 Lifemote Bilisim ve Ticaret A.S. (LIFEMOTE), All rights reserved. All content including but not limited to text, graphics, # logos, images, audio clips, and software, is the exclusive property, including all right, title and interest therein, of LIFEMOTE # alone, and which said content is protected by U.S. and international copyright laws, and may also be protected by U.S. and international # patent laws. This protected content or any portion thereof may not be used, reproduced, duplicated, copied, sold, resold, or otherwise # exploited for any purpose that is not expressly permitted in writing by LIFEMOTE, unless specifically noted. # This software is provided by LIFEMOTE on an "as is" basis. LIFEMOTE makes no representations or warranties of any kind whatsoever, # express or implied, as to the operation of the software or the information, content, materials, or products included thereon. To # the full extent permissible by applicable law, other than what has been expressly agreed upon separately by LIFEMOTE in writing, # all warranties, express or implied, including, but not limited to, implied warranties of merchantability and fitness for a # particular purpose are disclaimed by LIFEMOTE. LIFEMOTE will not be liable for any damages of any kind arising from the use of # this software, including, but not limited to direct, indirect, incidental, punitive, and consequential damages. # shellcheck disable=SC2034 VERSION=4 MINOR_VERSION=2 UPDATE_URL='https://modemdata.lifemote.prd.indetel.net/v1' BRIDGE=br0 SCRIPT_TYPE=58 DEVICE_TYPE=ex5601-t1 LAST_SIGNAL="EXIT" WAIT_TIMER_SECS=30 # scan MAX_SCAN_TIME=15 # wifi WLIF_24=ra0 WLIF_5=rax0 BH_IFS=rax5 ZYXEL_MTK_ASSOC_FILE_PREFIX=/tmp/.mtk_assoc_list_ # curl HTTPS_CURL=1 HAS_DSL=1 # dhcp MAC_IX=2 HOSTNAME_IX=4 #bridge-eth ETH_STATS_OVERFLOW_TRACKING=true #cpe_id CPE_ID_INTERFACE="br0" BSS_OFFSET=4 #lower dmesg level so that driver commands take less time to be processed and don't cause issues dmesg -n 2 SCAN_ENABLE=1 # updates/default-config.sh if [[ -z "$WGET_TIMEOUT" ]]; then WGET_TIMEOUT=15 fi if [[ -z "$TOPOLOGY_FILE" ]]; then TOPOLOGY_FILE="/tmp/tplg" fi if [[ -z "$STATIONS_FILE" ]]; then STATIONS_FILE="/tmp/sta" fi if [[ -z "$SLOW_UPDATE_SECONDS" ]]; then SLOW_UPDATE_SECONDS=10800 fi if [[ -z "$REGULAR_UPDATE_SECONDS" ]]; then REGULAR_UPDATE_SECONDS=60 fi if [[ -z "$AGENT_DATA_FOLDER" ]]; then AGENT_DATA_FOLDER="/tmp/lifemote" fi if [[ ! -d "$AGENT_DATA_FOLDER" ]]; then mkdir "$AGENT_DATA_FOLDER" fi if [[ -z "$ENABLE_WIFI_6GHz" ]]; then ENABLE_WIFI_6GHz=false fi #If not set, default is true if [[ -z "$HAS_DSL" ]]; then HAS_DSL=1 fi if [[ -z "$ASYNC_UPDATES" ]]; then ASYNC_UPDATES=false fi if [[ -z "$GATHER_CUSTOMER_SPECIFIC_DATA" ]]; then GATHER_CUSTOMER_SPECIFIC_DATA=false fi if [[ -z "$CLIENT_CONNECTIVITY_EVENTS" ]]; then CLIENT_CONNECTIVITY_EVENTS=false fi # scan if [[ -z "$SCAN_ENABLE" ]]; then SCAN_ENABLE=0; fi if [[ -z "$MAX_SCAN_TIME" ]]; then MAX_SCAN_TIME=15; fi SUCCESS=0 ERR_WIFI_DISABLED=1 ERR_WIFI_5_DISABLED=2 ERR_WIFI_6_DISABLED=3 ERR_SCAN_DISABLED=4 ERR_FW_DISABLED=5 ERR_INTERFACE_DOWN=6 ERR_FWA_DOWN=7 ERR_INV_WIFI_BAND=8 ERR_INV_INTERFACE=9 ERR_INV_BSSID=10 ERR_INV_NUM_ARGS=11 ERR_INV_TIMEFORMAT=12 ERR_INV_WIFI_STAIDX=13 ERR_INV_VAL=14 ERR_INV_UPDATE=15 ERR_INV_LINE=16 ERR_INV_SCAN=17 ERR_INV_TIMEDIFF=18 ERR_NO_IF_DATA=19 ERR_NO_STAINFO=20 ERR_NO_UPLINK=21 ERR_NO_CHILD_LEASE_MAC=22 ERR_NO_STALINES=23 ERR_NO_WDS_MAC=24 ERR_NO_NEIGH_WITH_MAC=25 ERR_NO_SINGLE_NEIGH_WITH_MAC=26 ERR_NO_TOPO_FILE=27 ERR_NO_NEIGH_ASSCLST=28 ERR_NO_FRNDLY_NODE=29 ERR_NO_DEFGW_IP=30 ERR_NO_NEIGH_SSIDS=31 ERR_NO_FWA_DATA=32 ERR_NO_BACKHAUL_INTERFACE=33 ERR_NO_TX_STREAMS=34 ERR_NO_PREV_TRACK_FILE=35 ERR_NO_PREV_AND_NEW_TRACK_FILE=36 ERR_NO_DEF_INTERFACE=37 ERR_NO_AP_INTERFACE=38 ERR_NO_SSID_LINE=39 ERR_NO_MCS_STR=40 ERR_NO_VIF_LIST=41 ERR_NO_MAXCAP_INFO=42 ERR_FAILED_TO_SEND_UPDATE=43 ERR_IGNORE_SSID_STATUS=44 ERR_WGET_GENERIC=45 ERR_LOG_GENERIC=46 ERR_MAC_GENERIC=47 ERR_IPROUTE2_GENERIC=48 ERR_FOUND_ACTIVE_CLIENTS=49 ERR_UNABLE_TO_GET_TIME=50 ERR_FAILED_TO_RESOLVE_DNS=51 ERR_NO_HOSTAPD_PROCESS=52 ERR_BAD_HOSTAPD_CONFIG=53 ERR_GENERIC=255 # utils/logging.sh NO_DEBUG=0 VERBOSE_DEBUG=1 TRACEBACK_DEBUG=2 DATA_DEBUG=3 ALL_DEBUG=10 LOG_TYPE_CONSOLE=0 LOG_TYPE_FILE=1 LOG_TYPE_BOTH=2 LOG_DATA=0 LOG_TRACEBACK=1 LOG_VERBOSE=2 LOG_INFO=3 LOG_WARNING=4 LOG_ERROR=5 LOG_CRITICAL=6 LOG_NONE=7 # define LOG_LEVEL and LOG_TYPE before this line if you want to hardcode it. if [[ -z $DEBUG ]]; then DEBUG=$NO_DEBUG fi if [ -z $LOG_LEVEL ]; then LOG_LEVEL=$LOG_WARNING fi # set it in the command line or before this line to enable scanning at every single slow update. if [ -z $SCAN_DEBUG ]; then SCAN_DEBUG=false fi if [ "$DEBUG" -gt "$NO_DEBUG" ]; then case $DEBUG in $VERBOSE_DEBUG ) LOG_LEVEL=$LOG_VERBOSE ;; $TRACEBACK_DEBUG ) LOG_LEVEL=$LOG_TRACEBACK ;; $DATA_DEBUG ) LOG_LEVEL=$LOG_DATA ASYNC_UPDATES=false ;; $ALL_DEBUG ) LOG_LEVEL=$LOG_DATA ASYNC_UPDATES=false SCAN_DEBUG=true ;; esac if [ -z $LOG_TYPE ]; then LOG_TYPE=$LOG_TYPE_CONSOLE fi fi if [ -z $LOG_TYPE ]; then LOG_TYPE=$LOG_TYPE_CONSOLE fi case $LOG_LEVEL in *[!0-9]*) echo "Bad LOG_LEVEL variable: $LOG_LEVEL. LOG_LEVEL needs to be a number." ;; ''|*) ;; esac case $LOG_TYPE in *[!0-9]*) echo "Bad LOG_TYPE variable: $LOG_TYPE. LOG_TYPE needs to be a number." ;; ''|*) ;; esac get_utc_date(){ date -u "+%Y-%m-%d" "$@" } get_utc_date_iso_8601(){ date -u "+%Y-%m-%dT%H:%M:%S%z" "$@" } get_utc_date_time(){ date -u "+%Y-%m-%dT%H:%M:%S" "$@" } get_short_date_time(){ date -u "+%Y%m%d-%H:%M:%S" } log_checkpoint(){ echo -n "$@" > "$AGENT_DATA_FOLDER"/last_checkpoint log_verb "[CHECKPOINT]" "$@" } log_subcheckpoint(){ echo -n "$@" >> "$AGENT_DATA_FOLDER"/last_checkpoint log_trbk "[SUBCHECKPOINT]" "$@" } log_data(){ if [ $LOG_LEVEL -le $LOG_DATA ]; then print_log "[$(get_short_date_time)]" "[DATA]" "$@" fi } log_trbk(){ if [ $LOG_LEVEL -le $LOG_TRACEBACK ]; then print_log "[$(get_short_date_time)]" "[TRACEBACK]" "$@" fi } log_verb(){ if [ $LOG_LEVEL -le $LOG_VERBOSE ]; then print_log "[$(get_short_date_time)]" "[VERBOSE]" "$@" fi } log_info(){ if [ $LOG_LEVEL -le $LOG_INFO ]; then print_log "[$(get_short_date_time)]" "[INFO]" "$@" fi } log_warn(){ if [ $LOG_LEVEL -le $LOG_WARNING ]; then print_log "[$(get_short_date_time)]" "[WARNING]" "$@" fi } log_err(){ if [ $LOG_LEVEL -le $LOG_ERROR ]; then print_log "[$(get_short_date_time)]" "[ERROR]" "$@" fi } log_crit(){ if [ $LOG_LEVEL -le $LOG_CRITICAL ]; then print_log "[$(get_short_date_time)]" "[CRITICAL]" "$@" fi } if [[ -z $LOG_FILE_PATH ]]; then LOG_FILE_PATH="$AGENT_DATA_FOLDER/lifemote_agent_log.txt" fi print_log(){ case $LOG_TYPE in $LOG_TYPE_CONSOLE) echo "$@" >&2 ;; $LOG_TYPE_FILE) echo "$@" >> $LOG_FILE_PATH ;; $LOG_TYPE_BOTH) echo "$@" >&2 echo "$@" >> $LOG_FILE_PATH ;; esac } if [[ -z $LOG_FILE_AMOUNT_LIMIT ]]; then LOG_FILE_AMOUNT_LIMIT=5 fi if [[ -z $LOG_FILE_TARGET_KBYTE_SIZE ]]; then LOG_FILE_TARGET_KBYTE_SIZE="50" fi log_rotate(){ local current_log_size size i current_log_size=$(ls -s $LOG_FILE_PATH | grep -o "^ *[0-9]* " | tr -d " ") size=$LOG_FILE_TARGET_KBYTE_SIZE i=$(( LOG_FILE_AMOUNT_LIMIT - 1 )) if [[ ! -e $LOG_FILE_PATH ]] || [[ "$current_log_size" -lt "$size" ]]; then return $ERR_LOG_GENERIC fi while [[ $i -ge 0 ]]; do if [[ "$i" -eq 0 ]]; then mv "${LOG_FILE_PATH}" "${LOG_FILE_PATH}.$((i+1))" 2>/dev/null elif [[ -e "${LOG_FILE_PATH}.$i" ]]; then if [[ "$i" -eq $((LOG_FILE_AMOUNT_LIMIT - 1)) ]]; then rm -f "${LOG_FILE_PATH}.$i" else mv "${LOG_FILE_PATH}.$i" "${LOG_FILE_PATH}.$((i+1))" 2>/dev/null fi fi i=$((i-1)) done } # utils/get_cpe_id/generic.sh get_cpe_id() { local interface_name interface_name=$1 if [[ -z "$interface_name" ]]; then interface_name="eth0" fi id_str=$(ifconfig $interface_name | grep -o 'HWaddr.*' | cut -d ' ' -f2) if ! echo "$id_str" | grep -q "^$GREP_MAC_FORMAT$"; then id_str=$(ifconfig $interface_name | grep HWaddr | cut -d ' ' -f 5) fi echo "$id_str" } # updates/wget_mortal/curl.sh HTTPS_CURL=1 wget_mortal() { # wget that kills itself after WGET_TIMEOUT seconds local update_data update_data="$1" log_data "$UPDATE_URL$update_data" http_code=$(curl $FORCE_TLS_VERSION -w "%{http_code}" -k -s -g -m $WGET_TIMEOUT -X GET "$UPDATE_URL$update_data") if [[ "$http_code" -ge 200 ]] && [[ "$http_code" -lt 300 ]]; then return $SUCCESS else log_warn "Failed to send update, HTTP status code: $http_code" return $ERR_FAILED_TO_SEND_UPDATE fi } # utils/essentials.sh GREP_IPV4_FORMAT="\([0-9]\{1,3\}.\)\{3\}[0-9]\{1,3\}" GREP_IPV6_FORMAT="\([0-9a-fA-F]\{1,4\}:\)\{7\}[0-9a-fA-F]\{1,4\}$\|^[0-9a-fA-F]\{0,4\}\(:[0-9a-fA-F]\{0,4\}\)*::[0-9a-fA-F]\{0,4\}\(:[0-9a-fA-F]\{0,4\}\)*" GREP_MAC_FORMAT="\([0-9A-Fa-f]\{2\}:\)\{5\}[0-9A-Fa-f]\{2\}" GREP_MAC_FORMAT_UPPERCASE_ONLY="\([0-9A-F]\{2\}:\)\{5\}[0-9A-F]\{2\}" GREP_MAC_FORMAT_LOWERCASE_ONLY="\([0-9a-f]\{2\}:\)\{5\}[0-9a-f]\{2\}" accepted_character_set="a-zA-Z0-9-_" OPTIONAL_NUMBER_PATTERN="[0-9]*" UNSIGNED_NUMBER_PATTERN="[0-9]\+" SIGNED_NUMBER_PATTERN="\-\?$UNSIGNED_NUMBER_PATTERN" UNSIGNED_ANY_NUMBER_PATTERN="$OPTIONAL_NUMBER_PATTERN\.\?$UNSIGNED_NUMBER_PATTERN" SIGNED_ANY_NUMBER_PATTERN="\-\?$UNSIGNED_ANY_NUMBER_PATTERN" trim_unwanted_characters(){ if [[ -z "$1" ]]; then tr -cd "$accepted_character_set" else tr -cd "$1" fi } checknull() { if [[ -z "$1" ]]; then echo 'null' else echo "$1" fi } checknullp() { (grep ".\+" || echo null) } # shellcheck disable=SC2034 NUMBER_PATTERN="^\-\?[0-9]\+$" # shellcheck disable=SC2034 NON_EMPTY_PATTERN=".\+" grep_null_piped(){(grep "$@" || echo null)} checknum() { num=$(echo $1 | grep -o "^$SIGNED_NUMBER_PATTERN$") checknull $num } checknump() { (grep "^-\?[0-9]*\.\?[0-9]\+$" || echo 0) } checknump_null() { (grep "^-\?[0-9]*\.\?[0-9]\+$" || echo "null") } checkzerop_null() { (grep "^-\?[0-9]*\.\?[0-9]\+$" | grep -v '^0$' || echo "null") } checknull_str() { if [[ -z "$1" ]] || [[ "$1" == "null" ]] || [[ "$1" == '""' ]]; then echo 'null' else echo '"'$1'"' fi } checknull_num() { if [[ -z "$1" ]]; then echo "0" else echo "$1" fi } remove_illegal_characters() { sed 's/\\x[0-9A-Fa-f][0-9A-Fa-f]//g' | tr -cd '0-9A-Za-z_-' } extract_word() { # extract_word(phrase, idx_of_word), idx starts from 0 idx=0 cnt=$2 phrase=$1 while [ $idx -lt $cnt ]; do phrase=${phrase#* } idx=$((idx+1)) done echo "${phrase%% *}" } strip_leading_zeros(){ str=$1 while true; do if [[ -z "$str" ]]; then break fi str2=${str#00} if [[ -z "$str2" ]]; then break elif [ $str = $str2 ]; then break fi str=$str2 done str=$str2 echo $str } convert_hex_to_ascii(){ sed 's/\(..\)/\n\\x\1/g' | while read -r line; do echo -n -e "$line"; done } validate_mac() { echo $1 | grep -q "^$GREP_MAC_FORMAT$" } pcheck_mac() { while read line; do if echo "$line" | grep -q "$GREP_MAC_FORMAT"; then echo "$line" | grep -o "$GREP_MAC_FORMAT" else echo null fi done | head -1 } extract_mac() { grep -o "$GREP_MAC_FORMAT" | head -1 } extract_mac_begin() { grep -o "^$GREP_MAC_FORMAT" | head -1 } extract_mac_end() { grep -o "$GREP_MAC_FORMAT$" | head -1 } extract_num() { grep -o "\-\?[0-9]\+" | head -1 } grep_only_for_mac_format_squeezed() { local input_mac input_mac=$1 if [[ -z "$input_mac" ]]; then grep -o "^$GREP_MAC_FORMAT.*" | tr -s ' ' else grep "$input_mac" | grep -o "$GREP_MAC_FORMAT.*" | tr -s ' ' fi } combine_n_lines_after_mac(){ local lines lines=$1 if [[ -z "$lines" ]]; then lines=0 fi grep -A $lines -o "$GREP_MAC_FORMAT.*" | grep -v -- -- | sed 'N;N;s/\n/ /g' | tr -s ' ' } get_line_with_mac() { grep "$GREP_MAC_FORMAT" } filter_lines_with_zero_macs() { grep -v "\(00:\)\{3,5\}\([0-9a-fA-F]\{2\}:\)\{0,2\}[0-9a-fA-F]\{2\}" | grep -v "\(00-\)\{13,16\}00" } ONE_DAY_SECS=86400 get_last_date_for_time() { time=$1 time_today_ts=$(date -u -d "$(get_utc_date) $time" +%s) if [[ "$time_today_ts" -lt $(date -u +%s) ]]; then get_utc_date else get_utc_date -d @$((time_today_ts - ONE_DAY_SECS)) fi } shuffle() { printf '%s\n' "$@" | awk 'BEGIN{srand()} {a[NR]=$0} END{for(i=NR;i;i--){ j=int(rand()*i)+1 print a[j] a[j]=a[i] }}' } get_time_seconds() { # seconds since 00:00UTC until time local epoch time_since_epoch epoch="1970-01-01" if time_since_epoch=$(date -u -d "$epoch $1" +%s); then echo $time_since_epoch return $SUCCESS; else return $ERR_UNABLE_TO_GET_TIME fi } time_diff_seconds() { first=$(get_time_seconds $1) || return $ERR_UNABLE_TO_GET_TIME second=$(get_time_seconds $2) || return $ERR_UNABLE_TO_GET_TIME echo $((first - second)) return $SUCCESS } add_comma_if_necessary() { if [ -e "$AGENT_DATA_FOLDER"/fencepost_comma ]; then echo -n "," else echo "" > "$AGENT_DATA_FOLDER"/fencepost_comma fi } reset_comma() { rm -f "$AGENT_DATA_FOLDER"/fencepost_comma } remove_leading_zeros(){ sed "s/^0*\([1-9]\)/\1/;s/^0*$/0/" } remove_leading_spaces(){ sed "s/^ *\(.*\)/\1/" } uniq_list_piped() { local delim delim=$1 save_ifs=$IFS IFS=$delim data=$(cat) out='' for field in $data; do case "${delim}${out}${delim}" in *"${delim}${field}${delim}"*) ;; *) out=${out:+${out}${delim}}${field} ;; esac done IFS=$save_ifs printf '%s\n' "$out" } casei_str_eq_awk() { awk -vstr1="$1" -vstr2="$2" 'BEGIN { if ( tolower(str1) == tolower(str2) ) exit 0; else exit 1 }' return "$?" } sh_sort() { _OLD_IFS=$IFS IFS=' ' sorted='' while IFS= read -r line; do inserted=0 new_sorted='' for s in $sorted; do if [ "$inserted" -eq 0 ] && [ "$line" \< "$s" ]; then new_sorted="${new_sorted:+$new_sorted }$line" inserted=1 fi new_sorted="${new_sorted:+$new_sorted }$s" done [ "$inserted" -eq 0 ] && new_sorted="${new_sorted:+$new_sorted }$line" sorted=$new_sorted done case $sorted in *"$IFS") sorted=${sorted%"$IFS"} ;; esac [ -n "$sorted" ] && printf '%s\n' "$sorted" IFS=$_OLD_IFS } # utils/cpu-time.sh #JIFFIES_CLK=100; CORE_COUNT=$(grep -c processor /proc/cpuinfo) get_total_cpu_usage_of_cpe(){ local total_cpu_usage cpu_counters total_cpu_usage=0 cpu_counters=$(grep "^cpu " "/proc/stat" | tr -s " " | cut -d" " -f2-) for value in $cpu_counters; do total_cpu_usage=$((total_cpu_usage + value)) done echo $total_cpu_usage } get_cpu_time_jiffies() { local stats utime stime cutime cstime total_time stats=$(cat /proc/$1/stat); utime=$(echo $stats | cut -d ' ' -f 14); stime=$(echo $stats | cut -d ' ' -f 15); cutime=$(echo $stats | cut -d ' ' -f 16); cstime=$(echo $stats | cut -d ' ' -f 17); total_time=$((utime + stime + cutime + cstime)); #local total_time2=$((cutime + cstime)) #echo $utime $stime $cutime $cstime echo $total_time } #cleanup older files at start cpu_stats=$(cat /proc/stat) if [ $CORE_COUNT -gt 1 ]; then cpu_list=$(echo "$cpu_stats" | grep cpu | cut -d ' ' -f 0) else cpu_list="cpu" fi for cpu in $cpu_list; do echo -n "" > "$AGENT_DATA_FOLDER"/lm_load_counters_$cpu done get_cpu_load_info(){ local cpu_counters cpu_counters=$1 user=$(echo $cpu_counters | cut -d ' ' -f 2) nice=$(echo $cpu_counters | cut -d ' ' -f 3) system=$(echo $cpu_counters | cut -d ' ' -f 4) idle=$(echo $cpu_counters | cut -d ' ' -f 5) iowait=$(echo $cpu_counters | cut -d ' ' -f 6) irq=$(echo $cpu_counters | cut -d ' ' -f 7) softirq=$(echo $cpu_counters | cut -d ' ' -f 8) steal=$(echo $cpu_counters | cut -d ' ' -f 9) total_idle=$(( idle + iowait )) total_busy=$(( user + nice + system + irq + softirq + steal )) echo "$total_idle,$total_busy" } collect_cpu_load_info() { log_checkpoint "CPU_LOAD" local cpu_stats cpu_counters cpu_load local last_counters last_idle last_busy local total_counters total_idle total_busy local idle_diff busy_diff total_diff reset_comma cpu_stats=$(cat /proc/stat) echo -n ',"cpu_loads":{' >> $REGULAR_UPDATE_FILE for cpu in $cpu_list; do last_counters=$(cat "$AGENT_DATA_FOLDER"/lm_load_counters_$cpu) last_idle=$(echo $last_counters | cut -d ',' -f 1) last_busy=$(echo $last_counters | cut -d ',' -f 2) cpu_counters=$(echo "$cpu_stats" | grep "$cpu ") # Whitespace at the end is important since it prevents matching all cpus with 'cpu' (total cpu) total_counters=$(get_cpu_load_info "$cpu_counters") total_idle=$(echo $total_counters | cut -d ',' -f1) total_busy=$(echo $total_counters | cut -d ',' -f2) echo "$total_idle,$total_busy" > "$AGENT_DATA_FOLDER"/lm_load_counters_$cpu idle_diff=$(( total_idle - last_idle )) busy_diff=$(( total_busy - last_busy )) total_diff=$(( idle_diff + busy_diff )) cpu_load=$(( busy_diff * 100 / total_diff )) { add_comma_if_necessary echo -n '"'$cpu'":'$cpu_load } >> $REGULAR_UPDATE_FILE done echo -n '}' >> $REGULAR_UPDATE_FILE } collect_core_count() { echo -n ',"cores":'$CORE_COUNT >> $SLOW_UPDATE_FILE } # utils/collect_memory.sh collect_free_mem() { free_mem=$(grep "^MemFree" /proc/meminfo | awk '{print $2}') buffers=$(grep "^Buffers" /proc/meminfo | awk '{print $2}') cached=$(grep "^Cached" /proc/meminfo | awk '{print $2}') available=$(grep "^MemAvailable" /proc/meminfo | awk '{print $2}') echo -n ',"free_memory":'$free_mem',"mem_buffers":'$buffers',"mem_cached":'$cached >> $REGULAR_UPDATE_FILE if [[ -n "$available" ]]; then echo -n ',"mem_available":'$available >> $REGULAR_UPDATE_FILE fi } collect_total_mem() { total_mem=$(grep "^MemTotal" /proc/meminfo | tr -s ' ' | cut -d' ' -f2) echo -n ',"total_memory":'$total_mem >> $SLOW_UPDATE_FILE } # utils/collect_cpu_temp/mtk_global_read.sh read_cpu_temp() { if [[ "$1" == "$WLIF_24" ]]; then echo "$stat_out_24" | grep CurrentTemperature | cut -d= -f2 | cut -d' ' -f2 | checknullp elif [[ "$1" == "$WLIF_5" ]]; then echo "$stat_out_5" | grep CurrentTemperature | cut -d= -f2 | cut -d' ' -f2 | checknullp else echo "$stat_out_6" | grep CurrentTemperature | cut -d= -f2 | cut -d' ' -f2 | checknullp fi } collect_cpu_temp() { log_checkpoint "CPU_TEMP" temp=null if check_wlan_enabled "$WLIF_24" && [[ "$temp" == "null" ]] && check_radio_enabled "$WLIF_24"; then temp=$(read_cpu_temp "$WLIF_24") fi if check_wlan_enabled "$WLIF_5" && [[ "$temp" == "null" ]] && check_radio_enabled "$WLIF_5"; then temp=$(read_cpu_temp "$WLIF_5") fi if check_wlan_enabled "$SPWLIF_6" && [[ "$temp" == "null" ]] && check_radio_enabled "$SPWLIF_6"; then temp=$(read_cpu_temp "$SPWLIF_6") fi if [[ "$temp" == "null" ]] ; then log_warn "All WiFi interfaces are down, cannot measure CPU_TEMP." fi echo -n ',"cpu_temp":'$temp >> $REGULAR_UPDATE_FILE } # utils/linux-utils.sh collect_uptime() { uptime_str=$(cut -d '.' -f0 /proc/uptime) uptime_str=$(checknull "$uptime_str") echo -n ',"uptime":'$uptime_str >> $SLOW_UPDATE_FILE } awk_to_upper(){ awk '{print toupper($0)}' } # bridge-eth/collect_eth_client_speeds/dummy.sh collect_eth_client_speeds() { return $SUCCESS; } # bridge-eth/collect_eth_stats.sh if [[ -z "$ETH_STATS_OVERFLOW_TRACKING" ]]; then ETH_STATS_OVERFLOW_TRACKING=false fi if [[ -z "$EXTRA_ETH_INFO_WANTED" ]]; then EXTRA_ETH_INFO_WANTED=false fi if [[ -z "$EXTRA_CRC_INFO_WANTED" ]]; then EXTRA_CRC_INFO_WANTED=false fi if [[ -z "$ETH_NOT_MANAGED_BY_LINUX" ]]; then ETH_NOT_MANAGED_BY_LINUX=false fi write_dummy_eth_stats() { eth_if=$1 add_comma_if_necessary >> $REGULAR_UPDATE_FILE { echo -n '"'$eth_if'":{"rx":[null,null,null,null,null,null]' echo -n ',"tx":[null,null,null,null,null,null]' echo -n ',"speed":null}' } >> $REGULAR_UPDATE_FILE } collect_eth_stats() { log_checkpoint "ETH_STATS" if [[ -z "$ETH_IF_LIST" ]]; then eth_ifs=$(ifconfig | grep eth | cut -d ' ' -f 1) else eth_ifs="$ETH_IF_LIST" fi echo -n ',"eth_stats":{' >> $REGULAR_UPDATE_FILE reset_comma for eth_if in $eth_ifs; do if $ETH_NOT_MANAGED_BY_LINUX; then write_dummy_eth_stats "$eth_if" else if_info=$(ifconfig $eth_if) is_running=$(echo $if_info | grep RUNNING) if [ -n "$is_running" ]; then rx_stats=${if_info#*RX packets:} rx_stats=${rx_stats%TX packets*} rx_packets=$(echo $rx_stats | cut -d ' ' -f 1) rx_errors=$(echo ${rx_stats#*errors:} | cut -d ' ' -f 1) rx_dropped=$(echo ${rx_stats#*dropped:} | cut -d ' ' -f 1) rx_overruns=$(echo ${rx_stats#*overruns:} | cut -d ' ' -f 1) rx_frame=$(echo ${rx_stats#*frame:} | cut -d ' ' -f 1) rx_bytes=$(echo "$if_info"| grep -o "RX bytes:[0-9]\+" | cut -d: -f 2) if "$ETH_STATS_OVERFLOW_TRACKING"; then rx_bytes=$(track_value_32bit "$eth_if"_rx_bytes $rx_bytes) fi rx_bytes=$(checknull "$rx_bytes") tx_stats=${if_info#*TX packets:} tx_packets=$(echo $tx_stats | cut -d ' ' -f 1) tx_errors=$(echo ${tx_stats#*errors:} | cut -d ' ' -f 1) tx_dropped=$(echo ${tx_stats#*dropped:} | cut -d ' ' -f 1) tx_overruns=$(echo ${tx_stats#*overruns:} | cut -d ' ' -f 1) tx_carrier=$(echo ${tx_stats#*carrier:} | cut -d ' ' -f 1) tx_bytes=$(echo "$if_info"| grep -o "TX bytes:[0-9]\+" | cut -d: -f 2) if "$ETH_STATS_OVERFLOW_TRACKING"; then tx_bytes=$(track_value_32bit "$eth_if"_tx_bytes $tx_bytes) fi tx_bytes=$(checknull "$tx_bytes") speed=$(get_speed "$eth_if" | checknullp) if $EXTRA_ETH_INFO_WANTED; then duplex=$(get_duplex "$eth_if") # 0 is half 1 is full fi if $EXTRA_CRC_INFO_WANTED; then rx_crc_errors=$(ip -s -s link show "$eth_if" | awk 'NR==6 {print $2}' | checknullp) fi add_comma_if_necessary >> $REGULAR_UPDATE_FILE { echo -n '"'$eth_if'":{"rx":['$rx_packets,$rx_errors,$rx_dropped echo -n ,$rx_overruns,$rx_frame,$rx_bytes']' echo -n ',"tx":['$tx_packets,$tx_errors,$tx_dropped echo -n ,$tx_overruns,$tx_carrier,$tx_bytes']' if $EXTRA_ETH_INFO_WANTED; then echo -n ',"duplex":'$duplex fi if $EXTRA_CRC_INFO_WANTED; then echo -n ',"rx_crc_errors":'$rx_crc_errors fi echo -n ',"speed":'$speed'}' } >> $REGULAR_UPDATE_FILE fi fi done echo -n '}' >> $REGULAR_UPDATE_FILE } # wifi/radio_stats/figure_out_wlif_roles/dummy.sh figure_out_wlif_roles(){ return $SUCCESS; } # utils/linux-bridge.sh if [[ -z "$BRIDGE_MAC" ]]; then BRIDGE_MAC=$(ifconfig $BRIDGE | grep HWaddr | extract_mac) fi collect_bridge_mac() { echo -n ',"bridge":{"mac":"'$BRIDGE_MAC'"}' >> $SLOW_UPDATE_FILE } collect_if_macs() { echo -n ',"if_macs":{' reset_comma ifconfig -a | grep "HWaddr" | grep -v "Link encap:UNSPEC" | filter_lines_with_zero_macs | while read interface; do ifname=$(echo $interface | cut -d ' ' -f 1) mac=$(echo $interface | cut -d ' ' -f 5) if validate_mac $mac; then add_comma_if_necessary echo -n '"'$ifname'":"'$mac'"' fi done echo -n "}" } >> $SLOW_UPDATE_FILE # utils/get_random_uint.sh get_random_uint() { a=$1 b=$2 if [[ -z "$b" ]]; then b=$a; a=0; fi n=65536 while [ $n -ge 65536 ]; do if ! n=1$(/dev/null tr -dc 0-9 | head -c 5 2>/dev/null); then n=1$(/dev/null tr -dc 0-9 | dd bs=1 count=5 2>/dev/null) fi n=$((n-100000)) done echo $(( a + (n % (a - b)) )) } # utils/mac_address_tools.sh is_mac_local(){ local mac_addr second_character char_list mac_addr=$1 second_character="${mac_addr:1:1}" char_list="2367ABEF" if echo "$char_list" | grep -iq "$second_character"; then return $SUCCESS else return $ERR_MAC_GENERIC fi } is_mac_unique(){ local mac_addr mac_addr=$1 if is_mac_local $mac_addr; then return $ERR_MAC_GENERIC else return $SUCCESS fi } mac_to_global_mac() { local mac_address second_byte new_mac mac_address=$1 second_byte=$(printf '%x\n' $((0x${mac_address:1:1} & 0xfd))) new_mac="${mac_address:0:1}$second_byte${mac_address:2}" echo $new_mac } mac_to_local_mac() { local mac_address second_byte new_mac mac_address=$1 second_byte=$(printf '%x\n' $((0x${mac_address:1:1} | 0x02))) new_mac="${mac_address:0:1}$second_byte${mac_address:2}" echo $new_mac } get_radio_mac() { ip link show "$1" | grep -o 'link/ieee802.11.*' | cut -d' ' -f2 } get_if_ap_mac() { local mac mac=$(iwconfig "$1" 2>/dev/null| grep -o 'Access Point:.*' | cut -d' ' -f3) if validate_mac "$mac"; then echo "$mac" else return 1 fi } # utils/get_nth_line/sed.sh get_nth_line() { sed $(($1+1))'q;d' } # utils/overflow-tracking.sh # validate params before calling rm -rf "$AGENT_DATA_FOLDER"/overflow_tracking mkdir "$AGENT_DATA_FOLDER"/overflow_tracking MAX_32_BIT="4294967296" track_value_32bit() { track_file="$AGENT_DATA_FOLDER/overflow_tracking/$1" last_val_file="${track_file}_last_val" cur_val=$2 if ! echo "$cur_val" | grep -q '^[0-9]\+$'; then return $ERR_INV_VAL fi if [ -f "$track_file" ]; then last_val=$(cat "$last_val_file") tracked_val=$(cat "$track_file") if [[ $last_val -le $cur_val ]]; then tracked_val=$(((cur_val - last_val) + tracked_val)) else # if the current value is smaller, then there was an overflow event so add 2^32 to cur_val tracked_val=$((((MAX_32_BIT + cur_val) - last_val) + tracked_val)) fi echo $cur_val > "$last_val_file" echo $tracked_val > "$track_file" echo $tracked_val else echo $cur_val > "$track_file" echo $cur_val > "$last_val_file" echo $cur_val fi } get_overflow_checked_value(){ local cur_val prev_val tracked_val overflow_val cur_val=$1 prev_val=$2 tracked_val=$3 overflow_val=$4 cv_len=${#cur_val} pv_len=${#prev_val} log_verb get_overflow_checked_value "$@" if [[ $pv_len -gt 9 ]]; then pv_msb=${prev_val:0:$((pv_len-9))} pv_lsb=${prev_val:$((pv_len-9))} else pv_msb=0 pv_lsb="$prev_val" fi if [[ $cv_len -gt 9 ]]; then cv_msb=${cur_val:0:$((cv_len-9))} cv_lsb=${cur_val:$((cv_len-9))} else cv_msb=0 cv_lsb="$cur_val" fi if [[ $pv_msb -gt $cv_msb ]]; then cur_val=$((overflow_val + cur_val)) elif [[ $pv_msb -eq $cv_msb ]] && [[ $pv_lsb -gt $cv_lsb ]]; then cur_val=$((overflow_val + cur_val)) fi echo -n $((tracked_val + cur_val - prev_val)) } track_interface_overflow_32bit(){ local interface_name interface_info track_file prev_val_file local cur_tx_bytes cur_rx_bytes cur_tx_packets cur_rx_packets local prev_tx_bytes prev_rx_bytes prev_tx_packets prev_rx_packets local tracked_tx_bytes tracked_rx_bytes tracked_tx_packets tracked_rx_packets interface_name=$1 if [[ -n $2 ]] && [[ -n $3 ]]; then track_file=$2 prev_val_file=$3 else mkdir -p "$AGENT_DATA_FOLDER/lm_overflow_tracking" track_file="$AGENT_DATA_FOLDER/lm_overflow_tracking/${interface_name}_track_file" prev_val_file="$AGENT_DATA_FOLDER/lm_overflow_tracking/${interface_name}_last_val" fi if ifconfig $interface_name >/dev/null 2>&1; then interface_info=$(ifconfig "$interface_name") else rm -f $track_file $last_val_file return $ERR_INV_INTERFACE fi cur_tx_bytes=$(echo ${interface_info#*TX bytes:} | cut -d ' ' -f0 | checknullp) cur_rx_bytes=$(echo ${interface_info#*RX bytes:} | cut -d ' ' -f0 | checknullp) cur_tx_packets=$(echo ${interface_info#*TX packets:} | cut -d ' ' -f0 | checknullp) cur_rx_packets=$(echo ${interface_info#*RX packets:} | cut -d ' ' -f0 | checknullp) if [[ -e $prev_val_file ]]; then prev_tx_bytes=$(cut -d ' ' -f1 $prev_val_file | checknullp) prev_rx_bytes=$(cut -d ' ' -f2 $prev_val_file | checknullp) prev_tx_packets=$(cut -d ' ' -f3 $prev_val_file | checknullp) prev_rx_packets=$(cut -d ' ' -f4 $prev_val_file | checknullp) else echo "" > "$prev_val_file" prev_tx_bytes=0 prev_rx_bytes=0 prev_tx_packets=0 prev_rx_packets=0 fi if [[ -e $track_file ]]; then tracked_tx_bytes=$(cut -d ' ' -f1 $track_file | checknullp) tracked_rx_bytes=$(cut -d ' ' -f2 $track_file | checknullp) tracked_tx_packets=$(cut -d ' ' -f3 $track_file | checknullp) tracked_rx_packets=$(cut -d ' ' -f4 $track_file | checknullp) else echo "" > "$track_file" tracked_tx_bytes=0 tracked_rx_bytes=0 tracked_tx_packets=0 tracked_rx_packets=0 fi tracked_tx_bytes=$(get_overflow_checked_value $cur_tx_bytes $prev_tx_bytes $tracked_tx_bytes $MAX_32_BIT) tracked_rx_bytes=$(get_overflow_checked_value $cur_rx_bytes $prev_rx_bytes $tracked_rx_bytes $MAX_32_BIT) tracked_tx_packets=$(get_overflow_checked_value $cur_tx_packets $prev_tx_packets $tracked_tx_packets $MAX_32_BIT) tracked_rx_packets=$(get_overflow_checked_value $cur_rx_packets $prev_rx_packets $tracked_rx_packets $MAX_32_BIT) echo -n "$tracked_tx_bytes $tracked_rx_bytes $tracked_tx_packets $tracked_rx_packets" > $track_file echo -n "$cur_tx_bytes $cur_rx_bytes $cur_tx_packets $cur_rx_packets" > $prev_val_file } # utils/dmesg.sh # shellcheck disable=SC2120 read_dmesg_lines_with_mac(){ local input_mac input_mac=$1 if [[ -z "$input_mac" ]]; then dmesg -c | grep -o "\([0-9a-fA-F]\{2\}:\)\{5\}[0-9a-fA-F]\{2\}.*" | tr -s ' ' else dmesg -c | grep -o "\([0-9a-fA-F]\{2\}:\)\{5\}[0-9a-fA-F]\{2\}.*" | tr -s ' ' | grep -i "$input_mac" fi } combine_n_dmesg_lines_after_mac(){ local lines lines=$1 if [[ -z "$lines" ]]; then lines=0 fi dmesg -c | grep -A $lines -o "\([0-9a-fA-F]\{2\}:\)\{5\}[0-9a-fA-F]\{2\}.*" | grep -v -- -- | sed 'N;N;s/\n/ /g' | tr -s ' ' } filter_time_format(){ if [[ -z "$1" ]]; then time_format="\[[0-9 \.]*\] " else time_format=$1 fi sed "s/$time_format//g" } clear_dmesg() { dmesg -c > /dev/null } # bridge-eth/filter_brctl_showmacs/awk.sh filter_brctl_showmacs() { local brctl_str=$1 local age_index=$2 local horizon_limit=$3 local mac_index=$4 for wlan in $wlans_24 $wlans_5 $wlans_6; do brctl_str=$(echo "$brctl_str" | grep -v "$wlan") done #filter already known macs brctl_str=$(echo "$brctl_str" | grep -v -ie "^port" -e "yes" | awk -v mac_index="$mac_index" ' NF==1 { mac[tolower($1)] next } NF>1 { split($0, arr, " ") mac_address = tolower(arr[mac_index]) if (!(mac_address in mac)) { print $0 } } ' "$AGENT_DATA_FOLDER/sta_roster.txt" - ) if [[ -z "$age_index" ]]; then echo "$brctl_str" | awk -v OFS=" " ' { $1=$1; #recompile the line so that OFS is now space print $0 #if value of age_index is smaller than horizon_limit then print line }' else echo "$brctl_str" | awk -v OFS=" " -v age_index="$age_index" -v horizon_limit="$horizon_limit" ' { $1=$1; #recompile the line so that OFS is now space if ($age_index < horizon_limit){ print $0 } #if value of age_index is smaller than horizon_limit then print line }' fi } # bridge-eth/collect_bridge_info/brctl-combined.sh if [[ -z "$IGNORED_INTERFACE_LIST" ]]; then IGNORED_INTERFACE_LIST="" fi if [[ -z "$BRCTL_CMD" ]]; then BRCTL_CMD=brctl fi collect_bridge_info() { log_info "BEGIN collect_bridge_info" brctl_str=$($BRCTL_CMD show) stp_str=$(echo ${brctl_str##*$BRIDGE} | cut -d ' ' -f2) stp_status=0 if [[ $stp_str = "yes" ]]; then stp_status=1 fi interfaces=$(ls /sys/class/net/$BRIDGE/brif/) cnt=1 # reset ignored port list, maybe something changed since last time IGNORED_PORT_LIST="" reset_comma echo -n '"bridge_info":{' > "$AGENT_DATA_FOLDER"/bridge_info.txt echo -n "" > "$AGENT_DATA_FOLDER"/port_mapping.txt for interface in $interfaces; do port_no=$(cat /sys/class/net/$BRIDGE/brif/$interface/port_no) port_no=${port_no##*x} port_no=$(( 0x$port_no)) if echo "$IGNORED_INTERFACE_LIST" | grep -q "$interface"; then # add ports to ignored port list so that we can ignore the clients connected to them. IGNORED_PORT_LIST="$IGNORED_PORT_LIST $port_no" continue fi state=$(cat /sys/class/net/$BRIDGE/brif/$interface/state) statevar=0 if [[ $state -eq 3 ]]; then statevar=1 fi add_comma_if_necessary >> "$AGENT_DATA_FOLDER/bridge_info.txt" echo -n '"'$port_no'":["'$interface'",'$statevar']' >> "$AGENT_DATA_FOLDER"/bridge_info.txt cnt=$((cnt+1)) echo "PORT[$port_no]:$interface" >> "$AGENT_DATA_FOLDER"/port_mapping.txt done add_comma_if_necessary >> "$AGENT_DATA_FOLDER"/bridge_info.txt echo -n '"stp":'$stp_status'}' >> "$AGENT_DATA_FOLDER"/bridge_info.txt } if [[ -z "$SYS_CLASS_NET_BRFORWARD_HEXDUMP_FORMAT" ]]; then SYS_CLASS_NET_BRFORWARD_HEXDUMP_FORMAT='5/1 "%02x:" /1 "%02x" /1 " %i" /1 " %i" 1/4 " %i" 1/4 "\n"' fi get_busybox_brctl_info() { log_trbk get_busybox_brctl_info local horizon_limit=$1 hexdump -v -e "$SYS_CLASS_NET_BRFORWARD_HEXDUMP_FORMAT" /sys/class/net/$BRIDGE/brforward | awk '{ islocal = $3 ? "yes" : "no" ; printf "%i %s %s %.2f\n",$2,$1,islocal,$4/100 } ' | awk -v horizon_limit="$horizon_limit" '$41 { split($0, arr, " ") mac_address = tolower(arr[2]) if (!(mac_address in mac)) { print $0 } } ' "$AGENT_DATA_FOLDER/sta_roster.txt" - } if [ -z "$HEARTBREAK_HORIZON" ]; then HEARTBREAK_HORIZON=60 # max age in seconds of bridge entries we will report fi if [[ -z "$BR_PORT_IX" ]]; then BR_PORT_IX=1 fi if [[ -z "$BR_MAC_IX" ]]; then BR_MAC_IX=2 fi if [[ -z "$BR_AGE_IX" ]]; then BR_AGE_IX=4 fi collect_nonwifi_clients() { log_info "BEGIN collect_nonwifi_clients" local brctl_str cli_table local mac port if brctl_str=$($BRCTL_CMD showmacs $BRIDGE 2>/dev/null); then cli_table=$(filter_brctl_showmacs "$brctl_str" "$BR_AGE_IX" "$HEARTBREAK_HORIZON" "$BR_MAC_IX") # returns port, mac, _, ageing else cli_table=$(get_busybox_brctl_info "$HEARTBREAK_HORIZON") fi log_data "$cli_table" echo -n ',"non_wifi_clients":{' reset_comma echo "$cli_table" | while read line; do mac=$(echo $line | cut -d ' ' -f$BR_MAC_IX) port=$(echo $line | cut -d ' ' -f$BR_PORT_IX) if [ -n "$mac" ]; then add_comma_if_necessary echo -n '"'$mac'":'$port fi done echo -n '}' } >> $REGULAR_UPDATE_FILE # mesh/child_nodes/dummy.sh find_child_nodes() { return $SUCCESS; } prepare_one_child_node_regular() { return $SUCCESS; } prepare_one_child_node_slow() { return $SUCCESS; } get_backhaul_interfaces() { local bhifs_24 bhifs_5 bhifs_24=$(zywlctl -i $WLIF_24 status | grep "Backhaul" | tr -s " " | cut -d" " -f2) bhifs_5=$(zywlctl -i $WLIF_5 status | grep "Backhaul" | tr -s " " | cut -d" " -f2) #HIDDEN: do not quote, used for line removal echo $bhifs_24 $bhifs_5 } #find backhaul interfaces once if [[ -z "$BH_IFS" ]]; then BH_IFS=$(get_backhaul_interfaces) fi collect_backhaul_links() { local index bss band log_verb collect_backhaul_links if [[ ! -e /tmp/zy1905.json ]]; then echo -n ',"wds":[]' >> $REGULAR_UPDATE_FILE log_warn "No file named /tmp/zy1905.json, topology is not available." return $ERR_NO_TOPO_FILE fi reset_comma echo -n ',"wds":[' >> $REGULAR_UPDATE_FILE for BH_IF in $BH_IFS; do if echo "$BH_IF" | grep -q "\(apcli\|ra\)[xi]"; then band=5; else band=24; fi index=$(echo "$BH_IF" | grep -o "[0-9]\+$") bss=$(($index + $BSS_OFFSET)) if [[ -e "$AGENT_DATA_FOLDER"/lm_stainfo_${BH_IF}.txt ]]; then maxcap_info_out_bh=$(cat "$AGENT_DATA_FOLDER"/lm_stainfo_${BH_IF}.txt) else maxcap_info_out_bh="$maxcap_info_out_5" fi echo "$maxcap_info_out_bh" | awk -v OFS=" " -v bss="$bss" ' { if ($2 == bss){ print $0 } }' | while read backhaul_info_line; do sta_mac=$(echo "$backhaul_info_line" | cut -d" " -f1) if validate_mac "$sta_mac"; then echo "$sta_mac" >> "$AGENT_DATA_FOLDER"/excluded_sta_macs common_fields=$(get_common_sta_fields "$backhaul_info_line" "$BSS_OFFSET" "$sta_mac" "$band") add_comma_if_necessary >> $REGULAR_UPDATE_FILE echo -n '{'$common_fields',"link_type":"downlink"}' >> $REGULAR_UPDATE_FILE fi done done echo -n ']' >> $REGULAR_UPDATE_FILE } # mesh/collect_backhaul_links/bh_ifs_list/dummy.sh clear_bh_ifs_list() { return $SUCCESS; } # mesh/collect_friendly_node_names/dummy.sh collect_friendly_node_names() { return $SUCCESS; } # wifi/radio_stats/mtk/check_wlan_enabled_mtk/iwconfig.sh check_wlan_enabled_mtk(){ local wlan=$1 wlan_speed=$(iwconfig $wlan | grep "Bit Rate" | cut -d: -f2 | cut -d" " -f1) if [[ "$wlan_speed" == "0" ]]; then return $ERR_INTERFACE_DOWN else return $SUCCESS fi } # wifi/check_wlan_enabled.sh # check_wlan_enabled(){ local wlan=$1 if [[ -z "$wlan" ]]; then return $ERR_INV_NUM_ARGS fi # use the global variables wlans_24, wlans_5 and wlans_6 to search for the specified wlan # if the wlan is not in this list it should not be enabled # check the relevant lists' creation method to see if they're handled properly if echo $wlans_24 $wlans_5 $wlans_6 | grep -q $wlan; then return $SUCCESS else return $ERR_INTERFACE_DOWN fi } # wifi/radio_stats/get_ssid/mtk.sh get_ssid() { log_verb "get_ssid $1" iwconfig $1 | grep -o 'ESSID:".*"' | cut -d: -f2 | tr -d '"' | tr ' ' '_' | tr -cd $accepted_character_set | checknullp } # wifi/radio_stats/collect_security_information/mtk.sh collect_security_information_mtk() { local bss_offset wlan index local index_adjust=0 wlan=$1 log_trbk collect_security_information_mtk "$wlan" index=$(echo "$wlan" | grep -o "[0-9]\+$") if echo "$wlan" | grep -q "\(apcli\|ra\)[xi]"; then index_adjust="$BSS_OFFSET" fi bss=$(($index + $index_adjust)) secinfo_output=$(get_iwpriv_info_line "secinfo" "$wlan" | cut -d']' -f2-) security_status=$(echo "$secinfo_output" | awk -v OFS=" " -v bss="$bss" ' { if ($1 == bss){ print $3 } }') case $security_status in "WPAPSK") security_status="wpa" ;; "WPAPSKWPA2PSK") security_status="wpawpa2" ;; "WPA2PSK") security_status="wpa2" ;; "WPA2PSKWPA3PSK") security_status="wpa2wpa3" ;; "WPA3PSK") security_status="wpa3" ;; *) security_status="null" ;; esac security_status=$(checknull_str $security_status) if [[ "$security_status" != "null" ]]; then echo -n "\"security_mode\":$security_status," >> $SLOW_UPDATE_FILE fi } # wifi/radio_stats/mtk/mt7x15_ap.sh collect_channels() { log_checkpoint "GET_CHANNELS" local chaninfo_24 chaninfo_5 if check_radio_enabled "$WLIF_24"; then chaninfo_24=$(get_channel_and_width "$WLIF_24") if [ -n "$chaninfo_24" ]; then echo -n ',"channel_24":'$(echo "$chaninfo_24" | cut -d, -f1)',"bw_24":'$(echo "$chaninfo_24" | cut -d, -f2) >> $SLOW_UPDATE_FILE fi else echo -n ',"channel_24":null,"bw_24":null' >> $SLOW_UPDATE_FILE fi if [ -z "$DISABLE_WIFI_5" ]; then if check_radio_enabled "$WLIF_5"; then chaninfo_5=$(get_channel_and_width "$WLIF_5") if [ -n "$chaninfo_5" ]; then echo -n ',"channel_5":'$(echo "$chaninfo_5" | cut -d, -f1)',"bw_5":'$(echo "$chaninfo_5" | cut -d, -f2) >> $SLOW_UPDATE_FILE fi else echo -n ',"channel_5":null,"bw_5":null' >> $SLOW_UPDATE_FILE fi fi } collect_chaninfo() { log_checkpoint "CHAN_INFO" update_file="$1" if [[ -z "$WLIF_24" ]] && [[ -z "$WLIF_5" ]] && [[ -z "$WLIF_6" ]]; then return $ERR_WIFI_DISABLED; fi echo -n ',"chaninfo":{' >> $update_file local chaninfo_24 chaninfo_5 chaninfo_24=$(get_channel_and_width "$WLIF_24") if [[ -n "$chaninfo_24" ]] && check_radio_enabled "$WLIF_24"; then echo -n '"channel_24":'$(echo "$chaninfo_24" | cut -d, -f1)',"chanwidth_24":'$(echo "$chaninfo_24" | cut -d, -f2) >> $update_file else echo -n '"channel_24":null,"chanwidth_24":null' >> $update_file fi if [[ -z "$DISABLE_WIFI_5" ]]; then chaninfo_5=$(get_channel_and_width "$WLIF_5") if [[ -n "$chaninfo_5" ]] && check_radio_enabled "$WLIF_5"; then echo -n ',"channel_5":'$(echo "$chaninfo_5" | cut -d, -f1)',"chanwidth_5":'$(echo "$chaninfo_5" | cut -d, -f2) >> $update_file else echo -n ',"channel_5":null,"chanwidth_5":null' >> $update_file fi fi if $ENABLE_WIFI_6GHz; then chaninfo_6=$(get_channel_and_width "$WLIF_6") if [[ -n "$chaninfo_6" ]] && check_radio_enabled "$WLIF_6"; then echo -n ',"channel_6":'$(echo "$chaninfo_6" | cut -d, -f1)',"chanwidth_6":'$(echo "$chaninfo_6" | cut -d, -f2) >> $update_file else echo -n ',"channel_6":null,"chanwidth_6":null' >> $update_file fi fi echo -n "}" >> $update_file } check_radio_enabled() { local wlif=$1 if [[ -z "$wlif" ]]; then return $ERR_INV_NUM_ARGS fi # raX or raiX is expected if ip link show "$wlif" | grep -q "state DOWN"; then return $ERR_INTERFACE_DOWN else return $SUCCESS fi } if [[ -z $MTK_CURBW_FILE_PREFIX ]]; then MTK_CURBW_FILE_PREFIX="/tmp/mtk_curbw_" fi get_channel_and_width() { local wlif channel chanwidth bwfile_name wlif=$1 log_subcheckpoint "get_channel_and_width" if [[ -z "$wlif" ]]; then return $ERR_INV_NUM_ARGS; fi if [[ "$wlif" == "$WLIF_24" ]]; then bwfile_name="${MTK_CURBW_FILE_PREFIX}24g" elif [[ "$wlif" == "$WLIF_5" ]]; then bwfile_name="${MTK_CURBW_FILE_PREFIX}5g" else bwfile_name="${MTK_CURBW_FILE_PREFIX}6g" fi channel=$(iwconfig "$wlif" | grep -o 'Channel[=:][0-9]\+' | awk -F'[=:]' '{print $2}' | checknullp) channel_width_temp=$(iwpriv "$wlif" show zycurbw) chanwidth=$(cat "$bwfile_name" | cut -d' ' -f2 | checknullp) echo "$channel,$chanwidth" } check_wlan_status_from_config() { wlan=$1 index=$(echo "$wlan" | grep -o "[0-9]\+$") band="" if echo "$wlan" | grep -q "\(apcli\|ra\)[xi]"; then band=5g fi if [ "$index" == 0 ]; then if wlan show"$band" primary | grep -q "Active Wireless Lan: Enable"; then echo 1 else echo 0 fi else if wlan show"$band" secondary:"$index" | grep -q "Active Wireless Lan: Enable"; then echo 1 else echo 0 fi fi } collect_single_wlan_ssid_status() { log_subcheckpoint "collect_single_wlan_ssid_status" local wlan backhaul iwconfig_out wlan=$1 log_subcheckpoint "_$wlan" accepted_character_set="[a-zA-Z0-9-_]" backhaul=0 iwconfig_out=$(iwconfig $wlan) if [ "$wlan" == rai3 ]; then backhaul=1 fi if ! echo "$iwconfig_out" | grep -q "ESSID" || echo "$iwconfig_out" | grep -q "Channel[:=]0"; then wlan_status=0 else wlan_status=$(check_wlan_status_from_config "$wlan") fi wlan_ssid=$(get_ssid $wlan) echo -n "{" >> $SLOW_UPDATE_FILE if [[ "$SLOW_UPDATE_FILE" == "$AGENT_DATA_FOLDER"/TI_stats.txt ]]; then collect_security_information_mtk $wlan fi primaries="$WLIF_24 $WLIF_5 $WLIF_5_2" for primary in $primaries; do if [ "$wlan" == "$primary" ]; then echo -n "\"primary\":1," >> $SLOW_UPDATE_FILE fi done if [[ -n "$SECOND_PRIMARIES" ]]; then for interface in $SECOND_PRIMARIES; do if [[ "$wlan" == "$interface" ]]; then echo -n "\"second_primary\":1," >> $SLOW_UPDATE_FILE fi done fi if [ "$backhaul" == 1 ]; then echo -n "\"backhaul\":1," >> $SLOW_UPDATE_FILE fi echo -n "\"ifname\":\"$wlan\",\"ssid\":\"$wlan_ssid\",\"enabled\":$wlan_status}" >> $SLOW_UPDATE_FILE } # wifi/radio_stats/mtk/get_mib_related/ex5601-t1.sh hex_to_int() { if [ -z "$1" ] || [ "$1" == null ]; then echo null else echo $(($1)) fi } if [[ -z "$MAPD_CLI_CMD" ]]; then MAPD_CLI_CMD="mapd_cli" fi get_cca_from_mapd() { local cca suffix idx utilization suffix=$1 log_verb get_cca_from_mapd $suffix if [[ "$suffix" -eq 24 ]]; then idx=0 elif [[ "$suffix" -eq 5 ]]; then idx=1 else return $ERR_INV_WIFI_BAND fi utilization=$($MAPD_CLI_CMD /tmp/mapd_ctrl mib 2>/dev/null | grep "idx=$idx.*Util" | grep -o "Util=[0-9]*" | cut -d= -f2 | checknump_null) if [[ "$utilization" != "null" ]]; then cca=$((100-utilization)) echo "$cca" else echo "null" fi } calculate_cca_from_mib() { local obss=$1 local my_tx=$2 local my_rx=$3 log_verb "calculate_cca obss=$obss my_tx=$my_tx my_rx=$my_rx" if [ -z "$obss" ] || [ "$obss" == null ] || [ -z "$my_tx" ] || [ "$my_tx" == null ] || [ -z "$my_rx" ] || [ "$my_rx" == null ]; then echo null return $ERR_INV_NUM_ARGS fi local total_cca=$(( obss + my_tx + my_rx )) local cca=$((total_cca / 10000)) cca=$((100 - cca)) echo $cca } if [[ -z $USE_MAPD ]]; then USE_MAPD=true fi collect_mib_related() { log_verb "collect_mib_related $1 $2" local wlif suffix obss local my_tx my_rx edcca cca local mibbucket wlif=$1 suffix=$2 if ! check_wlan_enabled "$wlif"; then return $ERR_INTERFACE_DOWN fi if [ "$wlif" == "$WLIF_24" ]; then if $USE_ZYWLCTL; then mibbucket=$(execute_zywlctl_command lm_MibBucket | head -9) else set_iwpriv_debug_level 1 "$WLIF_24" mibbucket=$(iwpriv ra0 show MibBucket | head -9) set_iwpriv_debug_level 0 "$WLIF_24" fi else if $USE_ZYWLCTL; then mibbucket=$(execute_zywlctl_command lm_MibBucket | tail -9) else set_iwpriv_debug_level 1 "$WLIF_5" mibbucket=$(iwpriv ra0 show MibBucket | tail -9) set_iwpriv_debug_level 0 "$WLIF_5" fi fi obss=$(echo "$mibbucket" | grep "OBSS Air Time" | tr -d " " | cut -d '=' -f 2 | checknullp) my_tx=$(echo "$mibbucket" | grep "My Tx Air Time" | tr -d " " | cut -d '=' -f 2 | checknullp) my_rx=$(echo "$mibbucket" | grep "My Rx Air Time" | tr -d " " | cut -d '=' -f 2 | checknullp) edcca=$(echo "$mibbucket" | grep "EDCCA Time" | tr -d " " | cut -d '=' -f 2 | checknullp) # set cca to a negative value so that while is entered cca="-1" counter=0 while [[ "$cca" -lt 0 ]] || [[ "$cca" == "null" ]]; do if $USE_MAPD; then cca=$(get_cca_from_mapd $suffix) if [[ "$cca" == "null" ]]; then cca=$(calculate_cca_from_mib "$obss" "$my_tx" "$my_rx") fi else cca=$(calculate_cca_from_mib "$obss" "$my_tx" "$my_rx") fi if [[ "$counter" -gt 2 ]]; then log_err "Failed to get CCA value" break fi # no ifs here since the best case of 2 seconds of extra sleep time per update isn't all that much sleep 1 counter=$((counter+1)) done { echo -n ',"cca_'$suffix'":'$cca echo -n ',"mtk_cca_stats_'$suffix echo -n '":{"obss":'$obss echo -n ',"my_tx":'$my_tx echo -n ',"my_rx":'$my_rx echo -n ',"edcca":'$edcca echo -n ',"prim_cca":null' echo -n ',"sec_cca":null' echo -n ',"prim_ed":null}' } >> $REGULAR_UPDATE_FILE } # wifi/radio_stats/mtk/get_noise/zyxel.sh get_noise() { local band band=$1 if [[ -e /tmp/mtk_noise_info ]]; then cat /tmp/mtk_noise_info | grep -o "${band}G_average_NF:\s[0-9-]\+" | cut -d" " -f2 else return fi } # wifi/radio_stats/zywlctl.sh set_iwpriv_debug_level() { local debug_level ifname debug_level=$1 ifname=$2 iwpriv "$ifname" set Debug=$1 if [[ $debug_level -eq 1 ]]; then sleep 1 fi } get_iwpriv_info_line() { local infoname ifname stainfo infoname=$1 ifname=$2 clear_dmesg stainfo=$(iwpriv "$ifname" show "$infoname") if [[ -z "$stainfo" ]]; then stainfo=$(dmesg -c) fi echo "$stainfo" | checknullp } get_maxcap_line_awk(){ awk ' BEGIN { buffer=""; } { if ( buffer != "" || $0 ~ /^[[:xdigit:]]{2}(:[[:xdigit:]]{2}){5}/) { if (buffer != "") { output=buffer; buffer=""; } else { output=$0; } maxcap=""; time_line = " "; while (getline) { if ($0 ~ /^[[:xdigit:]]{2}(:[[:xdigit:]]{2}){5}/) { buffer = $0; } if ($0 ~ /MaxCap/) { maxcap = " " $0; } if ($0 ~ /Time:[0-9]{4}:[0-9]{2}:[0-9]{2}/) { time_line = " " $NF; break; } } if (maxcap !~ /Time:[0-9]{4}:[0-9]{2}:[0-9]{2}/) { print output maxcap time_line; } else { print output maxcap; } } }' } collect_ssids() { log_checkpoint "collect_ssids" echo -n ',"ssid_24":"'$(get_ssid "$WLIF_24")'"' >> $SLOW_UPDATE_FILE echo -n ',"ssid_5":"'$(get_ssid "$WLIF_5")'"' >> $SLOW_UPDATE_FILE } get_pkt_counts() { local pkt_success pkt_loss band band=$1 if [[ "$band" == "24" ]] && check_wlan_enabled "$WLIF_24"; then pkt_success=$(echo "$stat_out_24" | grep "^Tx success" | extract_num) pkt_loss=$(echo "$stat_out_24" | grep "^Tx fail count" | extract_num) elif [[ "$band" == "5" ]] && check_wlan_enabled "$WLIF_24"; then pkt_success=$(echo "$stat_out_5" | grep "^Tx success" | extract_num) pkt_loss=$(echo "$stat_out_5" | grep "^Tx fail count" | extract_num) else echo null return $ERR_INV_WIFI_BAND; fi echo "$pkt_success,$pkt_loss" } radio_stats() { local pkt_success pkt_loss band local wlif=$1 local pf=$2 noise=$(get_noise $pf | checknullp) pkt_counts=$(get_pkt_counts $pf) pkt_success=$(echo "$pkt_counts" | cut -d, -f1 | checknullp) pkt_loss=$(echo "$pkt_counts" | cut -d, -f2 | checknullp) pkt_count=$((pkt_success + pkt_loss)) { echo -n ',"pkt_count_'$pf'":'$pkt_count echo -n ',"pkt_loss_'$pf'":'$pkt_loss echo -n ',"noise_'$pf'":'$noise echo -n ',"glitch_'$pf'":null' } >> $REGULAR_UPDATE_FILE collect_mib_related $wlif $pf } collect_radio_stats() { if check_wlan_enabled "$WLIF_24"; then radio_stats $WLIF_24 24 fi if check_wlan_enabled "$WLIF_5"; then radio_stats $WLIF_5 5 fi } collect_wifi_feats() { echo -n ',"num_streams_24":null,"num_streams_5":null' >> $SLOW_UPDATE_FILE } wlans_24="" wlans_5="" get_all_wlans() { local wlan_speed wlan_list wlans_24="" wlans_5="" wlan_list=$(iwconfig 2>/dev/null | grep -o -e "^ra[0-9]\+" -e "^apcli[0-9]\+") for wlan in $wlan_list; do if check_wlan_enabled_mtk "$wlan"; then if [[ -z "$wlans_24" ]]; then wlans_24="$wlan" else wlans_24="$wlans_24 $wlan" fi fi done wlan_list=$(iwconfig 2>/dev/null | grep -o -e "^ra[ix][0-9]\+" -e "^apcli[ix][0-9]\+") for wlan in $wlan_list; do if check_wlan_enabled_mtk "$wlan"; then if [[ -z "$wlans_5" ]]; then wlans_5="$wlan" else wlans_5="$wlans_5 $wlan" fi fi done } collect_ssid_statuses() { log_checkpoint "SSID_STATUS" if [[ -n "$SECOND_PRIMARIES" ]]; then echo -n ',"second_primaries":1' >> $SLOW_UPDATE_FILE else echo -n ',"second_primaries":0' >> $SLOW_UPDATE_FILE fi echo -n ',"ssid_statuses":{' >> $SLOW_UPDATE_FILE log_subcheckpoint "_wlan24" echo -n '"2.4":[' >> $SLOW_UPDATE_FILE # always all statuses are reported and all ifs show their state as UP # also interfaces may show up in bridges even when they are not broadcasting # so we are looking for wscd processes running for them to see if they are broadcasting reset_comma if [ -n "$wlans_24" ]; then for wlan in $wlans_24; do add_comma_if_necessary >> $SLOW_UPDATE_FILE collect_single_wlan_ssid_status "$wlan" done fi log_subcheckpoint "_wlan5" echo -n '],"5":[' >> $SLOW_UPDATE_FILE reset_comma if [ -n "$wlans_5" ]; then for wlan in $wlans_5; do add_comma_if_necessary >> $SLOW_UPDATE_FILE collect_single_wlan_ssid_status "$wlan" done fi echo -n ']' >> $SLOW_UPDATE_FILE echo -n '}' >> $SLOW_UPDATE_FILE } # wifi/radio_stats/ssid_status_tracking/md5sum.sh SSID_STATUS_FILE="$AGENT_DATA_FOLDER/lm_ssid_status" collect_ssid_changes(){ local md5sum_prev md5sum_current log_info collect_ssid_changes if ! $SSID_STATUS_TRACKING_WANTED; then return $SUCCESS; fi echo -n "" > "$SSID_STATUS_FILE" md5sum_prev=$(cat "${SSID_STATUS_FILE}_md5sum") SLOW_UPDATE_FILE="$SSID_STATUS_FILE" collect_ssid_statuses SLOW_UPDATE_FILE="$AGENT_DATA_FOLDER/TI_stats.txt" md5sum "$SSID_STATUS_FILE" | cut -d" " -f0 > "${SSID_STATUS_FILE}_md5sum" md5sum_current=$(cat "${SSID_STATUS_FILE}_md5sum") if ! [[ "$md5sum_prev" == "$md5sum_current" ]] && [[ $regular_seq_num -ne 0 ]]; then log_info ssid_change_detected force_enter_slow=1 fi } # wifi/scan_channels/mtk.sh # defaults to full scan, set in config file if [[ -z $SCAN_STRING ]]; then SCAN_STRING="SiteSurvey=1" fi scan_channels() { local output_file wlifs results results_5g results_combined ssid_col if ! check_wlan_enabled "$WLIF_24" && ! check_wlan_enabled "$WLIF_5"; then return $ERR_WIFI_DISABLED fi output_file="$AGENT_DATA_FOLDER/scan_results.txt" if check_wlan_enabled "$WLIF_24"; then iwpriv "$WLIF_24" set "$SCAN_STRING" fi if check_wlan_enabled "$WLIF_5"; then iwpriv "$WLIF_5" set "PartialScan=1" fi sleep 5 if check_wlan_enabled "$WLIF_5"; then ssid_col=$(iwpriv "$WLIF_5" get_site_survey | grep "SSID" | head -n 1 | awk '{for(i=1;i<=NF;i++) if ($i=="SSID") print i}') fi if check_wlan_enabled "$WLIF_24"; then results=$(iwpriv "$WLIF_24" get_site_survey | get_line_with_mac | tr -s ' ') fi if check_wlan_enabled "$WLIF_5"; then results_5g=$(iwpriv "$WLIF_5" get_site_survey | get_line_with_mac | tr -s ' ') fi results_combined="$results"$'\n'"$results_5g" echo -n '"neighbors":[' > "$output_file" reset_comma echo "$results_combined" | while read -r current_neighbor; do local channel bssid ssid remaining_part rssi standard_str ch_extension_str standard chanwidth nss channel=$(echo "$current_neighbor" | cut -d ' ' -f 2 | checknullp) bssid=$(echo "$current_neighbor" | extract_mac) ssid=$(echo "$current_neighbor" | cut -d ' ' -f ${ssid_col}-) ssid=${ssid%%$bssid*} ssid=$(echo "$ssid" | tr -cd '[]a-zA-Z0-9_-' | checknullp) remaining_part=${current_neighbor##*$bssid } rssi=$(echo "$remaining_part" | cut -d ' ' -f 2 | tr -cd '[0-9]-' | checknullp) standard_str=$(echo "$remaining_part" | cut -d ' ' -f 3) ch_extension_str=$(echo "$remaining_part" | cut -d ' ' -f 4) case $standard_str in *ac*) standard='ac' case $ch_extension_str in *NONE*) chanwidth=80 ;; *) chanwidth=40 ;; esac ;; *) standard='n' case $ch_extension_str in *NONE*) chanwidth=40 ;; *) chanwidth=20 ;; esac ;; esac chanwidth=$(echo "$chanwidth" | checknullp) nss=1 add_comma_if_necessary >> "$output_file" { echo -n '[' echo -n '"'"$bssid"'"' echo -n ',"'"$ssid"'"' echo -n ','"$rssi" echo -n ',"'"$standard"'"' echo -n ','"$channel" echo -n ','"$chanwidth" echo -n ','"$nss" echo -n ']' } >> "$output_file" done echo -n ']' >> "$output_file" } # wifi/stations-and-backhaul/mtk/ex5601-t1.sh if [ -z "$GATHER_STEERING_INFO" ]; then GATHER_STEERING_INFO=false; fi collect_all_station_infos(){ collect_station_info 24 collect_station_info 5 if $GATHER_STEERING_INFO; then collect_steering_event fi } # MT7975N/P (mt_wifi) collect_station_info() { local band lc_wlif bss_offset band_string local stainfo_line local connected_time connected_time_string local stainfo_out band=$1 log_verb "collect_station_info $band" log_checkpoint "STA_INFO_$band" if [ "$band" == "24" ]; then bss_offset=0 band_string="2.4" stainfo_out=$(cat "$AGENT_DATA_FOLDER"/lm_stainfo_ra0.txt) else bss_offset="$BSS_OFFSET" band_string="5" stainfo_out=$(cat "$AGENT_DATA_FOLDER"/lm_stainfo_rax0.txt) fi if [[ -n "$cur_active_client_tracking_file" ]]; then log_verb "[SCAN] Recording $band_string GHz client activities to file $cur_active_client_tracking_file" fi if [ -z "$stainfo_out" ]; then echo -n ',"rssi'$band'":[]' >> $REGULAR_UPDATE_FILE return $ERR_NO_STAINFO fi reset_comma echo -n ',"rssi'$band'":[' >> $REGULAR_UPDATE_FILE echo "$stainfo_out" | while read stainfo_line; do sta_mac=$(echo "$stainfo_line" | cut -d" " -f1) if grep -iq $sta_mac "$AGENT_DATA_FOLDER"/excluded_sta_macs; then continue fi common_sta_fields=$(get_common_sta_fields "$stainfo_line" "$bss_offset" "$sta_mac" "$band") add_comma_if_necessary >> $REGULAR_UPDATE_FILE; echo -n '{'$common_sta_fields'}' >> $REGULAR_UPDATE_FILE; done echo -n ']' >> $REGULAR_UPDATE_FILE } get_ifname_from_bss_index() { local bss_index=$1 local bss_offset=$2 local band=$3 if [[ -z "$bss_index" ]] && ! echo "$bss_index" | grep -q '[0-9]\+'; then return $ERR_INV_VAL fi if [ "$band" == "5" ]; then bss_index=$((bss_index - bss_offset)) #remove apcli interfaces then use xargs to get rid of leading / trailing spaces. interface_base=$(echo "$wlans_5" | sed 's/apcli[ix][0-9]//g' | xargs | cut -d" " -f1 | grep -o "ra[ix]") log_trbk "get_ifname_from_bss_index wlans5=$wlans_5 bss_index=$bss_index final_intf_name=$interface_base$bss_index" echo "$interface_base$bss_index" else echo "ra$bss_index" fi } if [[ -z "$rssi_index" ]]; then rssi_index=3 fi if [[ -z "$rate_index" ]]; then rate_index=8 fi if [[ -z "$rate_multiplier" ]]; then rate_multiplier=1000 fi if [[ -z "$rssi_limit" ]]; then rssi_limit="-100" fi if [[ -z "$phy_mode_index" ]]; then phy_mode_index=10 fi if [[ -z "$mcs_index" ]]; then mcs_index=11 fi get_common_sta_fields() { local stainfo_line=$1 local bss_offset=$2 local sta_mac=$3 local band=$4 local stacountinfo_line connected_time_line local bss_index ifname rssi tx_rate rx_rate tx_bytes rx_bytes connected_time max_phy_mode max_mcs log_data "$stainfo_line" "$bss_offset" #the 4th element will sometimes be combined with the 5th so we just take that into account #if it is combined the element needs to have at least 2 "/" for ex:HE_SU/HE_TRIG20M/20M skew_decide_num=$(echo "$stainfo_line" | cut -d ' ' -f4 | tr -cd "/" | wc -c ) if [[ $skew_decide_num -gt 1 ]]; then skew=1 else skew=0 fi bss_index=$(echo "$stainfo_line" | cut -d" " -f2) ifname=$(get_ifname_from_bss_index "$bss_index" "$bss_offset" "$band") rssi=$(echo "$stainfo_line" | cut -d ' ' -f $rssi_index | awk -v rssi_limit=$rssi_limit -v FS='/' '{sum=0; count=0; for(i=1;i<=NF;i++){ if($i!="0") { if($i>rssi_limit) { sum+=$i; count+=1; } } } print int(sum/count)}' | checknullp) tx_rate=$(echo "$stainfo_line" | cut -d" " -f$((rate_index-skew)) | cut -d"/" -f1) tx_rate=$((tx_rate * rate_multiplier)) tx_rate=$(checknull "$tx_rate") rx_rate=$(echo "$stainfo_line" | cut -d" " -f$((rate_index-skew)) | cut -d"/" -f2) rx_rate=$((rx_rate * rate_multiplier)) rx_rate=$(checknull "$rx_rate") stacountinfo_line=$(echo "$stacountinfo_out" | grep -i $sta_mac | head -1) tx_bytes=$(echo "$stacountinfo_line" | cut -d" " -f2 | checknullp) rx_bytes=$(echo "$stacountinfo_line" | cut -d" " -f3 | checknullp) connected_time_line=$(echo "$stainfo_line" | grep -o "Time:[0-9:]\+" | checknullp) connected_time=$(get_sta_connected_time | checkzerop_null) max_phy_mode=$(echo "$stainfo_line" | cut -d" " -f$((phy_mode_index-skew)) | checknullp) max_mcs=$(echo "$stainfo_line" | cut -d" " -f$((mcs_index-skew)) | checknullp) if $GATHER_STEERING_INFO; then v11=$(echo "$ZYSLCTL_INFO" | grep -i "$sta_mac" | awk '$9 == "YES" {print 1} $9 == "NO" {print 0}' | checknullp ) steerable=$(echo "$ZYSLCTL_INFO" | grep -i "$sta_mac" | awk '{ print ($10 == "STEERABLE") ? 1 : 0 }' | checknullp ) fi { echo -n '"mac":"'$sta_mac'"' echo -n ',"ifname":"'$ifname'"' echo -n ',"rssi":'$rssi echo -n ',"tx_bytes":'$tx_bytes echo -n ',"tx_rate":'$tx_rate echo -n ',"rx_bytes":'$rx_bytes echo -n ',"rx_rate":'$rx_rate echo -n ',"flags":null' echo -n ',"connected":'$connected_time echo -n ',"max_phy_mode":"'$max_phy_mode'"' echo -n ',"max_mcs":"'$max_mcs'"' if $GATHER_STEERING_INFO; then echo -n ',"11v":'$v11 echo -n ',"steerable":'$steerable fi } echo "$sta_mac" >> "$AGENT_DATA_FOLDER"/sta_roster.txt } get_sta_connected_time(){ log_verb get_sta_connected_time $connected_time_line hours=$(echo $connected_time_line | cut -d: -f2 | remove_leading_zeros | checknump) minutes=$(echo $connected_time_line | cut -d: -f3 | remove_leading_zeros | checknump) seconds=$(echo $connected_time_line | cut -d: -f4 | remove_leading_zeros | checknump) #add hours into minutes minutes=$(( hours * 60 + minutes )) #add minutes into seconds seconds=$(( minutes * 60 + seconds )) echo $seconds } collect_steering_event (){ local start end mac method frombss tobss result one_minute_ago log_info "collecting steer info" echo -n ',"steering_events":[' >> $REGULAR_UPDATE_FILE one_minute_ago=$((loop_start-60)) reset_comma echo "$STEER_INFO" | grep -v "TimeStart" | awk -v t="$one_minute_ago" '$2>t' | while read steerings; do add_comma_if_necessary >> $REGULAR_UPDATE_FILE start=$(echo "$steerings" | cut -d" " -f1 | checknump_null) end=$(echo "$steerings" | cut -d" " -f2 | checknump_null) mac=$(echo "$steerings" | cut -d" " -f3 | checknullp) method=$(echo "$steerings" | cut -d" " -f4 | checknullp) frombss=$(echo "$steerings" | cut -d" " -f5 | checknullp) tobss=$(echo "$steerings" | cut -d" " -f6 | checknullp) result=$(echo "$steerings" | cut -d" " -f7) if echo $result | grep -iq accept; then result=0 else result=$(echo $result | grep -o '[0-9]\+') if [[ -z "$result" ]]; then result=1 fi fi { echo -n '{"start":'$start echo -n ',"end":'$end echo -n ',"mac":"'$mac'"' echo -n ',"method":"'$method'"' echo -n ',"frombss":"'$frombss'"' echo -n ',"tobss":"'$tobss'"' echo -n ',"result":'$result'}' } >> $REGULAR_UPDATE_FILE done echo -n ']' >> $REGULAR_UPDATE_FILE } # wifi/stations-and-backhaul/collect_uplink_stats/from_bridge.sh collect_uplink_stats() { log_verb "[UPLINK_STATS]" brinf=$(ifconfig $BRIDGE) br_rx_pack=$(echo ${brinf#*RX packets:} | cut -d ' ' -f0) br_rx_pack=$(checknull "$br_rx_pack") br_tx_pack=$(echo ${brinf#*TX packets:} | cut -d ' ' -f0) br_tx_pack=$(checknull "$br_tx_pack") br_rx_byte=$(echo ${brinf#*RX bytes:} | cut -d ' ' -f0) br_rx_byte=$(checknull "$br_rx_byte") br_tx_byte=$(echo ${brinf#*TX bytes:} | cut -d ' ' -f0) br_tx_byte=$(checknull "$br_tx_byte") echo -n ',"br_data":['$br_rx_pack','$br_tx_pack','$br_rx_byte','$br_tx_byte']' >> $REGULAR_UPDATE_FILE } # regular_info/ex5601-t1.sh stat_out_24="" stat_out_5="" stacountinfo_out_24="" maxcap_info_out_24="" stacountinfo_out_5="" maxcap_info_out_5="" ZYSLCTL_INFO="" prepare_info_if_any() { # used in stations-and-backhaul/mtk/wx5600-t0.sh log_trbk prepare_info_if_any ZYSLCTL_INFO=$(zyslctl -c) stainfo_out_24="" stacountinfo_out_24="" maxcap_info_out_24="" stainfo_out_5="" stacountinfo_out_5="" maxcap_info_out_5="" prepare_client_info } if [ -z "$STAINFO_MTK_DEBUG_LEVEL" ]; then STAINFO_MTK_DEBUG_LEVEL="1" fi if [ -z "$STACOUNTINFO_MTK_DEBUG_LEVEL" ]; then STACOUNTINFO_MTK_DEBUG_LEVEL="1" fi STAINTO_RELATED_FIELDS_FILTER="1,5,9,10,11,12,13,16,18,19,21,26" STACOUNTINFO_RELATED_FIELDS_FILTER="1,5,6" if [[ -z "$USE_ZYWLCTL" ]]; then ZYWLCTL_STRING=$(zywlctl -h 2>&1 | grep lm_MibBucket) if [[ -n "$ZYWLCTL_STRING" ]]; then USE_ZYWLCTL=true else USE_ZYWLCTL=false fi fi execute_zywlctl_command() { local interface command clear_dmesg if [[ -z "$2" ]];then command=$1 zywlctl "$command" else interface=$1 command=$2 zywlctl -i "$interface" "$command" fi dmesg -c | filter_time_format "\[[0-9 \.]*\] \(Z[0-9]:\|\)" } prepare_client_info() { log_trbk prepare_client_info # shellcheck disable=SC2002 # stainfo_out_24=$(get_iwpriv_info_line "stainfo" "$WLIF_24" | combine_n_lines_after_mac 2) if $USE_ZYWLCTL; then stat_out_24=$(execute_zywlctl_command "$WLIF_24" "lm_stat" | tr -s " ") stat_out_5=$(execute_zywlctl_command "$WLIF_5" "lm_stat" | tr -s " ") else stat_out_24=$(iwpriv "$WLIF_24" "stat" | head -10 | tail -9 | awk 'NR!=4 && NR!=5' | tr -s " " ) stat_out_5=$(iwpriv "$WLIF_5" "stat" | head -10 | tail -9 | awk 'NR!=4 && NR!=5' | tr -s " " ) fi rm -f "$AGENT_DATA_FOLDER"/lm_stainfo_* touch "$AGENT_DATA_FOLDER"/lm_stainfo_${WLIF_24}.txt "$AGENT_DATA_FOLDER"/lm_stainfo_${WLIF_5}.txt for interface in $wlans_24 $wlans_5; do if $USE_ZYWLCTL; then execute_zywlctl_command "$interface" "lm_stainfo" | get_maxcap_line_awk | tr -s " " > "$AGENT_DATA_FOLDER"/lm_stainfo_${interface}.txt else get_iwpriv_info_line "stainfo" "$interface" | get_maxcap_line_awk | tr -s " " | cut -d" " -f$STAINTO_RELATED_FIELDS_FILTER > "$AGENT_DATA_FOLDER"/lm_stainfo_${interface}.txt fi done # shellcheck disable=SC2002 # stainfo_out_5=$(get_iwpriv_info_line "stainfo" "$WLIF_5" | combine_n_lines_after_mac 2) #maxcap_info_out_24=$(get_iwpriv_info_line "stainfo" "$WLIF_24" | filter_time_format | get_maxcap_line_awk | tr -s " ") #maxcap_info_out_5=$(get_iwpriv_info_line "stainfo" "$WLIF_5" | filter_time_format | get_maxcap_line_awk | tr -s " ") if $USE_ZYWLCTL; then stacountinfo_out=$(execute_zywlctl_command "lm_stacountinfo" | tr -s " ") else stacountinfo_out_24=$(get_iwpriv_info_line "stacountinfo" "$WLIF_24" | grep_only_for_mac_format_squeezed | cut -d" " -f"$STACOUNTINFO_RELATED_FIELDS_FILTER") stacountinfo_out_5=$(get_iwpriv_info_line "stacountinfo" "$WLIF_5" | grep_only_for_mac_format_squeezed | cut -d" " -f"$STACOUNTINFO_RELATED_FIELDS_FILTER") stacountinfo_out=$(echo -e "$stacountinfo_out_24\n$stacountinfo_out_5") fi log_data "$stacountinfo_out" log_trbk prepare_client_info_end } # dsl/collect_dsl_data/dummy.sh collect_dsl_data() { echo -n ',"dsl_data":null,"dsl_stats":null' >> $REGULAR_UPDATE_FILE } # wan/get_wan_interface/check_wan_interface/generic.sh check_wan_interface(){ local wan_interface wan_interface=$1 if [[ -z "$wan_interface" ]]; then wan_interface=$(cat "$AGENT_DATA_FOLDER"/lm_wan_interface) if [[ -z "$wan_interface" ]]; then wan_interface=eth0 fi else echo $wan_interface > "$AGENT_DATA_FOLDER"/lm_wan_interface fi echo $wan_interface } # wan/get_wan_interface/ex5601-t0.sh echo "" > "$AGENT_DATA_FOLDER"/lm_wan_interface get_wan_interface(){ wan_interface=$(ip route | grep "default" | grep -o "dev [a-zA-Z0-9\-_\.]*" | cut -d' ' -f2 | head -1 | awk ' { split($0,input,"[^[:alnum:]]"); print input[1] }') wan_interface=$(check_wan_interface $wan_interface) echo $wan_interface } # wan/collect_ppp_uptime/zyxel.sh collect_ppp_uptime() { log_verb collect_ppp_uptime default_interface=$(ip route | grep 'default via' | head -1 | tr -s ' '| cut -d ' ' -f 5) if [ -z "$default_interface" ] || ! [ -f "/var/run/$default_interface.pid" ]; then return $ERR_NO_DEF_INTERFACE; fi ppp_pid_created_at=$(date +%s -r /var/run/$default_interface.pid) if [ -n "$ppp_pid_created_at" ]; then now=$(date +%s) ppp_pid_time=$((now - ppp_pid_created_at)) if [ "$ppp_pid_time" -lt 0 ]; then echo -n ',"ppp_uptime":null' >> $REGULAR_UPDATE_FILE else echo -n ',"ppp_uptime":'$ppp_pid_time >> $REGULAR_UPDATE_FILE fi fi } # wan/collect_wan_stats/get_speed/ethwanctl.sh get_speed() { interface=$1 if [[ -z $interface ]]; then speed=0 elif [[ "$interface" == "$WAN_IF" ]]; then speed=$(ethwanctl show | tail -1 | grep -o ' [0-9]\+ ' | tr -d ' ') else speed=$(cat /sys/class/net/$interface/speed 2>/dev/null) fi if [[ -z $speed ]]; then echo 0 else echo $speed fi } # wan/collect_wan_stats/generic.sh collect_wan_stats() { log_verb "[WAN_STATS]" waninf=$(ifconfig "$WAN_IF") wan_rx_packets=$(echo ${waninf#*RX packets:} | cut -d ' ' -f0 | checknullp) wan_tx_packets=$(echo ${waninf#*TX packets:} | cut -d ' ' -f0 | checknullp) wan_rx_bytes=$(echo ${waninf#*RX bytes:} | cut -d ' ' -f0 | checknullp) wan_tx_bytes=$(echo ${waninf#*TX bytes:} | cut -d ' ' -f0 | checknullp) ethwan_speed=$(get_speed "$WAN_IF" | checknullp) { echo -n ',"wan":{"interface":"'$WAN_IF echo -n '","tx_bytes":'$wan_tx_bytes echo -n ',"rx_bytes":'$wan_rx_bytes echo -n ',"tx_packets":'$wan_tx_packets echo -n ',"rx_packets":'$wan_rx_packets echo -n ',"eth_wan_speed":'$ethwan_speed'}' echo -n ',"br_data":['$wan_tx_packets','$wan_rx_packets','$wan_tx_bytes','$wan_rx_bytes']' } >> $REGULAR_UPDATE_FILE } # wan/is_gateway/iproute2.sh is_gateway() { gw_in_br=$(ip route | grep "default via" | grep br) if [ -n "$gw_in_br" ]; then return $ERR_IPROUTE2_GENERIC else return $SUCCESS fi } if is_gateway; then echo "This device is a gateway." else echo "This device is an access point." fi # wan/collect_default_gw/iproute2.sh collect_default_gw() { default_gw=$(ip route | grep "default via" | cut -d' ' -f3) log_verb collect_default_gw $default_gw gw_mac=$(ip neigh show to "$default_gw" nud 2 2>/dev/null | head -1 | cut -d' ' -f 5 | pcheck_mac) if [[ -z "$gw_mac" ]] || [[ "$gw_mac" == "null" ]]; then gw_mac=$(ip neigh show to "$default_gw" | head -1 | cut -d' ' -f 5 | pcheck_mac) fi gw_mac=$(checknull_str $gw_mac) echo -n ',"gateway":{"mac":'$gw_mac'}' >> $SLOW_UPDATE_FILE } # device/zyxel.sh collect_device_info() { local serial_fw serial_fw=$(read_device_info) if echo "$serial_fw" | grep -q "null"; then sys atsh > "$AGENT_DATA_FOLDER"/lm_sys_atsh_stdout serial_fw=$(read_device_info) fi echo -n ',"dev_name":'$(echo "$serial_fw" | cut -d, -f1)',"dr_ver":'$(echo "$serial_fw" | cut -d, -f2) >> $SLOW_UPDATE_FILE } read_device_info(){ local sys_atsh_output sys_atsh_output=$(cat "$AGENT_DATA_FOLDER"/lm_sys_atsh_stdout) serial=$(echo "$sys_atsh_output" | grep "^Serial Number" | cut -d ':' -f2 | tr -d ' ') fw_ver=$(echo "$sys_atsh_output"| grep "^Firmware Version" | cut -d ':' -f2 | tr -d ' ') serial=$(checknull_str $serial) fw_ver=$(checknull_str $fw_ver) echo "$serial,$fw_ver" } collect_recover_status() { local recover_status_output if [[ "$first_time_running_script" == 1 ]]; then cat /misc/recover_status > "$AGENT_DATA_FOLDER"/lm_recover_status_stdout fi recover_status_output=$(cat "$AGENT_DATA_FOLDER"/lm_recover_status_stdout | grep "retrun" | grep -o "[0-9]\+" | tail -1) recover_status=$(echo "$recover_status_output" | checknullp) echo -n ',"recover_status":'$recover_status >> $SLOW_UPDATE_FILE } # dhcp/collect_leases/dnsmasq.sh if [[ -z "$LEASE_FILE" ]]; then LEASE_FILE="/var/dnsmasq/dnsmasq.leases" fi if [[ -z "$DNSMASQ_PROC_NAME" ]]; then DNSMASQ_PROC_NAME="/sbin/dnsmasq" fi if [[ -z "$MAC_IX" ]]; then MAC_IX=1 fi if [[ -z "$HOSTNAME_IX" ]]; then HOSTNAME_IX=3 fi if [[ -z "$DHCP_VERSION_IX" ]]; then DHCP_VERSION_IX=6 fi signal_dnsmasq_leases() { log_checkpoint "signal_dnsmasq_leases" # do not run if you don't know who to send signal to!!! # also acts a switch to whether signal before querying or not if [ -n "$DNSMASQ_PROC_NAME" ]; then ps | grep "$DNSMASQ_PROC_NAME" | grep -v grep | while read ps_line; do echo "$ps_line" | cut -d' ' -f1 | xargs kill -USR1; done sleep 1 fi } collect_leases() { log_checkpoint "collect_leases" signal_dnsmasq_leases echo -n '"stations":[' > "$AGENT_DATA_FOLDER"/station_metadata.txt dhcp_dump=$(cat "$LEASE_FILE") reset_comma if [ -n "$dhcp_dump" ]; then echo "$dhcp_dump" | while read -r line; do mac=$(echo "$line" | tr -s " " | cut -d' ' -f$MAC_IX | pcheck_mac) mac=$(checknull_str $mac) mac_no_quotes=${mac//\"/} name=$(echo "$line" | tr -s " " | cut -d' ' -f$HOSTNAME_IX | remove_illegal_characters) name=$(checknull_str $name) dhcp_ver=$(echo "$line" | tr -s " " | cut -d' ' -f${DHCP_VERSION_IX}- | tr " " "_" | remove_illegal_characters) dhcp_ver=$(checknull_str $dhcp_ver) if [[ -n "$SQLITE_INFO" ]]; then linksys_extra_info=$(echo "$SQLITE_INFO" | grep -i "$mac_no_quotes") linksys_model_number=$(echo "$linksys_extra_info" | cut -d'|' -f6) linksys_model_number=$(checknull_str $linksys_model_number) if echo $linksys_model_number | grep -q "^\"MX56"; then linksys_hostname=$(echo "$linksys_extra_info" | cut -d'|' -f8) else linksys_hostname=$(echo "$linksys_extra_info" | cut -d'|' -f3) fi linksys_hostname=$(checknull_str $linksys_hostname) if [[ -z "$name" ]] || [[ "$name" == "null" ]]; then name=$linksys_hostname fi linksys_device_type=$(echo "$linksys_extra_info" | cut -d'|' -f4) linksys_device_type=$(checknull_str $linksys_device_type) linksys_manufacturer=$(echo "$linksys_extra_info" | cut -d'|' -f5) linksys_manufacturer=$(checknull_str $linksys_manufacturer) linksys_operating_system=$(echo "$linksys_extra_info" | cut -d'|' -f7) linksys_operating_system=$(checknull_str $linksys_operating_system) fi { add_comma_if_necessary echo -n '{' echo -n '"mac":'$mac echo -n ',"name":'$name [ "$dhcp_ver" != "null" ] && echo -n ',"dhcp_info":'$dhcp_ver if [[ -n "$SQLITE_INFO" ]]; then [ "$linksys_device_type" != "null" ] && echo -n ',"type":'$linksys_device_type [ "$linksys_manufacturer" != "null" ] && echo -n ',"manufacturer":'$linksys_manufacturer [ "$linksys_model_number" != "null" ] && echo -n ',"model":'$linksys_model_number [ "$linksys_operating_system" != "null" ] && echo -n ',"operating_system":'$linksys_operating_system fi echo -n '}' } >> "$AGENT_DATA_FOLDER"/station_metadata.txt done fi; echo -n ']' >> "$AGENT_DATA_FOLDER"/station_metadata.txt } parse_dhcp() { cut -d ' ' -f2-4 "$LEASE_FILE" } # skeleton/child_updates.sh if [[ -z "$CHILD_UPDATES" ]]; then CHILD_UPDATES=false fi child_nodes="" prepare_child_nodes_updates() { local update_type=$1 log_info "Found nodes: $child_nodes" if [[ -n "$child_nodes" ]]; then mkdir "$AGENT_DATA_FOLDER"/child_${update_type}s if [[ "$update_type" == "regular" ]]; then for child_node in $child_nodes; do prepare_one_child_node_regular $child_node done elif [[ "$update_type" == "slow" ]]; then for child_node in $child_nodes; do prepare_one_child_node_slow $child_node $first_time_running_script done else log_err "Unknown update type $update_type" fi fi } send_child_nodes_updates(){ local update_type=$1 child_updates=$(ls "$AGENT_DATA_FOLDER"/child_${update_type}s/ 2>/dev/null) if [[ -n "$child_updates" ]]; then echo "$child_updates" | while read child_id; do if $ASYNC_UPDATES; then send_one_child_node_update "$update_type" "$child_id" & else send_one_child_node_update "$update_type" "$child_id" fi done fi } send_one_child_node_update(){ local update_type=$1 if [[ "$update_type" == "regular" ]]; then endpoint=reports param=cpe elif [[ "$update_type" == "slow" ]]; then endpoint=metadata param=metadata else log_err "Unknown update type $update_type" return $ERR_INV_UPDATE fi update_file="$2" child_id=$(echo "$update_file" | tr _ :) log_info "Sending $update_type for $child_id" wget_mortal '/'"$endpoint"'/'"$child_id"'?'$param'='$(cat "$AGENT_DATA_FOLDER"/child_"${update_type}"s/"$update_file") request_return_code=$? if [ $request_return_code -gt 0 ]; then log_err "Failed to send $update_type update for $child_id" else log_info "Sent $update_type update for $child_id successfully" fi } # skeleton/collect_codex_interface_list.sh collect_codex_interface_list(){ log_verb collect_codex_interface_list echo -n ',"codex_interface_list":{' >> $SLOW_UPDATE_FILE reset_comma echo -n '"primaries":{' >> $SLOW_UPDATE_FILE if [[ -n "$WLIF_24" ]]; then add_comma_if_necessary >> $SLOW_UPDATE_FILE echo -n '"24":"'$WLIF_24'"' >> $SLOW_UPDATE_FILE fi if [[ -z "$DISABLE_WIFI_5" ]] && [[ -n "$WLIF_5" ]]; then add_comma_if_necessary >> $SLOW_UPDATE_FILE echo -n '"5":"'$WLIF_5'"' >> $SLOW_UPDATE_FILE fi #end primaries list echo -n '}' >> $SLOW_UPDATE_FILE if [[ -n "$SECOND_PRIMARIES" ]]; then echo -n ',"second_primaries":{' >> $SLOW_UPDATE_FILE reset_comma if [[ -n "$SPWLIF_24" ]]; then add_comma_if_necessary >> $SLOW_UPDATE_FILE echo -n '"24":"'$SPWLIF_24'"' >> $SLOW_UPDATE_FILE fi if [[ -n "$SPWLIF_5" ]]; then add_comma_if_necessary >> $SLOW_UPDATE_FILE echo -n '"5":"'$SPWLIF_5'"' >> $SLOW_UPDATE_FILE fi if [[ -n "$SPWLIF_6" ]]; then add_comma_if_necessary >> $SLOW_UPDATE_FILE echo -n '"6":"'$SPWLIF_6'"' >> $SLOW_UPDATE_FILE fi #end second primaries list echo -n '}' >> $SLOW_UPDATE_FILE fi #end entire list echo -n "}" >> $SLOW_UPDATE_FILE } # skeleton/regular_update.sh regular_update() { log_info "RegularU start" cpe_id=$1 regular_seq_num=$2 timings_string=$3 post_mortem_stats=$(get_post_mortem_stats) echo -n "" > $REGULAR_UPDATE_FILE echo -n '{"ver":'$VERSION',"minor_ver":'$MINOR_VERSION',"script_type":'$SCRIPT_TYPE >> $REGULAR_UPDATE_FILE if [ $regular_seq_num -eq 0 ]; then collect_post_mortem "$post_mortem_stats" else log_checkpoint "ALL_TIMINGS" regular_interval=$(echo $timings_string | cut -d, -f1 | checknullp) regular_cpu_percentage=$(echo $timings_string | cut -d, -f2) regular_elapsed_time=$(echo $timings_string | cut -d, -f3) slow_interval=$(echo $timings_string | cut -d, -f4 | checknullp) slow_cpu_percentage=$(echo $timings_string | cut -d, -f5) slow_elapsed_time=$(echo $timings_string | cut -d, -f6) { echo -n ',"report_timings":{"since_last":'$regular_interval echo -n ',"elapsed":'$regular_elapsed_time echo -n ',"cpu_usage":'$regular_cpu_percentage'}' echo -n ',"metadata_timings":{"since_last":'$slow_interval echo -n ',"elapsed":'$slow_elapsed_time echo -n ',"cpu_usage":'$slow_cpu_percentage'}' } >> $REGULAR_UPDATE_FILE fi echo -n '' > "$AGENT_DATA_FOLDER"/sta_roster.txt echo -n '' > "$AGENT_DATA_FOLDER"/excluded_sta_macs collect_ssid_changes # cur_active_client_tracking_file is set globally on each iteration and used inside rssi24 and rssi5 if [[ "$ACTIVE_CLIENT_TRACKING_FLAG" -eq 1 ]]; then cur_active_client_tracking_file=$(get_cur_active_client_tracking_filename) # since there is no `touch` in some CPEs echo -n "" > "$cur_active_client_tracking_file" else cur_active_client_tracking_file="" fi collect_backhaul_links collect_all_station_infos log_checkpoint "REGULAR_STATS_24" collect_radio_stats collect_chaninfo "$REGULAR_UPDATE_FILE" if [[ $HAS_DSL -eq 1 ]]; then collect_dsl_data fi log_checkpoint "USAGE_COUNTERS" if is_gateway; then # also contains br_info but fills it with wan stats collect_wan_stats else collect_uplink_stats fi collect_eth_stats collect_ppp_uptime collect_nonwifi_clients collect_eth_client_speeds if [ $regular_seq_num -ne 0 ]; then collect_cpu_load_info fi if $CLIENT_CONNECTIVITY_EVENTS; then collect_client_events fi collect_free_mem collect_cpu_temp if $GATHER_CUSTOMER_SPECIFIC_DATA; then collect_customer_specific_data_regular fi echo -n ',"seq":'$regular_seq_num >> $REGULAR_UPDATE_FILE if [ -f "$AGENT_DATA_FOLDER"/lm_request_fails ]; then failed_string=$(cat "$AGENT_DATA_FOLDER"/lm_request_fails) failed_len=${#failed_string} if [[ $failed_len -gt 0 ]]; then echo -n ',"failed_requests":'$failed_len >> $REGULAR_UPDATE_FILE fi fi echo -n '}' >> $REGULAR_UPDATE_FILE if $ASYNC_UPDATES; then send_regular_update & else send_regular_update fi } send_regular_update() { log_info "RegularU Tx" wget_mortal '/reports/'$cpe_id'?cpe='$(cat $REGULAR_UPDATE_FILE) request_return_code=$? if [ $request_return_code -eq 0 ]; then echo -n "" > "$AGENT_DATA_FOLDER"/lm_request_fails else echo -n "F" >> "$AGENT_DATA_FOLDER"/lm_request_fails fi log_info "RegularU done." } # skeleton/slow_update.sh slow_update() { log_checkpoint "SLOW_BEGIN" cpe_id=$1 slow_seq_num=$2 next_regular_seq_num=$3 scan_flag=$4 if [[ $slow_seq_num -eq 0 ]]; then first_time_running_script=1 else first_time_running_script=0 fi echo -n '{"ver":'$VERSION',"minor_ver":'$MINOR_VERSION',"script_type":'$SCRIPT_TYPE',"first_run":'$first_time_running_script > $SLOW_UPDATE_FILE collect_codex_interface_list collect_uptime collect_device_info collect_recover_status collect_total_mem log_checkpoint "CPE_INFO_24" collect_ssids log_verb "COLLECT SSID STATUSES" collect_ssid_statuses collect_chaninfo "$SLOW_UPDATE_FILE" collect_wifi_feats log_checkpoint "SCAN_CHANNELS_BEGIN" if [ $scan_flag -eq 1 ] || [ $SCAN_DEBUG = true ]; then log_info "Started Scan" scan_channels scan_str=$(cat "$AGENT_DATA_FOLDER"/scan_results.txt) scan_flag=0 else scan_str='"neighbors":[]' fi echo -n ','"$scan_str" >> $SLOW_UPDATE_FILE collect_leases station_str=$(cat "$AGENT_DATA_FOLDER"/station_metadata.txt) echo -n ','$station_str >> $SLOW_UPDATE_FILE collect_friendly_node_names log_checkpoint "BRIDGE_BEGIN" collect_bridge_info bridge_info_str=$(cat "$AGENT_DATA_FOLDER"/bridge_info.txt) echo -n ','$bridge_info_str >> $SLOW_UPDATE_FILE if is_gateway; then echo -n ',"is_gateway":1' >> $SLOW_UPDATE_FILE else echo -n ',"is_gateway":0' >> $SLOW_UPDATE_FILE collect_default_gw fi collect_bridge_mac collect_if_macs collect_core_count if $GATHER_CUSTOMER_SPECIFIC_DATA; then collect_customer_specific_data_slow fi echo -n ',"seq":'$slow_seq_num',"next_update_seq":'$next_regular_seq_num >> $SLOW_UPDATE_FILE if [ -s "$AGENT_DATA_FOLDER"/lm_request_fails ]; then failed_string=$(cat "$AGENT_DATA_FOLDER"/lm_request_fails) failed_len=${#failed_string} echo -n ',"failed_requests":'$failed_len >> $SLOW_UPDATE_FILE fi echo -n "}" >> $SLOW_UPDATE_FILE # close bracket for message if $ASYNC_UPDATES; then send_slow_update & else send_slow_update fi } send_slow_update() { log_info "Started SlowU" wget_mortal '/metadata/'$cpe_id'?metadata='$(cat $SLOW_UPDATE_FILE) request_return_code=$? if [ $request_return_code -eq 0 ]; then echo -n "" > "$AGENT_DATA_FOLDER"/lm_request_fails else echo -n "F" >> "$AGENT_DATA_FOLDER"/lm_request_fails fi log_info "SlowU done" } # skeleton/scan_timer/active-client-tracking.sh DEFAULT_CLIENT_ACTIVE_THRESHOLD_PER_MIN=1500000 DEFAULT_ACTIVE_CLIENT_CHECK_INTERVAL_IN_MINS=30 DEFAULT_SCAN_SAFE_INTERVAL_BEGIN="23:00" DEFAULT_SCAN_SAFE_INTERVAL_END="02:00" if [[ -z "$ACTIVE_CLIENT_TRACKING_FLAG" ]]; then ACTIVE_CLIENT_TRACKING_FLAG=0; fi if [ -z "$SCAN_ENABLE" ]; then SCAN_ENABLE=0; fi if [ -z "$CLIENT_ACTIVE_THRESHOLD_PER_MIN" ]; then CLIENT_ACTIVE_THRESHOLD_PER_MIN=$DEFAULT_CLIENT_ACTIVE_THRESHOLD_PER_MIN; fi if [ -z "$ACTIVE_CLIENT_CHECK_INTERVAL_IN_MINS" ]; then ACTIVE_CLIENT_CHECK_INTERVAL_IN_MINS=$DEFAULT_ACTIVE_CLIENT_CHECK_INTERVAL_IN_MINS; fi if [ -z "$SCAN_SAFE_INTERVAL_BEGIN" ]; then SCAN_SAFE_INTERVAL_BEGIN=$DEFAULT_SCAN_SAFE_INTERVAL_BEGIN; fi if [ -z "$SCAN_SAFE_INTERVAL_END" ]; then SCAN_SAFE_INTERVAL_END=$DEFAULT_SCAN_SAFE_INTERVAL_END; fi TRACKING_FILE_PREFIX="$AGENT_DATA_FOLDER/lm_client_usage_" is_scan_necessary() { if [[ "$SCAN_ENABLE" -ne 1 ]]; then return $ERR_SCAN_DISABLED; fi last_scan_date=$(cat "$AGENT_DATA_FOLDER"/last_scan_date 2>/dev/null) if [[ -z "$last_scan_date" ]]; then log_verb "[SCAN] No previous scan done" return $SUCCESS; elif [[ $(get_last_date_for_time "$SCAN_SAFE_INTERVAL_BEGIN") == "$last_scan_date" ]]; then log_verb "[SCAN] A scan was done already in today's scan interval" return $ERR_INV_SCAN; fi } if ! SCAN_PERIOD_CONTAINS_MIDNIGHT=$(time_diff_seconds "$SCAN_SAFE_INTERVAL_BEGIN" "$SCAN_SAFE_INTERVAL_END"); then log_verb "[ERROR] Failed to compute time difference. Using default, is in scan period will return true to be safe" SCAN_PERIOD_CONTAINS_MIDNIGHT=0 fi is_in_scan_period() { now=$1 today_scan_safe_begin_ts=$(date -u -d "$(get_utc_date) $SCAN_SAFE_INTERVAL_BEGIN" +%s) today_scan_safe_end_ts=$(date -u -d "$(get_utc_date) $SCAN_SAFE_INTERVAL_END" +%s) if [[ "$SCAN_PERIOD_CONTAINS_MIDNIGHT" -eq 0 ]]; then log_verb "[SCAN] No specific scan interval" return $SUCCESS; elif [[ "$SCAN_PERIOD_CONTAINS_MIDNIGHT" -lt 0 ]]; then if [[ $now -gt $today_scan_safe_begin_ts ]] && [[ $now -lt $today_scan_safe_end_ts ]]; then log_verb "[SCAN] In safe scan interval" return $SUCCESS; else return $ERR_INV_TIMEDIFF; fi else # scan interval contains midnight if [[ $now -gt $today_scan_safe_end_ts ]] && [[ $now -lt $today_scan_safe_begin_ts ]]; then return $ERR_INV_TIMEDIFF; else log_verb "[SCAN] In safe scan interval" return $SUCCESS; fi fi } check_active_clients_and_schedule_scan() { local loop_start loop_start=$1 if is_scan_necessary && is_in_scan_period "$loop_start"; then log_verb "[SCAN] check_active_clients_and_schedule_scan" log_verb "loop_start: $loop_start next_active_client_check_time: $next_active_client_check_time diff: $((next_active_client_check_time-loop_start))" scan_flag=0 if [[ -z "$next_active_client_check_time" ]]; then rand_sec_delta=$(get_random_uint $((ACTIVE_CLIENT_CHECK_INTERVAL_IN_MINS * 60))) next_active_client_check_time=$((loop_start + rand_sec_delta)) log_verb "[SCAN] start scan procedure after $rand_sec_delta seconds" elif [[ "$loop_start" -gt "$next_active_client_check_time" ]]; then next_active_client_check_time=$((loop_start + (ACTIVE_CLIENT_CHECK_INTERVAL_IN_MINS * 60))) if check_if_there_are_no_active_clients || ! is_in_scan_period "$next_active_client_check_time"; then log_verb "[SCAN] No active clients or last chance to scan, preparing a slow update with scan" scan_flag=1 next_active_client_check_time="" mark_last_scan_date_and_cleanup else log_verb "[SCAN] Active clients found and there's still time to do a scan, retry after $ACTIVE_CLIENT_CHECK_INTERVAL_IN_MINS minutes" fi fi fi log_verb "[SCAN] check_active_clients_and_schedule_scan exit" return $scan_flag } get_cur_active_client_tracking_filename() { echo "$TRACKING_FILE_PREFIX$(date -u +%s)" } check_if_there_are_no_active_clients() { valid_interval=$REGULAR_UPDATE_SECONDS cur_ts=$(date -u +%s) # take latest two client tracking files and compare data inside files=$(ls -t "${TRACKING_FILE_PREFIX}"* | head -2) if [[ -n "$files" ]]; then log_verb "[SCAN] Found active client tracking files:" echo "$files" | while read file; do log_verb "[SCAN] $file"; done fi new_file=$(echo "$files" | get_nth_line 0) prev_file=$(echo "$files" | get_nth_line 1) cur_clients=$(cat "$new_file" 2>/dev/null) if [[ -z "$cur_clients" ]]; then log_verb "[SCAN] Current tracking file $new_file is empty" return $SUCCESS elif [[ -z "$prev_file" ]]; then log_verb "[SCAN] No previous file but current tracking file has clients" return $ERR_NO_PREV_TRACK_FILE fi # check if prev_file is from correct time # (or some left over file from a crash etc.) new_file_ts=$(echo "$new_file" | grep -o "[0-9]\+$") prev_file_ts=$(echo "$prev_file" | grep -o "[0-9]\+$") expected_prev_file_ts=$((cur_ts - ACTIVE_CLIENT_CHECK_INTERVAL_IN_MINS * 60)) log_verb "[SCAN] Current ts: $cur_ts Expected prev tracking file ts: $expected_prev_file_ts Valid interval: $valid_interval" log_verb "[SCAN] new file ts: $new_file_ts prev file ts: $prev_file_ts" if [[ "$new_file_ts" -gt $((cur_ts - valid_interval)) ]] \ && [[ "$prev_file_ts" -gt $((expected_prev_file_ts - valid_interval)) ]] \ && [[ "$prev_file_ts" -lt $((expected_prev_file_ts + valid_interval)) ]]; then log_verb "[SCAN] Comparing files $new_file vs. $prev_file" if cmp_client_data_usages "$new_file" "$prev_file"; then return $SUCCESS else return $ERR_FOUND_ACTIVE_CLIENTS fi else log_verb "[SCAN] Unable to find new or previous client tracking records from correct time" return $ERR_NO_PREV_AND_NEW_TRACK_FILE fi } mark_last_scan_date_and_cleanup() { rm -r "$AGENT_DATA_FOLDER"/lm_client_usage_* get_last_date_for_time "$SCAN_SAFE_INTERVAL_BEGIN" > "$AGENT_DATA_FOLDER"/last_scan_date } cmp_client_data_usages() { # for each client in new file see if old data exist # mark as active if old data does not exist as we can't know if it is inactive new_client_records=$(cat "$1") prev_client_records=$(cat "$2") echo "$new_client_records" | while read -r record; do client=$(echo "$record" | cut -d' ' -f1) prev_record=$(echo "$prev_client_records" | grep "$client") # check_client_active also checks if prev record exists if check_client_active "$record" "$prev_record"; then return $ERR_FOUND_ACTIVE_CLIENTS fi done return $SUCCESS } check_client_active() { local total_active_threshold txb_now txb_prev rxb_now rxb_prev rx_diff tx_diff local record=$1 local prev_record=$2 txb_now=$(echo "$record" | cut -d' ' -f2) rxb_now=$(echo "$record" | cut -d' ' -f3) if [[ -z "$prev_record" ]]; then return $SUCCESS else txb_prev=$(echo "$prev_record" | cut -d' ' -f2) rxb_prev=$(echo "$prev_record" | cut -d' ' -f3) fi total_active_threshold=$((CLIENT_ACTIVE_THRESHOLD_PER_MIN * ACTIVE_CLIENT_CHECK_INTERVAL_IN_MINS)) rx_diff=$((rxb_now - rxb_prev)) tx_diff=$((txb_now - txb_prev)) if [[ $tx_diff -gt $total_active_threshold ]] || [[ $rx_diff -gt $total_active_threshold ]]; then return $SUCCESS else return $ERR_NO_CLIENT_ACTIVITY fi } # skeleton/lm_procs/generic.sh other_lm_agent_pids() { local ps_out agent_pid ps_out=$(ps) agent_pid=$1 subshell_pid=$$ log_verb "$ps_out" log_verb "$agent_pid" log_verb "$subshell_pid" pid_list=$(echo "$ps_out" | grep "[l]ifemote_cpe" | grep -o '^\( \+\)\?[0-9]\+' | tr -d ' ' | grep -v "^$agent_pid" | grep -v "^$subshell_pid") log_verb "$pid_list" echo "$pid_list" } fratricide() { other_pids=$1 echo "$other_pids" | while read pid; do kill -9 $pid # kill em all done } existential_crisis() { other_pids=$1 echo "$other_pids" if [ -n "$other_pids" ]; then log_checkpoint "HARAKIRI" exit fi } # skeleton/cleanup.sh LAST_SIGNAL="EXIT" dying_gasp() { log_verb "dying_gasp $1" LAST_SIGNAL=$1 echo "$LAST_SIGNAL" > "$AGENT_DATA_FOLDER"/lm_quit_signal exit } get_post_mortem_stats(){ if [ -f $REGULAR_UPDATE_FILE ]; then regular_time=$(get_utc_date_iso_8601 -r "$REGULAR_UPDATE_FILE" | tr + _); last_regular_seq=$(grep -o '\"seq\":[0-9]\+' $REGULAR_UPDATE_FILE | cut -d':' -f2 | checknump) fi if [ -f $SLOW_UPDATE_FILE ]; then slow_time=$(get_utc_date_iso_8601 -r "$SLOW_UPDATE_FILE" | tr + _); last_slow_seq=$(grep -o '\"seq\":[0-9]\+' $SLOW_UPDATE_FILE | cut -d':' -f2 | checknump) fi echo "$regular_time,$last_regular_seq,$slow_time,$last_slow_seq" } collect_post_mortem() { post_mortem_stats=$1 regular_time=$(echo $post_mortem_stats | cut -d',' -f1); last_regular_seq=$(echo $post_mortem_stats | cut -d',' -f2); slow_time=$(echo $post_mortem_stats | cut -d',' -f3); last_slow_seq=$(echo $post_mortem_stats | cut -d',' -f4); reset_comma echo -n ',"post_mortem":{' >> $REGULAR_UPDATE_FILE if [ -n "$regular_time" ]; then { add_comma_if_necessary echo -n '"regular_time":"'$regular_time echo -n '","last_regular_seq":'$last_regular_seq } >> $REGULAR_UPDATE_FILE fi if [ -n "$slow_time" ]; then { add_comma_if_necessary echo -n '"slow_time":"'$slow_time echo -n '","last_slow_seq":'$last_slow_seq } >> $REGULAR_UPDATE_FILE fi if [ -f "$AGENT_DATA_FOLDER"/last_checkpoint ]; then { add_comma_if_necessary echo -n '"last_checkpoint":"'$(head -1 "$AGENT_DATA_FOLDER"/last_checkpoint) echo -n '","last_checkpoint_date":"'$(get_utc_date_iso_8601 -r "$AGENT_DATA_FOLDER"/last_checkpoint | tr + _)'"' } >> $REGULAR_UPDATE_FILE fi if [ -f $0 ]; then { add_comma_if_necessary echo -n '"agent_dwld_date":"'$(get_utc_date_iso_8601 -r $0 | tr + _)'"' } >> $REGULAR_UPDATE_FILE fi if [ -f "$AGENT_DATA_FOLDER"/lm_quit_signal ]; then { add_comma_if_necessary echo -n '"quit_signal":"'$(head -1 "$AGENT_DATA_FOLDER"/lm_quit_signal) echo -n '","quit_signal_date":"'$(get_utc_date_iso_8601 -r "$AGENT_DATA_FOLDER"/lm_quit_signal | tr + _)'"' } >> $REGULAR_UPDATE_FILE # reset last signal rm "$AGENT_DATA_FOLDER"/lm_quit_signal fi echo -n '}' >> $REGULAR_UPDATE_FILE } sentinel_message() { last_checkpoint=$(cat "$AGENT_DATA_FOLDER"/last_checkpoint) if [ -f "$AGENT_DATA_FOLDER"/lm_quit_signal ]; then last_signal=$(cat "$AGENT_DATA_FOLDER"/lm_quit_signal) else last_signal=EXIT echo EXIT > "$AGENT_DATA_FOLDER"/lm_quit_signal fi log_verb "sentinel_message $last_checkpoint $last_signal" if [ "$last_checkpoint" != "HARAKIRI" ] || [ "$last_signal" != "TERM" ]; then { echo -n '?data={"ver":'$VERSION echo -n ',"minor_ver":'$MINOR_VERSION echo -n ',"device_type":"'$DEVICE_TYPE echo -n '","checkpoint":"'$last_checkpoint echo -n '","signal":"'$LAST_SIGNAL'"}' } > "$AGENT_DATA_FOLDER"/sentinel_msg.txt if [ $HTTPS_CURL -eq 1 ]; then if $ASYNC_UPDATES; then wget_mortal '/crash/'${cpe_id}$(cat "$AGENT_DATA_FOLDER"/sentinel_msg.txt) & else wget_mortal '/crash/'${cpe_id}$(cat "$AGENT_DATA_FOLDER"/sentinel_msg.txt) fi else secure_get $UPDATE_URL'/crash/'$cpe_id $(cat "$AGENT_DATA_FOLDER"/sentinel_msg.txt) fi fi } setup_generic_traps() { for signal in "$@" ; do # shellcheck disable=SC2064 trap "dying_gasp $signal" "SIG$signal" done } #No SIGINT because that's used for debug purposes. setup_generic_traps HUP QUIT ILL ABRT FPE KILL SEGV PIPE ALRM TERM USR1 USR2 trap 'sentinel_message' EXIT agent_pid=$$ ps_out=$(ps) pid_list=$(echo "$ps_out" | grep "[l]ifemote_cpe" | grep -v "ps.*[l]ifemote_cpe" | grep -o '^\( \+\)\?[0-9]\+' | tr -d ' ' | grep -v "^$agent_pid") if [[ -n "$pid_list" ]]; then latest_version=$(cat "$AGENT_DATA_FOLDER"/lm_version_number) if grep "[0-9]*\.[0-9]*" "$AGENT_DATA_FOLDER"/lm_version_number; then lv_major=${latest_version%.*} lv_minor=${latest_version#*.} else lv_major=$latest_version lv_minor=0 fi if [ -z "$latest_version" ] || [ "$VERSION" -gt "$lv_major" ]; then fratricide $pid_list elif [ "$VERSION" -eq "$lv_major" ] && [ "$MINOR_VERSION" -gt "$lv_minor" ]; then fratricide $pid_list else log_checkpoint "HARAKIRI" exit fi fi echo -n "$VERSION.$MINOR_VERSION" > "$AGENT_DATA_FOLDER"/lm_version_number # skeleton/main-loop/generic.sh if [[ -z "$CHILD_UPDATES" ]]; then CHILD_UPDATES=false fi if [[ -z "$REGULAR_UPDATE_FILE" ]]; then REGULAR_UPDATE_FILE="$AGENT_DATA_FOLDER/report.txt" fi if [[ -z "$SLOW_UPDATE_FILE" ]]; then SLOW_UPDATE_FILE="$AGENT_DATA_FOLDER/TI_stats.txt" fi if [[ -z "$CPE_ID_INTERFACE" ]]; then CPE_ID_INTERFACE="eth0" fi if [[ -z "$WAIT_TIMER_SECS" ]] || [ "$DEBUG" -ne "$NO_DEBUG" ]; then WAIT_TIMER_SECS=0 fi if [[ -z "$(LC_ALL=C type -t prepare_info_if_any)" ]]; then eval "prepare_info_if_any() { return $SUCCESS; }" fi lifemote_cpe_agent() { local prev_regular_update_start prev_slow_update_start local regular_cpu_percentage regular_elapsed_time local slow_cpu_percentage slow_elapsed_time local slow_seq_num regular_seq_num scan_flag #Some devices have issues with stability before a certain amount of time. if [[ "$DEBUG" -eq "$NO_DEBUG" ]]; then sleep $WAIT_TIMER_SECS fi prev_slow_update_start=0 prev_regular_update_start=0 slow_time_delta=0 regular_time_delta=0 # Timing variables regular_cpu_percentage=0 regular_elapsed_time=0 slow_cpu_percentage=0 slow_elapsed_time=0 force_enter_slow=0 slow_seq_num=0 regular_seq_num=0 scan_flag=0 slow_interval_variation=$((REGULAR_UPDATE_SECONDS * 15)) slow_interval_variation=$(get_random_uint $REGULAR_UPDATE_SECONDS $slow_interval_variation) log_verb "[FIRST_RUN] slow_time_delta is $slow_time_delta" while true; do loop_start=$(date +%s) loop_start_script_cpu_usage=$(get_cpu_time_jiffies $$) loop_start_total_cpu_time=$(get_total_cpu_usage_of_cpe) if [[ -e $LOG_FILE_PATH ]]; then log_rotate fi cpe_id=$(get_cpe_id $CPE_ID_INTERFACE) # shellcheck disable=SC2034 WAN_IF=$(get_wan_interface) clear_bh_ifs_list get_all_wlans figure_out_wlif_roles prepare_info_if_any if [[ $regular_seq_num -ne 0 ]]; then regular_time_delta=$((loop_start - prev_regular_update_start)) slow_time_delta=$((loop_start - prev_slow_update_start)) fi if [ $regular_time_delta -ge $REGULAR_UPDATE_SECONDS ] || [ $regular_time_delta -eq 0 ]; then timings_string="$regular_time_delta,$regular_cpu_percentage,$regular_elapsed_time,$slow_time_delta,$slow_cpu_percentage,$slow_elapsed_time" regular_update "$cpe_id" "$regular_seq_num" "$timings_string" if $CHILD_UPDATES; then # used in child updates # shellcheck disable=SC2034 gw_cpe_id="$cpe_id" prepare_child_nodes_updates regular send_child_nodes_updates regular fi regular_end_epoch_time=$(date +%s) regular_elapsed_time=$((regular_end_epoch_time - loop_start)) regular_end_script_cpu_usage=$(get_cpu_time_jiffies $$) regular_end_script_loop_cpu_usage=$((regular_end_script_cpu_usage - loop_start_script_cpu_usage)) #includes all cpu usage times and idle regular_end_total_cpu_time=$(get_total_cpu_usage_of_cpe) total_intermediate_cpu_usage=$((regular_end_total_cpu_time - loop_start_total_cpu_time)) # multiply script usage by 100 to get percentage regular_cpu_percentage=$((regular_end_script_loop_cpu_usage * 100 / total_intermediate_cpu_usage)) regular_seq_num=$((regular_seq_num + 1)) prev_regular_update_start=$loop_start slow_cpu_percentage=0 slow_elapsed_time=0 fi; #prepare a scan if there isn't any active clients or if this is the last chance to do scan check_active_clients_and_schedule_scan "$loop_start" scan_flag=$? log_trbk "[SLOW_INTERVAL_VARIATION] $slow_interval_variation -lt $slow_time_delta" if [[ $slow_interval_variation -ne 0 ]] && [[ $slow_interval_variation -lt $slow_time_delta ]]; then slow_time_delta=0 slow_interval_variation=0 fi log_verb "[SLOW_UPDATE_CHECK] $slow_time_delta -ge $SLOW_UPDATE_SECONDS" if [ $slow_time_delta -ge $SLOW_UPDATE_SECONDS ] || [ $slow_time_delta -eq 0 ] || [ $force_enter_slow -eq 1 ] || [ $scan_flag -eq 1 ]; then slow_update "$cpe_id" "$slow_seq_num" "$regular_seq_num" "$scan_flag" if $CHILD_UPDATES; then prepare_child_nodes_updates slow send_child_nodes_updates slow fi slow_end_epoch_time=$(date +%s) slow_elapsed_time=$(( slow_end_epoch_time - regular_end_epoch_time )) slow_end_script_cpu_usage=$(get_cpu_time_jiffies $$) slow_end_script_loop_cpu_usage=$((slow_end_script_cpu_usage - regular_end_script_cpu_usage)) #includes all cpu usage times and idle slow_end_total_cpu_time=$(get_total_cpu_usage_of_cpe) total_intermediate_cpu_usage=$((slow_end_total_cpu_time - regular_end_total_cpu_time)) # multiply script usage by 100 to get percentage slow_cpu_percentage=$((slow_end_script_loop_cpu_usage * 100 / total_intermediate_cpu_usage)) slow_seq_num=$((slow_seq_num + 1)) if [ $force_enter_slow -eq 1 ]; then force_enter_slow=0 else prev_slow_update_start=$loop_start fi fi; loop_end=$(date +%s) loop_time_delta=$((loop_end - loop_start)) sleep_duration=$((REGULAR_UPDATE_SECONDS - loop_time_delta)) log_checkpoint "SLEEP_BEGIN" echo "RTD: $regular_time_delta STD: $slow_time_delta LTD: $loop_time_delta SDUR: $sleep_duration" sleep $sleep_duration # negative durations will grumble and just not sleep log_checkpoint "SLEEP_END" done log_checkpoint "OUT_OF_LOOP" } cpe_id=$(get_cpe_id "$CPE_ID_INTERFACE") echo "RTD: regular_time_delta STD: slow_time_delta LTD: loop_time_delta SDUR: sleep_duration" lifemote_cpe_agent