Cellular connection dropping on GL-X2000 Spitz Plus

Bug Report: GL-X2000 — qcm.sh overrides ip_type setting, forces IPv4v6 regardless of user configuration

Summary

The file /lib/netifd/proto/qcm.sh contains a hardcoded pdp_type='-4 -6' assignment that overrides the user-configured ip_type setting from the network config. This causes the QConnectManager to always attempt an IPv6 bearer setup — even when the user has explicitly set ip_type='IP' (IPv4 only) in the admin panel or via UCI.

This leads to a permanent connection failure after Telekom Germany's mandatory 24-hour session disconnect, because the IPv6 setup repeatedly fails with call_end_reason_verbose 231 (QMUXError 0xe), enters an infinite retry loop, and blocks the QMI interface with recurring requestSetupDataCall message timeout (err = 110).

Affected Device

  • Model: GL-X2000 (Spitz Plus)

  • Modem: Quectel EG120K-EA (firmware EG120KEAAAR01A11M2G)

  • Carrier: Deutsche Telekom (Germany), APN: internet.telekom

  • Firmware tested: 4.5.26 (confirmed), but the bug exists in all available firmware versions including 4.7.13 stable and 4.8.2 beta, as the affected code is identical.

Steps to Reproduce

  1. Insert a Telekom Germany SIM card into the GL-X2000.

  2. Set IP Type to "IPv4" in Internet → Cellular → SIM Card Settings.

  3. Confirm via UCI: uci get network.modem_2_1.ip_type returns IP.

  4. Confirm via AT command: AT+CGDCONT? returns +CGDCONT: 1,"IP","internet.telekom",....

  5. Wait for the carrier's 24-hour forced session disconnect (or simulate with ifdown modem_2_1 && sleep 5 && ifup modem_2_1).

  6. Observe the system log: the router attempts IPv6 bearer setup despite IPv4-only configuration.

Root Cause

In /lib/netifd/proto/qcm.sh, the case block correctly maps the ip_type UCI setting to the pdp_type variable:

case "$ip_type" in
    "IPV4V6") pdp_type='-4 -6' ;;
    "IPV6") pdp_type='-6' ;;
    *) pdp_type='-4' ;;
esac

However, a few lines later, inside the if [ "$apn_use" != "-1" ] block, pdp_type is unconditionally overwritten:

if [ "$apn_use" != "" ]; then
    pdp_type='-4 -6'    # <--- BUG: overrides the case block above
    proto_run_command "$interface" qcm ${pdp_type:=-4 -6} \
        ...

This means the user's IPv4-only setting is always ignored when apn_use is set (which is the default path).

Expected Behavior

The pdp_type variable set by the case "$ip_type" block should be passed through to proto_run_command without being overwritten. The QConnectManager should only attempt IPv6 if the user has explicitly configured ip_type='IPV4V6' or ip_type='IPV6'.

Workaround

Comment out the hardcoded assignment:

# pdp_type='-4 -6'

Then restart the network: /etc/init.d/network restart.

This fix must be reapplied after every firmware upgrade.

Log Evidence

After 24h disconnect — IPv6 retry loop (with bug):

modem_2_1: requestSetupDataCall QMUXResult = 0x1, QMUXError = 0xe
modem_2_1: call_end_reason is 1
modem_2_1: call_end_reason_type is 2
modem_2_1: call_end_reason_verbose is 231
modem_2_1: try to requestSetupDataCall 60 second later
modem_2_1: your sim card may not support ipv6, please contact your carrier
modem_2_1: check whether the sim card has obtained an ipv6 address. AT command 'AT+CGPADDR'
modem_2_1: trying to get ipv6 address
modem_2_1: requestSetupDataCall message timeout
modem_2_1: requestSetupDataCall err = 110

This cycle repeats indefinitely every 60 seconds, preventing reconnection.

Kernel log — related NETDEV WATCHDOG crash:

NETDEV WATCHDOG: wwan0 (qmi_wwan_q): transmit queue 0 timed out

The endless IPv6 retry loop saturates the QMI interface and eventually triggers a transmit queue timeout in the qmi_wwan_q driver.

Related Forum Thread

Other users are reporting identical symptoms and logs.

Suggested Fix

Remove the hardcoded pdp_type='-4 -6' assignment on the line inside the apn_use block, so the value from the case "$ip_type" block is respected. This is a one-line fix.