From bc5f99d027f1cb38c874347be067230ad05e181d Mon Sep 17 00:00:00 2001 From: Tony Ukken Date: Thu, 15 Oct 2026 21:50:41 +0530 Subject: [PATCH] RDKEMW-26238: [8.6] Fix false TELEMETRY_WIFI_NOT_CONNECTED after wifi toggle checkWifiConnected() determined wifi state with "wpa_cli status", which needs wpa_supplicant's per-interface control socket. NetworkManager creates supplicant interfaces over D-Bus passing only Driver and Ifname, so an interface it re-creates gets an empty config with no ctrl_interface and no socket. Any wifi toggle (SetInterfaceState, nmcli radio wifi off/on, rfkill) therefore leaves wpa_cli broken for the life of the wpa_supplicant process. The probe then reported "not connected" while wifi was up. That logged a false TELEMETRY_WIFI_NOT_CONNECTED and, worse, left both IsEthernetConnected and IsWifiConnected at 0 so neither branch of the main flow ran: no gateway packet-loss telemetry and no wifi recovery ladder until the next maintenance reboot. Take wifi state from the kernel instead, so the probe cannot be broken by the subsystem it is watching: - checkWifiConnected() uses "iw dev link" (nl80211), which needs no control socket, no daemon and no config prerequisite. The LNF SSIDs are hidden, so the SSID used for the LNF match comes from "iw dev info" (kernel station state), falling back to the SSID: line of "iw link". - Drop the /tmp/wifi-on gate, a second piece of derived state that can drift and produce the same symptom. The file and its other producers and consumers are unchanged. - wifiReassociate() calls fi.w1.wpa_supplicant1.Interface.Reassociate over D-Bus instead of "wpa_cli reassociate". Both are wpas_request_connection() behind the same WPA_INTERFACE_DISABLED guard, so the operation is identical, but D-Bus does not depend on the control socket. The wpa_cli form is kept as a comment because it remains the short hand-run equivalent for triage. - Log whether the reassociate was actually performed. IsWifiReassociated stays unconditional: it is the escalation rung counter, and gating it on success would stop the ladder ever reaching wifiReset. Telemetry markers and every t2CountNotify call are byte-identical, and escalation timing is unchanged. Verified on an 8.6 build, including LNF detection on a device connected to the LNF enterprise SSID. --- lib/rdk/networkConnectionRecovery.sh | 33 ++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/lib/rdk/networkConnectionRecovery.sh b/lib/rdk/networkConnectionRecovery.sh index efdeae54..28ee5e56 100755 --- a/lib/rdk/networkConnectionRecovery.sh +++ b/lib/rdk/networkConnectionRecovery.sh @@ -32,7 +32,6 @@ fi logsFile=$LOG_PATH/ConnectionStats.txt dnsFile="/etc/resolv.dnsmasq" -wifiStateFile="/tmp/wifi-on" ipv4PacketLoss=0 ipv6PacketLoss=0 ipv4GwPresent=0 @@ -131,10 +130,13 @@ fi checkWifiConnected() { - [ ! -f "$wifiStateFile" ] && return 0 - strBuffer=$(wpa_cli status 2> /dev/null) - case "$strBuffer" in *"wpa_state=COMPLETED"*) ;; *) return 0 ;; esac - case "$strBuffer" in *"$lnfPskSSID"*|*"$lnfEnterpriseSSID"*) lnfSSIDConnected=1 ; return 0 ;; esac + strBuffer=$(iw dev "$WIFI_INTERFACE" link 2> /dev/null) + case "$strBuffer" in *"Connected to "*) ;; *) return 0 ;; esac + # LNF SSIDs are hidden, so prefer the kernel's station state; the scan-cache SSID + # reported by "iw link" can be empty for an AP that cloaks its SSID in beacons. + ssidBuffer=$(iw dev "$WIFI_INTERFACE" info 2> /dev/null | sed -n 's/^[[:space:]]*ssid //p') + [ -z "$ssidBuffer" ] && ssidBuffer=$(printf '%s\n' "$strBuffer" | sed -n 's/^[[:space:]]*SSID: //p') + case "$ssidBuffer" in *"$lnfPskSSID"*|*"$lnfEnterpriseSSID"*) lnfSSIDConnected=1 ; return 0 ;; esac return 1 } @@ -190,8 +192,25 @@ wifiReassociate() { log "Packet Loss WiFi Reassociating" t2CountNotify "WIFIV_ERR_reassoc" - wpa_cli reassociate - #set IsWifiReassociated to 1 after wifi reassociation + # Hand-run equivalent of the two calls below, for triage: + # wpa_cli reassociate + # It needs wpa_supplicant started with -O /var/run/wpa_supplicant on RDKE builds, + # because NetworkManager re-creates the supplicant interface without a control socket. + wpaIfacePath=$(timeout 10 dbus-send --system --print-reply --reply-timeout=5000 \ + --dest=fi.w1.wpa_supplicant1 /fi/w1/wpa_supplicant1 \ + fi.w1.wpa_supplicant1.GetInterface string:"$WIFI_INTERFACE" 2> /dev/null \ + | sed -n 's/.*object path "\(.*\)".*/\1/p') + if [ -z "$wpaIfacePath" ] ; then + log "WiFi Reassociate not performed: could not resolve wpa_supplicant interface object" + elif timeout 10 dbus-send --system --print-reply --reply-timeout=5000 \ + --dest=fi.w1.wpa_supplicant1 "$wpaIfacePath" \ + fi.w1.wpa_supplicant1.Interface.Reassociate > /dev/null 2>&1 ; then + log "WiFi Reassociate done" + else + log "WiFi Reassociate not performed: Reassociate call failed" + fi + #Advance the rung counter even when the request failed, otherwise the ladder can never + #escalate to wifiReset and would retry the reassociate rung indefinitely IsWifiReassociated=1 }