Skip to content

Commit cf4118f

Browse files
author
Cruz Monrreal
authored
Merge pull request #10056 from jarvte/context_act_ppp_retry_logic
Cellular: retry logic for CellularContext connect
2 parents 333da46 + c6e5595 commit cf4118f

13 files changed

+198
-52
lines changed

UNITTESTS/stubs/AT_CellularContext_stub.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
using namespace mbed;
2121

2222
AT_CellularContext::AT_CellularContext(ATHandler &at, CellularDevice *device, const char *apn, bool cp_req, bool nonip_req) :
23-
AT_CellularBase(at), _is_blocking(true), _is_connected(false),
24-
_current_op(OP_INVALID), _nw(0), _fh(0), _cp_req(cp_req), _nonip_req(nonip_req), _cp_in_use(false)
23+
AT_CellularBase(at), _is_connected(false),
24+
_current_op(OP_INVALID), _fh(0), _cp_req(cp_req), _nonip_req(nonip_req), _cp_in_use(false)
2525
{
2626
_stack = NULL;
2727
_pdp_type = DEFAULT_PDP_TYPE;
@@ -37,7 +37,12 @@ AT_CellularContext::AT_CellularContext(ATHandler &at, CellularDevice *device, co
3737
_new_context_set = false;
3838
_next = NULL;
3939
_cp_netif = NULL;
40+
memset(_retry_timeout_array, 0, CELLULAR_RETRY_ARRAY_SIZE);
41+
_retry_array_length = 0;
42+
_retry_count = 0;
43+
_is_blocking = true;
4044
_device = device;
45+
_nw = NULL;
4146
}
4247

4348
AT_CellularContext::~AT_CellularContext()
@@ -251,10 +256,6 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr)
251256
{
252257
}
253258

254-
void AT_CellularContext::call_network_cb(nsapi_connection_status_t status)
255-
{
256-
}
257-
258259
ControlPlane_netif *AT_CellularContext::get_cp_netif()
259260
{
260261
return NULL;
@@ -281,3 +282,8 @@ void AT_CellularContext::deactivate_non_ip_context()
281282
void AT_CellularContext::set_disconnect()
282283
{
283284
}
285+
286+
void AT_CellularContext::do_connect_with_retry()
287+
{
288+
289+
}

UNITTESTS/stubs/CellularContext_stub.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) , Arm Limited and affiliates.
2+
* Copyright (c) 2018, Arm Limited and affiliates.
33
* SPDX-License-Identifier: Apache-2.0
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,7 +17,7 @@
1717

1818
#include "CellularContext.h"
1919

20-
using namespace mbed;
20+
namespace mbed {
2121

2222
void CellularContext::cp_data_received()
2323
{
@@ -28,3 +28,25 @@ CellularDevice *CellularContext::get_device() const
2828
{
2929
return _device;
3030
}
31+
32+
void CellularContext::do_connect_with_retry()
33+
{
34+
do_connect();
35+
}
36+
37+
void CellularContext::do_connect()
38+
{
39+
_cb_data.error = NSAPI_ERROR_OK;
40+
}
41+
42+
void CellularContext::call_network_cb(nsapi_connection_status_t status)
43+
{
44+
if (_connect_status != status) {
45+
_connect_status = status;
46+
if (_status_cb) {
47+
_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _connect_status);
48+
}
49+
}
50+
}
51+
52+
}

