Skip to content

Commit 66c39e0

Browse files
authored
Merge pull request #11424 from mirelachirica/stack_type_ip_versions
Stack type ip versions
2 parents 01bb1b9 + 78f4e8b commit 66c39e0

File tree

9 files changed

+85
-27
lines changed

9 files changed

+85
-27
lines changed

UNITTESTS/stubs/CellularUtil_stub.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ uint16_t char_str_to_hex(const char *str, uint16_t len, char *buf, bool omit_lea
5151
return CellularUtil_stub::uint16_value;
5252
}
5353

54-
void convert_ipv6(char *ip)
54+
nsapi_version_t convert_ipv6(char *ip)
5555
{
56-
56+
return NSAPI_UNSPEC;
5757
}
5858

5959
char *find_dot_number(char *str, int dot_number)

features/cellular/framework/AT/AT_CellularBase.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class AT_CellularBase {
6060
PROPERTY_AT_CSDH, // 0 = not supported, 1 = supported. Show text mode AT command
6161
PROPERTY_IPV4_PDP_TYPE, // 0 = not supported, 1 = supported. Does modem support IPV4?
6262
PROPERTY_IPV6_PDP_TYPE, // 0 = not supported, 1 = supported. Does modem support IPV6?
63-
PROPERTY_IPV4V6_PDP_TYPE, // 0 = not supported, 1 = supported. Does modem support dual stack IPV4V6?
63+
PROPERTY_IPV4V6_PDP_TYPE, // 0 = not supported, 1 = supported. Does modem support IPV4 and IPV6 simultaneously?
6464
PROPERTY_NON_IP_PDP_TYPE, // 0 = not supported, 1 = supported. Does modem support Non-IP?
6565
PROPERTY_AT_CGEREP, // 0 = not supported, 1 = supported. Does modem support AT command AT+CGEREP.
6666

features/cellular/framework/AT/AT_CellularContext.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -369,8 +369,9 @@ bool AT_CellularContext::get_context()
369369
// APN matched -> Check PDP type
370370
pdp_type_t pdp_type = string_to_pdp_type(pdp_type_from_context);
371371

372-
// Accept exact matching PDP context type
373-
if (get_property(pdp_type_t_to_cellular_property(pdp_type))) {
372+
// Accept exact matching PDP context type or dual PDP context for modems that support both IPv4 and IPv6 stacks
373+
if (get_property(pdp_type_t_to_cellular_property(pdp_type)) ||
374+
((pdp_type == IPV4V6_PDP_TYPE && (get_property(PROPERTY_IPV4_PDP_TYPE) && get_property(PROPERTY_IPV6_PDP_TYPE))) && !_nonip_req)) {
374375
_pdp_type = pdp_type;
375376
_cid = cid;
376377
}
@@ -403,7 +404,7 @@ bool AT_CellularContext::set_new_context(int cid)
403404
if (_nonip_req && _cp_in_use && get_property(PROPERTY_NON_IP_PDP_TYPE)) {
404405
strncpy(pdp_type_str, "Non-IP", sizeof(pdp_type_str));
405406
pdp_type = NON_IP_PDP_TYPE;
406-
} else if (get_property(PROPERTY_IPV4V6_PDP_TYPE)) {
407+
} else if (get_property(PROPERTY_IPV4V6_PDP_TYPE) || (get_property(PROPERTY_IPV4_PDP_TYPE) && get_property(PROPERTY_IPV6_PDP_TYPE))) {
407408
strncpy(pdp_type_str, "IPV4V6", sizeof(pdp_type_str));
408409
pdp_type = IPV4V6_PDP_TYPE;
409410
} else if (get_property(PROPERTY_IPV6_PDP_TYPE)) {

features/cellular/framework/AT/AT_CellularStack.cpp

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
using namespace mbed_cellular_util;
2424
using namespace mbed;
2525

26-
AT_CellularStack::AT_CellularStack(ATHandler &at, int cid, nsapi_ip_stack_t stack_type) : AT_CellularBase(at), _socket(NULL), _socket_count(0), _cid(cid), _stack_type(stack_type)
26+
AT_CellularStack::AT_CellularStack(ATHandler &at, int cid, nsapi_ip_stack_t stack_type) : AT_CellularBase(at), _socket(NULL), _socket_count(0), _cid(cid), _stack_type(stack_type), _ip_ver_sendto(NSAPI_UNSPEC)
2727
{
2828
memset(_ip, 0, PDP_IPV6_SIZE);
2929
}
@@ -59,27 +59,43 @@ const char *AT_CellularStack::get_ip_address()
5959
{
6060
_at.lock();
6161

62+
bool ipv4 = false, ipv6 = false;
63+
6264
_at.cmd_start_stop("+CGPADDR", "=", "%d", _cid);
6365
_at.resp_start("+CGPADDR:");
6466

65-
int len = -1;
6667
if (_at.info_resp()) {
6768
_at.skip_param();
6869

69-
len = _at.read_string(_ip, PDP_IPV6_SIZE);
70-
71-
if (len != -1 && _stack_type != IPV4_STACK) {
72-
// in case stack type is not IPV4 only, try to look also for IPV6 address
73-
(void)_at.read_string(_ip, PDP_IPV6_SIZE);
70+
if (_at.read_string(_ip, PDP_IPV6_SIZE) != -1) {
71+
convert_ipv6(_ip);
72+
SocketAddress address;
73+
address.set_ip_address(_ip);
74+
75+
ipv4 = (address.get_ip_version() == NSAPI_IPv4);
76+
ipv6 = (address.get_ip_version() == NSAPI_IPv6);
77+
78+
// Try to look for second address ONLY if modem has support for dual stack(can handle both IPv4 and IPv6 simultaneously).
79+
// Otherwise assumption is that second address is not reliable, even if network provides one.
80+
if ((get_property(PROPERTY_IPV4V6_PDP_TYPE) && (_at.read_string(_ip, PDP_IPV6_SIZE) != -1))) {
81+
convert_ipv6(_ip);
82+
address.set_ip_address(_ip);
83+
ipv6 = (address.get_ip_version() == NSAPI_IPv6);
84+
}
7485
}
7586
}
7687
_at.resp_stop();
7788
_at.unlock();
7889

79-
// we have at least IPV4 address
80-
convert_ipv6(_ip);
90+
if (ipv4 && ipv6) {
91+
_stack_type = IPV4V6_STACK;
92+
} else if (ipv4) {
93+
_stack_type = IPV4_STACK;
94+
} else if (ipv6) {
95+
_stack_type = IPV6_STACK;
96+
}
8197

82-
return len != -1 ? _ip : NULL;
98+
return (ipv4 || ipv6) ? _ip : NULL;
8399
}
84100

85101
nsapi_error_t AT_CellularStack::socket_stack_init()
@@ -256,6 +272,13 @@ nsapi_size_or_error_t AT_CellularStack::socket_sendto(nsapi_socket_t handle, con
256272
nsapi_size_or_error_t ret_val = NSAPI_ERROR_OK;
257273

258274
if (socket->id == -1) {
275+
276+
/* Check that stack type supports sendto address type*/
277+
if (!is_addr_stack_compatible(addr)) {
278+
return NSAPI_ERROR_PARAMETER;
279+
}
280+
281+
_ip_ver_sendto = addr.get_ip_version();
259282
_at.lock();
260283

261284
ret_val = create_socket_impl(socket);
@@ -267,9 +290,9 @@ nsapi_size_or_error_t AT_CellularStack::socket_sendto(nsapi_socket_t handle, con
267290
}
268291
}
269292

270-
/* Check parameters */
271-
if (addr.get_ip_version() == NSAPI_UNSPEC) {
272-
return NSAPI_ERROR_DEVICE_ERROR;
293+
/* Check parameters - sendto address is valid and stack type supports sending to that address type*/
294+
if (!is_addr_stack_compatible(addr)) {
295+
return NSAPI_ERROR_PARAMETER;
273296
}
274297

275298
_at.lock();
@@ -377,3 +400,14 @@ AT_CellularStack::CellularSocket *AT_CellularStack::find_socket(int sock_id)
377400
}
378401
return sock;
379402
}
403+
404+
bool AT_CellularStack::is_addr_stack_compatible(const SocketAddress &addr)
405+
{
406+
if ((addr.get_ip_version() == NSAPI_UNSPEC) ||
407+
(addr.get_ip_version() == NSAPI_IPv4 && _stack_type == IPV6_STACK) ||
408+
(addr.get_ip_version() == NSAPI_IPv6 && _stack_type == IPV4_STACK)) {
409+
return false;
410+
}
411+
return true;
412+
}
413+

features/cellular/framework/AT/AT_CellularStack.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@ class AT_CellularStack : public NetworkStack, public AT_CellularBase {
192192
*/
193193
int find_socket_index(nsapi_socket_t handle);
194194

195+
/**
196+
* Checks if send to address is valid and if current stack type supports sending to that address type
197+
*/
198+
bool is_addr_stack_compatible(const SocketAddress &addr);
199+
195200
// socket container
196201
CellularSocket **_socket;
197202

@@ -204,9 +209,12 @@ class AT_CellularStack : public NetworkStack, public AT_CellularBase {
204209
// PDP context id
205210
int _cid;
206211

207-
// stack type from PDP context
212+
// stack type - initialised as PDP type and set accordingly after CGPADDR checked
208213
nsapi_ip_stack_t _stack_type;
209214

215+
// IP version of send to address
216+
nsapi_version_t _ip_ver_sendto;
217+
210218
private:
211219

212220
int get_socket_index_by_port(uint16_t port);

features/cellular/framework/common/CellularUtil.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@
2828
using namespace mbed;
2929
namespace mbed_cellular_util {
3030

31-
void convert_ipv6(char *ip)
31+
nsapi_version_t convert_ipv6(char *ip)
3232
{
3333
if (!ip) {
34-
return;
34+
return NSAPI_UNSPEC;
3535
}
3636

3737
int len = strlen(ip);
@@ -49,7 +49,11 @@ void convert_ipv6(char *ip)
4949

5050
// more that 3 periods mean that it was ipv6 but in format of a1.a2.a3.a4.a5.a6.a7.a8.a9.a10.a11.a12.a13.a14.a15.a16
5151
// we need to convert it to hexadecimal format separated with colons
52-
if (pos > 3) {
52+
if (pos == 3) {
53+
54+
return NSAPI_IPv4;
55+
56+
} else if (pos > 3) {
5357
pos = 0;
5458
int ip_pos = 0;
5559
char b;
@@ -74,7 +78,11 @@ void convert_ipv6(char *ip)
7478
ip[pos] = '\0';
7579
}
7680
}
81+
82+
return NSAPI_IPv6;
7783
}
84+
85+
return NSAPI_UNSPEC;
7886
}
7987

8088
// For example "32.1.13.184.0.0.205.48.0.0.0.0.0.0.0.0"

features/cellular/framework/common/CellularUtil.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,9 @@ static const char hex_values[] = "0123456789ABCDEF";
4848
* where ax are in decimal format. In this case, function converts decimals to hex with separated with colons.
4949
*
5050
* @param ip IP address that can be IPv4 or IPv6 in different formats from AT command +CGPADDR. Converted result uses same buffer.
51+
* @return IP version of the address or NSAPI_UNSPEC if param ip empty or if IPv4 or IPv6 version could not be concluded.
5152
*/
52-
void convert_ipv6(char *ip);
53+
nsapi_version_t convert_ipv6(char *ip);
5354

5455
/** Separates IP addresses from the given 'orig' string. 'orig' may contain zero, one or two IP addresses in various formats.
5556
* See AT command +CGPIAF from 3GPP TS 27.007 for details. Does also needed conversions for IPv6 addresses.

features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ static const intptr_t cellular_properties[AT_CellularBase::PROPERTY_MAX] = {
5757
1, // AT_CMGF
5858
1, // AT_CSDH
5959
1, // PROPERTY_IPV4_STACK
60-
0, // PROPERTY_IPV6_STACK
60+
1, // PROPERTY_IPV6_STACK
6161
0, // PROPERTY_IPV4V6_STACK
6262
1, // PROPERTY_NON_IP_PDP_TYPE
6363
1, // PROPERTY_AT_CGEREP

features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularStack.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ nsapi_error_t QUECTEL_BG96_CellularStack::create_socket_impl(CellularSocket *soc
212212

213213
if (socket->proto == NSAPI_UDP && !socket->connected) {
214214
_at.at_cmd_discard("+QIOPEN", "=", "%d%d%s%s%d%d%d", _cid, request_connect_id, "UDP SERVICE",
215-
(_stack_type == IPV4_STACK) ? "127.0.0.1" : "0:0:0:0:0:0:0:1",
215+
(_ip_ver_sendto == NSAPI_IPv4) ? "127.0.0.1" : "0:0:0:0:0:0:0:1",
216216
remote_port, socket->localAddress.get_port(), 0);
217217

218218
handle_open_socket_response(modem_connect_id, err);
@@ -225,7 +225,7 @@ nsapi_error_t QUECTEL_BG96_CellularStack::create_socket_impl(CellularSocket *soc
225225
socket_close_impl(modem_connect_id);
226226

227227
_at.at_cmd_discard("+QIOPEN", "=", "%d%d%s%s%d%d%d", _cid, request_connect_id, "UDP SERVICE",
228-
(_stack_type == IPV4_STACK) ? "127.0.0.1" : "0:0:0:0:0:0:0:1",
228+
(_ip_ver_sendto == NSAPI_IPv4) ? "127.0.0.1" : "0:0:0:0:0:0:0:1",
229229
remote_port, socket->localAddress.get_port(), 0);
230230

231231
handle_open_socket_response(modem_connect_id, err);
@@ -273,6 +273,12 @@ nsapi_size_or_error_t QUECTEL_BG96_CellularStack::socket_sendto_impl(CellularSoc
273273
return NSAPI_ERROR_PARAMETER;
274274
}
275275

276+
if (_ip_ver_sendto != address.get_ip_version()) {
277+
_ip_ver_sendto = address.get_ip_version();
278+
socket_close_impl(socket->id);
279+
create_socket_impl(socket);
280+
}
281+
276282
int sent_len = 0;
277283
int sent_len_before = 0;
278284
int sent_len_after = 0;

0 commit comments

Comments
 (0)