- PDP context creation fixes for stack type handling

- Delete created contexts that do not succed to activate
pull/6082/head
Mirela Chirica 2018-02-23 10:36:23 +02:00 committed by Ari Parkkila
parent 0c49b669b4
commit 6670ebbc5f
2 changed files with 84 additions and 27 deletions

View File

@ -39,7 +39,7 @@ static const at_reg_t at_reg[] = {
AT_CellularNetwork::AT_CellularNetwork(ATHandler &atHandler) : AT_CellularBase(atHandler), AT_CellularNetwork::AT_CellularNetwork(ATHandler &atHandler) : AT_CellularBase(atHandler),
_stack(NULL), _apn(NULL), _uname(NULL), _pwd(NULL), _ip_stack_type_requested(DEFAULT_STACK), _ip_stack_type(DEFAULT_STACK), _cid(-1), _stack(NULL), _apn(NULL), _uname(NULL), _pwd(NULL), _ip_stack_type_requested(DEFAULT_STACK), _ip_stack_type(DEFAULT_STACK), _cid(-1),
_connection_status_cb(NULL), _op_act(operator_t::RAT_UNKNOWN), _authentication_type(CHAP), _last_reg_type(C_REG), _connection_status_cb(NULL), _op_act(operator_t::RAT_UNKNOWN), _authentication_type(CHAP), _last_reg_type(C_REG),
_connect_status(NSAPI_STATUS_DISCONNECTED) _connect_status(NSAPI_STATUS_DISCONNECTED), _new_context_set(false)
{ {
_at.set_urc_handler("NO CARRIER", callback(this, &AT_CellularNetwork::urc_no_carrier)); _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,
return connect(); return connect();
} }
nsapi_error_t AT_CellularNetwork::delete_current_context()
{
_at.clear_error();
_at.cmd_start("AT+CGDCONT=");
_at.write_int(_cid);
_at.cmd_stop();
_at.resp_start();
_at.resp_stop();
if (_at.get_last_error() == NSAPI_ERROR_OK) {
_cid = -1;
_new_context_set = false;
}
return _at.get_last_error();
}
nsapi_error_t AT_CellularNetwork::connect() nsapi_error_t AT_CellularNetwork::connect()
{ {
_at.lock(); _at.lock();
@ -155,7 +172,14 @@ nsapi_error_t AT_CellularNetwork::connect()
err = open_data_channel(); err = open_data_channel();
if (err != NSAPI_ERROR_OK) { if (err != NSAPI_ERROR_OK) {
// If new PDP context was created and failed to activate, delete it
if (_new_context_set) {
delete_current_context();
}
_at.unlock(); _at.unlock();
tr_error("Failed to open data channel!"); tr_error("Failed to open data channel!");
_connect_status = NSAPI_STATUS_DISCONNECTED; _connect_status = NSAPI_STATUS_DISCONNECTED;
@ -294,7 +318,7 @@ void AT_CellularNetwork::ppp_status_cb(nsapi_event_t event, intptr_t parameter)
nsapi_error_t AT_CellularNetwork::set_context_to_be_activated() nsapi_error_t AT_CellularNetwork::set_context_to_be_activated()
{ {
// try to find or create context with suitable stack // try to find or create context with suitable stack
if (!get_context(_ip_stack_type_requested)) { if (!get_context()) {
return NSAPI_ERROR_NO_CONNECTION; return NSAPI_ERROR_NO_CONNECTION;
} }
@ -316,12 +340,26 @@ nsapi_error_t AT_CellularNetwork::set_context_to_be_activated()
return _at.get_last_error(); return _at.get_last_error();
} }
bool AT_CellularNetwork::set_new_context(nsapi_ip_stack_t stack, int cid) bool AT_CellularNetwork::set_new_context(int cid)
{ {
nsapi_ip_stack_t tmp_stack = stack; nsapi_ip_stack_t tmp_stack = _ip_stack_type_requested;
if (tmp_stack == DEFAULT_STACK) {
bool modem_supports_ipv6 = get_modem_stack_type(IPV6_STACK);
bool modem_supports_ipv4 = get_modem_stack_type(IPV4_STACK);
if (modem_supports_ipv6 && modem_supports_ipv4) {
tmp_stack = IPV4V6_STACK;
} else if (modem_supports_ipv6) {
tmp_stack = IPV6_STACK;
} else if (modem_supports_ipv4) {
tmp_stack = IPV4_STACK;
}
}
char pdp_type[8+1] = {0}; char pdp_type[8+1] = {0};
switch (stack) { switch (tmp_stack) {
case IPV4_STACK: case IPV4_STACK:
strncpy(pdp_type, "IP", sizeof(pdp_type)); strncpy(pdp_type, "IP", sizeof(pdp_type));
break; break;
@ -332,7 +370,6 @@ bool AT_CellularNetwork::set_new_context(nsapi_ip_stack_t stack, int cid)
strncpy(pdp_type, "IPV4V6", sizeof(pdp_type)); strncpy(pdp_type, "IPV4V6", sizeof(pdp_type));
break; break;
default: default:
strncpy(pdp_type, "", sizeof(pdp_type));
break; break;
} }
@ -363,12 +400,13 @@ bool AT_CellularNetwork::set_new_context(nsapi_ip_stack_t stack, int cid)
if (success) { if (success) {
_ip_stack_type = tmp_stack; _ip_stack_type = tmp_stack;
_cid = cid; _cid = cid;
_new_context_set = true;
} }
return success; return success;
} }
bool AT_CellularNetwork::get_context(nsapi_ip_stack_t requested_stack) bool AT_CellularNetwork::get_context()
{ {
_at.cmd_start("AT+CGDCONT?"); _at.cmd_start("AT+CGDCONT?");
_at.cmd_stop(); _at.cmd_stop();
@ -378,6 +416,9 @@ bool AT_CellularNetwork::get_context(nsapi_ip_stack_t requested_stack)
char apn[MAX_ACCESSPOINT_NAME_LENGTH]; char apn[MAX_ACCESSPOINT_NAME_LENGTH];
int apn_len = 0; int apn_len = 0;
bool modem_supports_ipv6 = get_modem_stack_type(IPV6_STACK);
bool modem_supports_ipv4 = get_modem_stack_type(IPV4_STACK);
while (_at.info_resp()) { while (_at.info_resp()) {
int cid = _at.read_int(); int cid = _at.read_int();
if (cid > cid_max) { if (cid > cid_max) {
@ -392,30 +433,43 @@ bool AT_CellularNetwork::get_context(nsapi_ip_stack_t requested_stack)
continue; continue;
} }
nsapi_ip_stack_t pdp_stack = string_to_stack_type(pdp_type_from_context); nsapi_ip_stack_t pdp_stack = string_to_stack_type(pdp_type_from_context);
if (pdp_stack != DEFAULT_STACK) { // Accept dual PDP context for IPv4/IPv6 only modems
if (get_modem_stack_type(pdp_stack)) { if (pdp_stack != DEFAULT_STACK && (get_modem_stack_type(pdp_stack) || pdp_stack == IPV4V6_STACK)) {
if (requested_stack == IPV4_STACK) { if (_ip_stack_type_requested == IPV4_STACK) {
if (pdp_stack == IPV4_STACK || pdp_stack == IPV4V6_STACK) { if (pdp_stack == IPV4_STACK || pdp_stack == IPV4V6_STACK) {
_ip_stack_type = requested_stack; _ip_stack_type = _ip_stack_type_requested;
_cid = cid;
break;
}
} else if (_ip_stack_type_requested == IPV6_STACK) {
if (pdp_stack == IPV6_STACK || pdp_stack == IPV4V6_STACK) {
_ip_stack_type = _ip_stack_type_requested;
_cid = cid;
break;
}
} else {
// If dual PDP need to check for IPV4 or IPV6 modem support. Prefer IPv6.
if (pdp_stack == IPV4V6_STACK) {
if (modem_supports_ipv6) {
_ip_stack_type = IPV6_STACK;
_cid = cid;
break;
} else if (modem_supports_ipv4) {
_ip_stack_type = IPV4_STACK;
_cid = cid; _cid = cid;
break; break;
} }
} else if (requested_stack == IPV6_STACK) { // If PDP is IPV4 or IPV6 they are already checked if supported
if (pdp_stack == IPV6_STACK || pdp_stack == IPV4V6_STACK) { } else {
_ip_stack_type = requested_stack; _ip_stack_type = pdp_stack;
_cid = cid; _cid = cid;
if (pdp_stack == IPV6_STACK) {
break; break;
} }
} else { // accept any but prefer to IPv6 if (pdp_stack == IPV4_STACK && !modem_supports_ipv6) {
if (pdp_stack == IPV6_STACK || pdp_stack == IPV4V6_STACK) {
_ip_stack_type = requested_stack;
_cid = cid;
break; break;
} }
if (_ip_stack_type == DEFAULT_STACK) {
_ip_stack_type = pdp_stack;
_cid = cid;
}
} }
} }
} }
@ -424,7 +478,7 @@ bool AT_CellularNetwork::get_context(nsapi_ip_stack_t requested_stack)
} }
_at.resp_stop(); _at.resp_stop();
if (_cid == -1) { // no suitable context was found so create a new one if (_cid == -1) { // no suitable context was found so create a new one
if (!set_new_context(requested_stack, cid_max+1)) { if (!set_new_context(cid_max+1)) {
return false; return false;
} }
} }

View File

@ -139,9 +139,11 @@ private:
void free_credentials(); void free_credentials();
nsapi_error_t open_data_channel(); nsapi_error_t open_data_channel();
bool get_context(nsapi_ip_stack_t supported_stack); bool get_context();
bool set_new_context(nsapi_ip_stack_t stack, int cid); bool set_new_context(int cid);
nsapi_error_t set_registration_urc(bool on); nsapi_error_t set_registration_urc(bool on);
nsapi_error_t delete_current_context();
#if NSAPI_PPP_AVAILABLE #if NSAPI_PPP_AVAILABLE
void ppp_status_cb(nsapi_event_t, intptr_t); void ppp_status_cb(nsapi_event_t, intptr_t);
#endif #endif
@ -161,6 +163,7 @@ protected:
int _cell_id; int _cell_id;
RegistrationType _last_reg_type; RegistrationType _last_reg_type;
nsapi_connection_status_t _connect_status; nsapi_connection_status_t _connect_status;
bool _new_context_set;
}; };
} // namespace mbed } // namespace mbed