mm-broadband-bearer: fixed non-sequential CID selection

When a modem reported back non-sequential CIDs, MM was using the next
larger CID number after the last CID found.  In cases where the last CID
found was the highest numbered CID allowed and is not a modifiable CID,
MM would give up and fail to establish a data connection.

The above issue occurs on u-blox TOBY-R200 modems as of firmware 30.33
A02.02.  In this firmware version there are two default CIDs programmed
into the modem, one at CID 1 and another at CID 31.  The CID at 31 is
the highest CID number that can be used and cannot be modified.

This change makes it so while parsing CIDs for a match, if a jump in CID
numbers is detected, so not sequential, the first open CID will be used
before using the max CID +1 or replacing the max CID.  If an exact
match for IP type and APN is found, then that will still be used first.
This commit is contained in:
Matthew Starr
2019-09-13 18:13:26 +00:00
committed by Dan Williams
parent 2ecb96b6ad
commit e93b5c1c1f
+26 -5
View File
@@ -795,6 +795,7 @@ parse_pdp_list (MMBaseModem *modem,
GList *pdp_list;
GList *l;
guint cid;
guint prev_cid;
/* If cancelled, set result error */
if (g_cancellable_is_cancelled (ctx->cancellable)) {
@@ -832,6 +833,7 @@ parse_pdp_list (MMBaseModem *modem,
}
cid = 0;
prev_cid = 0;
/* Show all found PDP contexts in debug log */
mm_dbg ("Found '%u' PDP contexts", g_list_length (pdp_list));
@@ -871,14 +873,33 @@ parse_pdp_list (MMBaseModem *modem,
break;
}
/* PDP with no APN set? we may use that one if not exact match found */
if (!pdp->apn || !pdp->apn[0]) {
mm_dbg ("Found PDP context with CID %u and no APN",
pdp->cid);
cid = pdp->cid;
/* If an open CID was not found yet and the previous CID is not (CID - 1),
* this means that (previous CID + 1) is a blank CID that can be used.
*/
if (prev_cid != G_MAXUINT && (prev_cid + 1) < pdp->cid) {
mm_dbg ("Found the first unused PDP context with CID %u", (prev_cid + 1));
cid = prev_cid + 1;
/* Set prev_cid to G_MAXUINT to show an open CID was found and only an
* exact APN match would change the CID after
*/
prev_cid = G_MAXUINT;
} else {
/* PDP with no APN set? we may use that one if not exact match found */
if (!pdp->apn || !pdp->apn[0]) {
mm_dbg ("Found PDP context with CID %u and no APN",
pdp->cid);
cid = pdp->cid;
}
}
}
/* Update previous CID value to the current CID for use in the next loop,
* unless an unused CID was found
*/
if (prev_cid != G_MAXUINT)
prev_cid = pdp->cid;
if (ctx->max_cid < pdp->cid)
ctx->max_cid = pdp->cid;
}