Skip to content

Commit

Permalink
Cellular: notify global up after we have IP address
Browse files Browse the repository at this point in the history
CellularContext now tries to get an IP address after connect and before
sending NSAPI_STATUS_GLOBAL_UP. Even if we don't the IP address from
the modem we will send NSAPI_STATUS_GLOBAL_UP and return success.
Modem has an ip address but for some reason some modems don't
give it to us.
  • Loading branch information
Teppo Järvelin committed Aug 14, 2019
1 parent ce36104 commit 2ebc648
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ TEST_F(TestAT_CellularContext, connect_disconnect_sync)
ATHandler_stub::read_string_index = 2;
ASSERT_EQ(ctx1.connect(), NSAPI_ERROR_OK);

ASSERT_EQ(network_cb_count, 5);
ASSERT_EQ(network_cb_count, 4);

ASSERT_EQ(ctx1.disconnect(), NSAPI_ERROR_OK);
ATHandler_stub::resp_info_true_counter = 1;
Expand Down Expand Up @@ -704,7 +704,7 @@ TEST_F(TestAT_CellularContext, connect_disconnect_async)
data.status_data = CellularNetwork::Attached;
ctx1.cellular_callback((nsapi_event_t)CellularAttachNetwork, (intptr_t)&data);

ASSERT_EQ(network_cb_count, 5);
ASSERT_EQ(network_cb_count, 4);
ASSERT_EQ(ctx1.connect(), NSAPI_ERROR_IS_CONNECTED);
EXPECT_TRUE(ctx1.is_connected() == true);
ASSERT_EQ(ctx1.disconnect(), NSAPI_ERROR_NO_MEMORY);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_get_ip_address)
ATHandler at(&fh1, que, 0, ",");

MyStack st(at, 0, IPV6_STACK);
EXPECT_EQ(strlen(st.get_ip_address()), 0);
EXPECT_TRUE(st.get_ip_address() == NULL);

