uqmi: add PDP watchdog uqmi-optimization
authorDavid Bauer <mail@david-bauer.net>
Sat, 7 Oct 2023 20:29:06 +0000 (22:29 +0200)
committerDavid Bauer <mail@david-bauer.net>
Tue, 21 Nov 2023 13:37:36 +0000 (14:37 +0100)
package/network/utils/uqmi/Makefile
package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh
package/network/utils/uqmi/files/lib/uqmi/qmi-watchdog.sh [new file with mode: 0644]

index 26b588c7ef57fefda590c0f98322045cd04ed4c4..e6b6ddfe6af4c6fbf72f420c9874366c58aa0fd2 100644 (file)
@@ -41,9 +41,10 @@ CMAKE_OPTIONS += \
        -DDEBUG=1
 
 define Package/uqmi/install
-       $(INSTALL_DIR) $(1)/sbin
+       $(INSTALL_DIR) $(1)/sbin $(1)/lib/uqmi $(1)/lib/netifd/proto
        $(INSTALL_BIN) $(PKG_BUILD_DIR)/uqmi $(1)/sbin/
-       $(CP) ./files/* $(1)/
+       $(INSTALL_BIN) ./files/lib/uqmi/qmi-watchdog.sh $(1)/lib/uqmi/qmi-watchdog.sh
+       $(CP) ./files/lib/netifd/proto/qmi.sh $(1)/lib/netifd/proto/qmi.sh
 endef
 
 $(eval $(call BuildPackage,uqmi))
index f8e655455a54b591dab00b4fbde2d91a061591fa..5ccf935b34f9191c6c03eae3a8175f76c1f80999 100755 (executable)
@@ -27,6 +27,9 @@ proto_qmi_init_config() {
        proto_config_add_int plmn
        proto_config_add_int timeout
        proto_config_add_int mtu
+       proto_config_add_boolean watchdog_enabled
+       proto_config_add_int watchdog_interval
+       proto_config_add_int watchdog_timeout
        proto_config_add_defaults
 }
 
@@ -39,10 +42,12 @@ proto_qmi_setup() {
        local cid_4 pdh_4 cid_6 pdh_6
        local ip_6 ip_prefix_length gateway_6 dns1_6 dns2_6
        local profile_pdptype
+       local watchdog_enabled watchdog_interval watchdog_timeout
 
        json_get_vars device apn v6apn auth username password pincode delay modes
        json_get_vars pdptype profile v6profile dhcp dhcpv6 autoconnect plmn ip4table
-       json_get_vars ip6table timeout mtu $PROTO_DEFAULT_OPTIONS
+       json_get_vars ip6table timeout mtu
+       json_get_vars watchdog_enabled watchdog_interval watchdog_timeout $PROTO_DEFAULT_OPTIONS
 
        [ "$timeout" = "" ] && timeout="10"
 
@@ -484,6 +489,22 @@ proto_qmi_setup() {
                        ubus call network add_dynamic "$(json_dump)"
                fi
        }
+
+       local cid_list
+       if [ -n "$cid_4" -a -n "$cid_6" ]; then
+               cid_list="$cid_4,$cid_6"
+       elif [ -n "$cid_4" ]; then
+               cid_list="$cid_4"
+       elif [ -n "$cid_6" ]; then
+               cid_list="$cid_6"
+       fi
+
+       if [ -n "$watchdog_enabled" -a "$watchdog_enabled" != "0" ]; then
+               [ -z "$watchdog_interval" ] && watchdog_interval="60"
+               [ -z "$watchdog_timeout" ] && watchdog_timeout="5"
+               proto_run_command "$interface" /lib/uqmi/qmi-watchdog.sh "$device" "$watchdog_interval" \
+                       "$watchdog_timeout" "$cid_list"
+       fi
 }
 
 qmi_wds_stop() {
diff --git a/package/network/utils/uqmi/files/lib/uqmi/qmi-watchdog.sh b/package/network/utils/uqmi/files/lib/uqmi/qmi-watchdog.sh
new file mode 100644 (file)
index 0000000..ee625cd
--- /dev/null
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+. /usr/share/libubox/jshn.sh
+
+DEVICE_PATH=$1
+CHECK_INTERVAL=$2
+DISCONNECTED_TIMEOUT=$3
+CID_LIST=$4
+
+while true; do
+       oldifs="$IFS"
+       IFS=","
+       for cid in $CID_LIST; do
+               IFS="$oldifs"
+
+               # Reset for every CID
+               timeout_counter=0
+
+               while true; do
+                       sleep "$CHECK_INTERVAL"
+                       if [ "$timeout_counter" -gt "$DISCONNECTED_TIMEOUT" ]; then
+                               echo "Data / Network connection error exceeds timeout - restart interface now"
+                               return 1
+                       fi
+
+                       data_status="$(uqmi -t 1000 -s -d "$DEVICE_PATH" --set-client-id wds,$cid  --get-data-status)"
+                       registration_status=$(uqmi -s -d "$DEVICE_PATH" --get-serving-system 2>/dev/null | jsonfilter -e "@.registration" 2>/dev/null)
+
+                       json_init
+                       json_load "$(uqmi -s -d "$DEVICE_PATH" --uim-get-sim-state)"
+                       json_get_var card_application_state card_application_state
+
+                       if [ "$card_application_state" = "illegal" ]; then
+                               # This does not recover. We don't have to wait out the timeout.
+                               echo "SIM card in illegal state - restart interface now"
+                               return 1
+                       elif [ -z "$card_application_state" ]; then
+                               # No SIM Status. Either the next request succeeds or the SIM card
+                               # potentially needs to be power-cycled
+                               echo "Empty SIM card application status"
+                               let timeout_counter++
+                               continue
+                       elif [ "$data_status" != "\"connected\"" ]; then
+                               # PDP context might recover in case autoconnect is enabled
+                               # and still working. Give the modem a fair chance to recover.
+                               echo "PDP context not connected for CID $cid"
+                               let timeout_counter++
+                               continue
+                       elif [ "$registration_status" != "registered" ]; then
+                               # Sometimes Data status reports "connected" although
+                               # we are not registered to a mobile network.
+                               echo "No network registration"
+                               let timeout_counter++
+                               continue
+                       fi
+               done
+       done
+done
\ No newline at end of file