UNITTESTS/stubs/CellularStateMachine_stub.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,8 @@ void CellularStateMachine::set_cellular_callback(mbed::Callback<void(nsapi_event
7474
void CellularStateMachine::cellular_event_changed(nsapi_event_t ev, intptr_t ptr)
7575
{
7676
}
77+
78+
void CellularStateMachine::get_retry_timeout_array(uint16_t *timeout, int &array_len) const
79+
{
80+
81+
}

UNITTESTS/target_h/myCellularContext.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* limitations under the License.
1616
*/
1717

18-
#include "cellular/framework/API/CellularContext.h"
18+
#include "CellularContext.h"
1919
#include "ControlPlane_netif_stub.h"
2020

2121
namespace mbed {
@@ -186,10 +186,6 @@ class myCellularContext : public CellularContext {
186186
{
187187
};
188188

189-
void call_network_cb(nsapi_connection_status_t status)
190-
{
191-
};
192-
193189
ControlPlane_netif_stub *get_cp_netif()
194190
{
195191
if (!my_cp_netif) {
@@ -219,6 +215,11 @@ class myCellularContext : public CellularContext {
219215
void set_disconnect()
220216
{
221217
};
218+
219+
void do_connect_with_retry()
220+
{
221+
};
222+
222223
};
223224

224225
}

features/cellular/framework/API/CellularContext.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,22 @@ class CellularContext : public CellularInterface {
314314
*/
315315
void cp_data_received();
316316

317+
/** Retry logic after device attached to network. Retry to find and activate pdp context or in case
318+
* of PPP find correct pdp context and open data channel. Retry logic is the same which is used in
319+
* CellularStateMachine.
320+
*/
321+
virtual void do_connect_with_retry();
322+
323+
/** Helper method to call callback function if it is provided
324+
*
325+
* @param status connection status which is parameter in callback function
326+
*/
327+
void call_network_cb(nsapi_connection_status_t status);
328+
329+
/** Find and activate pdp context or in case of PPP find correct pdp context and open data channel.
330+
*/
331+
virtual void do_connect();
332+
317333
// member variables needed in target override methods
318334
NetworkStack *_stack; // must be pointer because of PPP
319335
pdp_type_t _pdp_type;
@@ -332,7 +348,12 @@ class CellularContext : public CellularInterface {
332348
bool _active_high;
333349

334350
ControlPlane_netif *_cp_netif;
351+
uint16_t _retry_timeout_array[CELLULAR_RETRY_ARRAY_SIZE];
352+
int _retry_array_length;
353+
int _retry_count;
335354
CellularDevice *_device;
355+
CellularNetwork *_nw;
356+
bool _is_blocking;
336357
};
337358

338359
/**

features/cellular/framework/API/CellularDevice.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,16 @@ class CellularDevice {
418418
protected:
419419
friend class AT_CellularNetwork;
420420
friend class AT_CellularContext;
421+
friend class CellularContext;
422+
423+
/** Get the retry array from the CellularStateMachine. Array is used in retry logic.
424+
* Array contains seconds and retry logic uses those second to wait before trying again.
425+
*
426+
* @param timeout timeout array containing seconds for retry logic. Must have space for
427+
* CELLULAR_RETRY_ARRAY_SIZE (defined in CellularCommon.h)
428+
* @param array_len length of the timeout array on return
429+
*/
430+
void get_retry_timeout_array(uint16_t *timeout, int &array_len) const;
421431

422432
/** Cellular callback to be attached to Network and CellularStateMachine classes.
423433
* CellularContext calls this when in PPP mode to provide network changes.

features/cellular/framework/AT/AT_CellularContext.cpp

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ using namespace mbed_cellular_util;
4848
using namespace mbed;
4949

5050
AT_CellularContext::AT_CellularContext(ATHandler &at, CellularDevice *device, const char *apn, bool cp_req, bool nonip_req) :
51-
AT_CellularBase(at), _is_connected(false), _is_blocking(true),
52-
_current_op(OP_INVALID), _nw(0), _fh(0), _cp_req(cp_req), _nonip_req(nonip_req), _cp_in_use(false)
51+
AT_CellularBase(at), _is_connected(false), _current_op(OP_INVALID), _fh(0), _cp_req(cp_req),
52+
_nonip_req(nonip_req), _cp_in_use(false)
5353
{
5454
tr_info("New CellularContext %s (%p)", apn ? apn : "", this);
5555
_stack = NULL;
@@ -68,7 +68,12 @@ AT_CellularContext::AT_CellularContext(ATHandler &at, CellularDevice *device, co
6868
_dcd_pin = NC;
6969
_active_high = false;
7070
_cp_netif = NULL;
71+
memset(_retry_timeout_array, 0, CELLULAR_RETRY_ARRAY_SIZE);
72+
_retry_array_length = 0;
73+
_retry_count = 0;
74+
_is_blocking = true;
7175
_device = device;
76+
_nw = NULL;
7277
}
7378

7479
AT_CellularContext::~AT_CellularContext()
@@ -119,6 +124,11 @@ AT_CellularDevice *AT_CellularContext::get_device() const
119124
return static_cast<AT_CellularDevice *>(CellularContext::get_device());
120125
}
121126

127+
void AT_CellularContext::do_connect_with_retry()
128+
{
129+
CellularContext::do_connect_with_retry();
130+
}
131+
122132
nsapi_error_t AT_CellularContext::connect()
123133
{
124134
tr_info("CellularContext connect");
@@ -129,15 +139,15 @@ nsapi_error_t AT_CellularContext::connect()
129139

130140
nsapi_error_t err = _device->attach_to_network();
131141
_cb_data.error = check_operation(err, OP_CONNECT);
132-
142+
_retry_count = 0;
133143
if (_is_blocking) {
134144
if (_cb_data.error == NSAPI_ERROR_OK || _cb_data.error == NSAPI_ERROR_ALREADY) {
135-
do_connect();
145+
do_connect_with_retry();
136146
}
137147
} else {
138148
if (_cb_data.error == NSAPI_ERROR_ALREADY) {
139149
// device is already attached, to be async we must use queue to connect and give proper callbacks
140-
int id = _device->get_queue()->call_in(0, this, &AT_CellularContext::do_connect);
150+
int id = _device->get_queue()->call_in(0, this, &AT_CellularContext::do_connect_with_retry);
141151
if (id == 0) {
142152
return NSAPI_ERROR_NO_MEMORY;
143153
}
@@ -580,8 +590,6 @@ void AT_CellularContext::do_connect()
580590
_cb_data.error = open_data_channel();
581591
_at.unlock();
582592
if (_cb_data.error != NSAPI_ERROR_OK) {
583-
tr_error("Failed to open data channel!");
584-
call_network_cb(NSAPI_STATUS_DISCONNECTED);
585593
_is_connected = false;
586594
} else {
587595
_is_context_activated = true;
@@ -970,7 +978,8 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr)
970978
if (_status_cb) {
971979
_status_cb(ev, ptr);
972980
}
973-
do_connect();
981+
_retry_count = 0;
982+
do_connect_with_retry();
974983
return;
975984
}
976985
}
@@ -1000,19 +1009,6 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr)
10001009
}
10011010
}
10021011

1003-
void AT_CellularContext::call_network_cb(nsapi_connection_status_t status)
1004-
{
1005-
if (_connect_status != status) {
1006-
_connect_status = status;
1007-
if (_status_cb) {
1008-
_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _connect_status);
1009-
}
1010-
if (_nw && _connect_status == NSAPI_STATUS_DISCONNECTED) {
1011-
tr_info("CellularContext disconnected");
1012-
}
1013-
}
1014-
}
1015-
10161012
ControlPlane_netif *AT_CellularContext::get_cp_netif()
10171013
{
10181014
tr_error("No control plane interface available from base context!");

features/cellular/framework/AT/AT_CellularContext.h

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,6 @@ class AT_CellularContext : public CellularContext, public AT_CellularBase {
9393
*/
9494
virtual uint32_t get_timeout_for_operation(ContextOperation op) const;
9595

96-
/** Helper method to call callback function if it is provided
97-
*
98-
* @param status connection status which is parameter in callback function
99-
*/
100-
void call_network_cb(nsapi_connection_status_t status);
101-
10296
virtual nsapi_error_t activate_non_ip_context();
10397
virtual nsapi_error_t setup_control_plane_opt();
10498
virtual void deactivate_non_ip_context();
@@ -123,13 +117,11 @@ class AT_CellularContext : public CellularContext, public AT_CellularBase {
123117
nsapi_error_t check_operation(nsapi_error_t err, ContextOperation op);
124118
AT_CellularBase::CellularProperty pdp_type_t_to_cellular_property(pdp_type_t pdp_type);
125119
void ciot_opt_cb(mbed::CellularNetwork::CIoT_Supported_Opt ciot_opt);
126-
120+
virtual void do_connect_with_retry();
127121
private:
128122
bool _is_connected;
129-
bool _is_blocking;
130123
ContextOperation _current_op;
131124
char _found_apn[MAX_APN_LENGTH];
132-
CellularNetwork *_nw;
133125
FileHandle *_fh;
134126
rtos::Semaphore _semaphore;
135127
rtos::Semaphore _cp_opt_semaphore;

features/cellular/framework/common/CellularCommon.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include <stdint.h>
2222
#include "nsapi_types.h"
2323

24+
const int CELLULAR_RETRY_ARRAY_SIZE = 10;
25+
2426
struct cell_callback_data_t {
2527
nsapi_error_t error; /* possible error code */
2628
int status_data; /* cellular_event_status related enum or other info in int format. Check cellular_event_status comments.*/

features/cellular/framework/device/CellularContext.cpp

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
* limitations under the License.
1616
*/
1717
#include "CellularContext.h"
18+
#include "CellularLog.h"
19+
#include "ThisThread.h"
1820

1921
MBED_WEAK CellularInterface *CellularInterface::get_target_default_instance()
2022
{
@@ -66,4 +68,79 @@ CellularDevice *CellularContext::get_device() const
6668
return _device;
6769
}
6870

71+
void CellularContext::do_connect_with_retry()
72+
{
73+
do_connect();
74+
if (_cb_data.error == NSAPI_ERROR_OK) {
75+
return;
76+
}
77+
78+
if (_retry_count == 0) {
79+
_device->get_retry_timeout_array(_retry_timeout_array, _retry_array_length);
80+
}
81+
82+
if (_is_blocking) {
83+
while (_retry_count < _retry_array_length) {
84+
tr_debug("SYNC do_connect failed with %d, retry after %d seconds", _cb_data.error, _retry_timeout_array[_retry_count]);
85+
rtos::ThisThread::sleep_for(_retry_timeout_array[_retry_count] * 1000);
86+
do_connect();
87+
if (_cb_data.error == NSAPI_ERROR_OK) {
88+
return;
89+
}
90+
_retry_count++;
91+
}
92+
} else {
93+
if (_retry_count < _retry_array_length) {
94+
if (_retry_count == _retry_array_length - 1) {
95+
// set the flag that this is the last try for ppp connect / pdp context activate
96+
_cb_data.final_try = true;
97+
}
98+
tr_debug("ASYNC do_connect failed with %d, retry after %d seconds", _cb_data.error, _retry_timeout_array[_retry_count]);
99+
int id = _device->get_queue()->call_in(_retry_timeout_array[_retry_count] * 1000, this, &CellularContext::do_connect_with_retry);
100+
if (id == 0) {
101+
tr_error("Failed call via eventqueue in do_connect_with_retry()");
102+
#if !NSAPI_PPP_AVAILABLE
103+
_cb_data.final_try = true;
104+
_cb_data.error = NSAPI_ERROR_NO_MEMORY;
105+
// in PPP mode we did not activate any context, just searched the correct _cid
106+
if (_status_cb) {
107+
_status_cb((nsapi_event_t)CellularActivatePDPContext, (intptr_t)&_cb_data);
108+
}
109+
_cb_data.final_try = false;
110+
_cb_data.error = NSAPI_ERROR_OK;
111+
#else
112+
call_network_cb(NSAPI_STATUS_DISCONNECTED);
113+
#endif // !NSAPI_PPP_AVAILABLE
114+
}
115+
_retry_count++;
116+
return; // don't call NSAPI_STATUS_DISCONNECTED in every failure, only the last one.
117+
}
118+
}
119+
120+
#if NSAPI_PPP_AVAILABLE
121+
if (_cb_data.error != NSAPI_ERROR_OK) {
122+
tr_error("Failed to open data channel!");
123+
call_network_cb(NSAPI_STATUS_DISCONNECTED);
124+
}
125+
#endif // #if NSAPI_PPP_AVAILABLE
126+
}
127+
128+
void CellularContext::do_connect()
129+
{
130+
_cb_data.error = NSAPI_ERROR_OK;
131+
}
132+
133+
void CellularContext::call_network_cb(nsapi_connection_status_t status)
134+
{
135+
if (_connect_status != status) {
136+
_connect_status = status;
137+
if (_status_cb) {
138+
_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _connect_status);
139+
}
140+
if (_nw && _connect_status == NSAPI_STATUS_DISCONNECTED) {
141+
tr_info("CellularContext disconnected");
142+
}
143+
}
144+
}
145+
69146
} // namespace mbed

0 commit comments

Comments
 (0)