Skip to content

Commit 55992a1

Browse files
author
Mirela Chirica
committed
- PDP context creation fixes for stack type handling
- Delete created contexts that do not succed to activate
1 parent 3e251e7 commit 55992a1

File tree

2 files changed

+83
-26
lines changed

2 files changed

+83
-26
lines changed

features/cellular/framework/AT/AT_CellularNetwork.cpp

Lines changed: 78 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ static const at_reg_t at_reg[] = {
3939
AT_CellularNetwork::AT_CellularNetwork(ATHandler &atHandler) : AT_CellularBase(atHandler),
4040
_stack(NULL), _apn(NULL), _uname(NULL), _pwd(NULL), _ip_stack_type_requested(DEFAULT_STACK), _ip_stack_type(DEFAULT_STACK), _cid(-1),
4141
_connection_status_cb(NULL), _op_act(operator_t::RAT_UNKNOWN), _authentication_type(CHAP), _last_reg_type(C_REG),
42-
_connect_status(NSAPI_STATUS_DISCONNECTED)
42+
_connect_status(NSAPI_STATUS_DISCONNECTED), _new_context_set(false)
4343
{
4444

4545
_at.set_urc_handler("NO CARRIER", callback(this, &AT_CellularNetwork::urc_no_carrier));
@@ -131,6 +131,23 @@ nsapi_error_t AT_CellularNetwork::connect(const char *apn,
131131
return connect();
132132
}
133133

134+
nsapi_error_t AT_CellularNetwork::delete_current_context()
135+
{
136+
_at.clear_error();
137+
_at.cmd_start("AT+CGDCONT=");
138+
_at.write_int(_cid);
139+
_at.cmd_stop();
140+
_at.resp_start();
141+
_at.resp_stop();
142+
143+
if (_at.get_last_error() == NSAPI_ERROR_OK) {
144+
_cid = -1;
145+
_new_context_set = false;
146+
}
147+
148+
return _at.get_last_error();
149+
}
150+
134151
nsapi_error_t AT_CellularNetwork::connect()
135152
{
136153
_at.lock();
@@ -155,7 +172,14 @@ nsapi_error_t AT_CellularNetwork::connect()
155172

156173
err = open_data_channel();
157174
if (err != NSAPI_ERROR_OK) {
175+
176+
// If new PDP context was created and failed to activate, delete it
177+
if (_new_context_set) {
178+
delete_current_context();
179+
}
180+
158181
_at.unlock();
182+
159183
tr_error("Failed to open data channel!");
160184

161185
_connect_status = NSAPI_STATUS_DISCONNECTED;
@@ -294,7 +318,7 @@ void AT_CellularNetwork::ppp_status_cb(nsapi_event_t event, intptr_t parameter)
294318
nsapi_error_t AT_CellularNetwork::set_context_to_be_activated()
295319
{
296320
// try to find or create context with suitable stack
297-
if (!get_context(_ip_stack_type_requested)) {
321+
if (!get_context()) {
298322
return NSAPI_ERROR_NO_CONNECTION;
299323
}
300324

@@ -316,12 +340,26 @@ nsapi_error_t AT_CellularNetwork::set_context_to_be_activated()
316340
return _at.get_last_error();
317341
}
318342

319-
bool AT_CellularNetwork::set_new_context(nsapi_ip_stack_t stack, int cid)
343+
bool AT_CellularNetwork::set_new_context(int cid)
320344
{
321-
nsapi_ip_stack_t tmp_stack = stack;
345+
nsapi_ip_stack_t tmp_stack = _ip_stack_type_requested;
346+
347+
if (tmp_stack == DEFAULT_STACK) {
348+
bool modem_supports_ipv6 = get_modem_stack_type(IPV6_STACK);
349+
bool modem_supports_ipv4 = get_modem_stack_type(IPV4_STACK);
350+
351+
if (modem_supports_ipv6 && modem_supports_ipv4) {
352+
tmp_stack = IPV4V6_STACK;
353+
} else if (modem_supports_ipv6) {
354+
tmp_stack = IPV6_STACK;
355+
} else if (modem_supports_ipv4) {
356+
tmp_stack = IPV4_STACK;
357+
}
358+
}
359+
322360
char pdp_type[8+1] = {0};
323361

324-
switch (stack) {
362+
switch (tmp_stack) {
325363
case IPV4_STACK:
326364
strncpy(pdp_type, "IP", sizeof(pdp_type));
327365
break;
@@ -332,7 +370,6 @@ bool AT_CellularNetwork::set_new_context(nsapi_ip_stack_t stack, int cid)
332370
strncpy(pdp_type, "IPV4V6", sizeof(pdp_type));
333371
break;
334372
default:
335-
strncpy(pdp_type, "", sizeof(pdp_type));
336373
break;
337374
}
338375

@@ -363,12 +400,13 @@ bool AT_CellularNetwork::set_new_context(nsapi_ip_stack_t stack, int cid)
363400
if (success) {
364401
_ip_stack_type = tmp_stack;
365402
_cid = cid;
403+
_new_context_set = true;
366404
}
367405

368406
return success;
369407
}
370408

371-
bool AT_CellularNetwork::get_context(nsapi_ip_stack_t requested_stack)
409+
bool AT_CellularNetwork::get_context()
372410
{
373411
_at.cmd_start("AT+CGDCONT?");
374412
_at.cmd_stop();
@@ -378,6 +416,9 @@ bool AT_CellularNetwork::get_context(nsapi_ip_stack_t requested_stack)
378416
char apn[MAX_ACCESSPOINT_NAME_LENGTH];
379417
int apn_len = 0;
380418

419+
bool modem_supports_ipv6 = get_modem_stack_type(IPV6_STACK);
420+
bool modem_supports_ipv4 = get_modem_stack_type(IPV4_STACK);
421+
381422
while (_at.info_resp()) {
382423
int cid = _at.read_int();
383424
if (cid > cid_max) {
@@ -392,29 +433,42 @@ bool AT_CellularNetwork::get_context(nsapi_ip_stack_t requested_stack)
392433
continue;
393434
}
394435
nsapi_ip_stack_t pdp_stack = string_to_stack_type(pdp_type_from_context);
395-
if (pdp_stack != DEFAULT_STACK) {
396-
if (get_modem_stack_type(pdp_stack)) {
397-
if (requested_stack == IPV4_STACK) {
398-
if (pdp_stack == IPV4_STACK || pdp_stack == IPV4V6_STACK) {
399-
_ip_stack_type = requested_stack;
436+
// Accept dual PDP context for IPv4/IPv6 only modems
437+
if (pdp_stack != DEFAULT_STACK && (get_modem_stack_type(pdp_stack) || pdp_stack == IPV4V6_STACK)) {
438+
if (_ip_stack_type_requested == IPV4_STACK) {
439+
if (pdp_stack == IPV4_STACK || pdp_stack == IPV4V6_STACK) {
440+
_ip_stack_type = _ip_stack_type_requested;
441+
_cid = cid;
442+
break;
443+
}
444+
} else if (_ip_stack_type_requested == IPV6_STACK) {
445+
if (pdp_stack == IPV6_STACK || pdp_stack == IPV4V6_STACK) {
446+
_ip_stack_type = _ip_stack_type_requested;
447+
_cid = cid;
448+
break;
449+
}
450+
} else {
451+
// If dual PDP need to check for IPV4 or IPV6 modem support. Prefer IPv6.
452+
if (pdp_stack == IPV4V6_STACK) {
453+
if (modem_supports_ipv6) {
454+
_ip_stack_type = IPV6_STACK;
400455
_cid = cid;
401456
break;
402-
}
403-
} else if (requested_stack == IPV6_STACK) {
404-
if (pdp_stack == IPV6_STACK || pdp_stack == IPV4V6_STACK) {
405-
_ip_stack_type = requested_stack;
457+
} else if (modem_supports_ipv4) {
458+
_ip_stack_type = IPV4_STACK;
406459
_cid = cid;
407460
break;
408461
}
409-
} else { // accept any but prefer to IPv6
410-
if (pdp_stack == IPV6_STACK || pdp_stack == IPV4V6_STACK) {
411-
_ip_stack_type = requested_stack;
412-
_cid = cid;
462+
// If PDP is IPV4 or IPV6 they are already checked if supported
463+
} else {
464+
_ip_stack_type = pdp_stack;
465+
_cid = cid;
466+
467+
if (pdp_stack == IPV6_STACK) {
413468
break;
414469
}
415-
if (_ip_stack_type == DEFAULT_STACK) {
416-
_ip_stack_type = pdp_stack;
417-
_cid = cid;
470+
if (pdp_stack == IPV4_STACK && !modem_supports_ipv6) {
471+
break;
418472
}
419473
}
420474
}
@@ -424,7 +478,7 @@ bool AT_CellularNetwork::get_context(nsapi_ip_stack_t requested_stack)
424478
}
425479
_at.resp_stop();
426480
if (_cid == -1) { // no suitable context was found so create a new one
427-
if (!set_new_context(requested_stack, cid_max+1)) {
481+
if (!set_new_context(cid_max+1)) {
428482
return false;
429483
}
430484
}

features/cellular/framework/AT/AT_CellularNetwork.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,11 @@ class AT_CellularNetwork : public CellularNetwork, public AT_CellularBase
139139
void free_credentials();
140140

141141
nsapi_error_t open_data_channel();
142-
bool get_context(nsapi_ip_stack_t supported_stack);
143-
bool set_new_context(nsapi_ip_stack_t stack, int cid);
142+
bool get_context();
143+
bool set_new_context(int cid);
144144
nsapi_error_t set_registration_urc(bool on);
145+
nsapi_error_t delete_current_context();
146+
145147
#if NSAPI_PPP_AVAILABLE
146148
void ppp_status_cb(nsapi_event_t, intptr_t);
147149
#endif
@@ -161,6 +163,7 @@ class AT_CellularNetwork : public CellularNetwork, public AT_CellularBase
161163
int _cell_id;
162164
RegistrationType _last_reg_type;
163165
nsapi_connection_status_t _connect_status;
166+
bool _new_context_set;
164167
};
165168

166169
} // namespace mbed

0 commit comments

Comments
 (0)