Hi @silvia,
Following up with a full root-cause analysis and a working minimal fix. This is not an APN/IP-type misconfiguration — the modem and SIM are fine; it is a specific interaction between the operator’s behaviour and quectel-CM’s connect logic. It affects any operator that auto-activates the IPv6 default/secondary PDN at attach (Orange Poland here, but this is a network class, not a one-off).
Setup
-
Modem: RG500Q-EA, FW RG500QEAAAR13A01M4G (..._01.200.01.200)
-
Driver: qmi_wwan_q, RawIP + QMAP, qmap_mode=1, single mux 0x81 → wwan0_1
-
App: QConnectManager_Linux_V1.6.5 (also verified identical code in V1.6.8)
-
Network: Orange PL. internet = IPv4-only PDN (CID1), internetipv6 = IPv6-only PDN (CID2)
The asymmetry
On the same attach:
-
IPv4 (-s internet, CID1 = the LTE attach/default bearer) → START_NETWORK_INTERFACE succeeds, data flows.
-
IPv6 (-s internetipv6, CID2 = a separate PDN) → START_NETWORK_INTERFACE always returns call_end_reason_verbose = 241 (INTERFACE_IN_USE_CONFIG_MATCH).
Why — the network auto-activates CID2 at every attach. AT confirms it (config is IPv4-only, yet CID2 comes up by itself):
+CGDCONT: 1,"IP","internet",...
+CGDCONT: 2,"IPV6","internetipv6",...
+CGACT: 1,1
+CGACT: 2,1 <-- IPv6 PDN already ACTIVE, activated by the network
+CGCONTRDP: 2,6,internetipv6,42.0.15.68.12.208... <-- real GUA 2a00:f44:cd0:bb66::/64, gw fe80::1, DNS 2a01:1700:3:ffff::9822
Because CID2 is already up, quectel-CM’s fresh IPv6 START_NETWORK_INTERFACE collides with it. Stock quectel-CM has no “adopt existing bearer” path for IPv6 — it just logs the reason and retries forever:
[15:24:21] requestQueryDataCall IPv6ConnectionStatus: DISCONNECTED
[15:24:21] requestSetupDataCall QMUXResult = 0x1, QMUXError = 0xe
[15:24:21] call_end_reason is 1
[15:24:21] call_end_reason_type is 2
[15:24:21] call_end_reason_verbose is 241
[15:24:21] try to requestSetupDataCall 5 second later
[15:24:26] ... call_end_reason_verbose is 241 ... 10 second later
[15:24:36] ... call_end_reason_verbose is 241 ... 20 second later
Proof the modem is fully capable — the IPv6 bearer is healthy; the only problem is the START-vs-already-active collision. If I deactivate CID2 (AT+CGACT=0,2) and immediately issue START, it succeeds and is stable. Note the network re-activates CID2 within < 2 s, so the deactivate+START must be tight:
[15:57:15] (AT) AT+CGACT=0,2 <-- deactivate the auto-active IPv6 PDN
[15:57:15] requestSetupDataCall ... verbose 241 -> retry
[15:57:15] (AT) AT+CGACT=0,2
[15:57:16] requestSetupDataCall WdsConnectionIPv6Handle: 0x227e2330 <-- SUCCESS
[15:57:16] ip -6 address add 2a00:f44:cd0:bb66:4dad:9c7d:258b:a280/64 dev wwan0_1
# ping6 google = 0% loss, stable, single handle, no reconnect loop
Minimal fix (host side, quectel-CM) — in requestSetupDataCall() (identical in V1.6.5 and V1.6.8), on an IPv6 failure, deactivate the matching PDN over the AT port and retry START in a tight loop:
static int requestSetupDataCall(PROFILE_T *profile, int curIpFamily) {
...
+ int v6_race = 0;
profile->curIpFamily = curIpFamily;
+_setup_start:
pRequest = ComposeQMUXMsg(QMIType, QMIWDS_START_NETWORK_INTERFACE_REQ, ...);
err = QmiThreadSendQMITimeout(pRequest, &pResponse, 120 * 1000, __func__);
qmi_rsp_check();
if (QMUXResult || QMUXError) {
... /* existing call_end_reason / verbose extraction */
err = le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError);
free(pResponse);
+ /* network auto-activated this IPv6 PDN -> 241; drop it and retry START
+ to win the short (<2s) window before the network brings it back */
+ if (curIpFamily == IpFamilyV6 && v6_race++ < 90) {
+ char at[32];
+ snprintf(at, sizeof(at), "AT+CGACT=0,%d\r", profile->pdp);
+ send_at_to_modem(at); /* write to the modem AT port, e.g. /dev/ttyUSB2 */
+ usleep(150 * 1000);
+ goto _setup_start;
+ }
return err;
}
...
}
This wins in ~2 attempts (< 1 s) and the IPv6 session is then stable. It is harmless on a clean modem (CGACT=0 on a down context just returns, then START succeeds) and does not touch the IPv4 path.
Requests
-
Preferred (CM side, your code): add an option to quectel-CM to handle verbose 241 on IPv6 by deactivating the auto-active PDN and retrying START (as above), or by adopting/reusing the existing bearer. We have a working reference implementation and can share the full diff.
-
Optional (firmware): make START_NETWORK_INTERFACE on a secondary IPv6 PDN whose config matches an already-active (network-initiated) bearer reuse it and return its handle — i.e. behave like the IPv4 attach bearer does today — instead of returning 241. That would remove the need for any host workaround.
Happy to provide full logs, a QMI capture, or the complete patch. Thank you!