char table[] = "1.2.3.4.5.65.7.8.9.10.11\0";
ATHandler_stub::ssize_value = -1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ set(unittest-test-sources
stubs/NetworkStack_stub.cpp
stubs/SocketAddress_stub.cpp
stubs/mbed_assert_stub.c
stubs/ThisThread_stub.cpp
)
9 changes: 9 additions & 0 deletions features/cellular/framework/API/CellularContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,11 @@ class CellularContext : public CellularInterface {
*/
virtual void do_connect();

/** After we have connected successfully we must check that we have a valid IP address.
* Some modems/networks don't give IP address right after connect so we must poll it for a while.
*/
void validate_ip_address();

// member variables needed in target override methods
NetworkStack *_stack; // must be pointer because of PPP
pdp_type_t _pdp_type;
Expand All @@ -368,6 +373,10 @@ class CellularContext : public CellularInterface {
CellularDevice *_device;
CellularNetwork *_nw;
bool _is_blocking;
// flag indicating if Non-IP context was requested to be setup
bool _nonip_req;
// tells if CCIOTOPTI received green from network for CP optimization use
bool _cp_in_use;
};

/**
Expand Down
5 changes: 2 additions & 3 deletions features/cellular/framework/AT/AT_CellularContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ using namespace mbed;
using namespace rtos;

AT_CellularContext::AT_CellularContext(ATHandler &at, CellularDevice *device, const char *apn, bool cp_req, bool nonip_req) :
AT_CellularBase(at), _is_connected(false), _current_op(OP_INVALID), _fh(0), _cp_req(cp_req),
_nonip_req(nonip_req), _cp_in_use(false)
AT_CellularBase(at), _is_connected(false), _current_op(OP_INVALID), _fh(0), _cp_req(cp_req)
{
tr_info("New CellularContext %s (%p)", apn ? apn : "", this);
_nonip_req = nonip_req;
_apn = apn;
_device = device;
}
Expand Down Expand Up @@ -587,7 +587,6 @@ void AT_CellularContext::do_connect()
}
#else
_is_connected = true;
call_network_cb(NSAPI_STATUS_GLOBAL_UP);
#endif
}

Expand Down
4 changes: 0 additions & 4 deletions features/cellular/framework/AT/AT_CellularContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,6 @@ class AT_CellularContext : public CellularContext, public AT_CellularBase {
char _found_apn[MAX_APN_LENGTH];
// flag indicating if CP was requested to be setup
bool _cp_req;
// flag indicating if Non-IP context was requested to be setup
bool _nonip_req;
// tells if CCIOTOPTI received green from network for CP optimization use
bool _cp_in_use;
};

} // namespace mbed
Expand Down
21 changes: 6 additions & 15 deletions features/cellular/framework/AT/AT_CellularStack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "AT_CellularStack.h"
#include "CellularUtil.h"
#include "CellularLog.h"
#include "ThisThread.h"

using namespace mbed_cellular_util;
using namespace mbed;
Expand Down Expand Up @@ -54,41 +55,31 @@ int AT_CellularStack::find_socket_index(nsapi_socket_t handle)

/** NetworkStack
*/

const char *AT_CellularStack::get_ip_address()
{
_at.lock();

_at.cmd_start_stop("+CGPADDR", "=", "%d", _cid);

_at.resp_start("+CGPADDR:");

int len = -1;
if (_at.info_resp()) {

_at.skip_param();

int len = _at.read_string(_ip, NSAPI_IPv4_SIZE);
if (len == -1) {
_ip[0] = '\0';
_at.resp_stop();
_at.unlock();
// no IPV4 address, return
return NULL;
}
len = _at.read_string(_ip, NSAPI_IPv4_SIZE);

// in case stack type is not IPV4 only, try to look also for IPV6 address
if (_stack_type != IPV4_STACK) {
if (len != -1 && _stack_type != IPV4_STACK) {
// in case stack type is not IPV4 only, try to look also for IPV6 address
(void)_at.read_string(_ip, PDP_IPV6_SIZE);
}
}

_at.resp_stop();
_at.unlock();

// we have at least IPV4 address
convert_ipv6(_ip);

return _ip;
return len != -1 ? _ip : NULL;
}

nsapi_error_t AT_CellularStack::socket_stack_init()
Expand Down
30 changes: 29 additions & 1 deletion features/cellular/framework/device/CellularContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ CellularContext::CellularContext() : _next(0), _stack(0), _pdp_type(DEFAULT_PDP_
_authentication_type(CellularContext::CHAP), _connect_status(NSAPI_STATUS_DISCONNECTED), _status_cb(0),
_cid(-1), _new_context_set(false), _is_context_active(false), _is_context_activated(false),
_apn(0), _uname(0), _pwd(0), _dcd_pin(NC), _active_high(false), _cp_netif(0), _retry_array_length(0),
_retry_count(0), _device(0), _nw(0), _is_blocking(true)
_retry_count(0), _device(0), _nw(0), _is_blocking(true), _nonip_req(false), _cp_in_use(false)
{
memset(_retry_timeout_array, 0, CELLULAR_RETRY_ARRAY_SIZE);
}
Expand All @@ -87,6 +87,28 @@ void CellularContext::set_authentication_type(AuthenticationType type)
_authentication_type = type;
}

void CellularContext::validate_ip_address()
{
const int IP_MAX_TRIES = 10; // maximum of 2 seconds as we wait 200ms between tries
const int IP_WAIT_INTERVAL = 200; // 200 ms between retries
const char *ip = NULL;
int i = 0;

while (1) {
ip = get_ip_address();
if (ip || i >= IP_MAX_TRIES) {
if (ip == NULL) {
tr_warning("Connected but no local ip address");
} else {
tr_info("Cellular local IP: %s", ip);
}
break;
}
rtos::ThisThread::sleep_for(IP_WAIT_INTERVAL);
i++;
}
}

void CellularContext::do_connect_with_retry()
{
if (_cb_data.final_try) {
Expand All @@ -97,6 +119,12 @@ void CellularContext::do_connect_with_retry()
}
do_connect();
if (_cb_data.error == NSAPI_ERROR_OK) {
// Some modems don't get the ip address right after connect so we must
// validate it but even if we don't get ip we still send NSAPI_STATUS_GLOBAL_UP
if (!_nonip_req && !_cp_in_use) { // don't validate if non-ip case
validate_ip_address();
}
call_network_cb(NSAPI_STATUS_GLOBAL_UP);
return;
}

Expand Down

0 comments on commit 2ebc648

Please sign in to comment.