Skip to content

Commit 16621bc

Browse files
eivindj-nordicrlubos
authored andcommitted
lib: pdn: decrease stack and heap for pdn_dynamic_info_get()
Decrease stack requirements for pdn_dynamic_info_get(). Remove use of k_malloc(). Add use of pdn_dynamic_info_get() to PDN sample and add tests. Signed-off-by: Eivind Jølsgard <[email protected]>
1 parent c98b56e commit 16621bc

File tree

7 files changed

+356
-161
lines changed

7 files changed

+356
-161
lines changed

doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,10 @@ Cellular samples
346346

347347
* Fixed an issue with devicetree configuration after HCI updates in `sdk-zephyr`_.
348348

349+
* :ref:`pdn_sample` sample:
350+
351+
* Added dynamic PDN information.
352+
349353
Cryptography samples
350354
--------------------
351355

@@ -559,7 +563,6 @@ Modem libraries
559563

560564
* :ref:`pdn_readme` library:
561565

562-
* Added the :kconfig:option:`CONFIG_PDN_DYNAMIC_INFO_AT_BUF_SIZE ` Kconfig option to set the response buffer size for the ``AT+CGCONTRDP`` AT command.
563566
* Deprecated the :c:func:`pdn_dynamic_params_get` function.
564567
Use the new function :c:func:`pdn_dynamic_info_get` instead.
565568

include/modem/pdn.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ __deprecated int pdn_dynamic_params_get(uint8_t cid, struct in_addr *dns4_pri,
243243
*
244244
* @return Zero on success or an error code on failure.
245245
*/
246-
int pdn_dynamic_info_get(uint32_t cid, struct pdn_dynamic_info *pdn_info);
246+
int pdn_dynamic_info_get(uint8_t cid, struct pdn_dynamic_info *pdn_info);
247247

248248
/**
249249
* @brief Retrieve the default Access Point Name (APN).

lib/pdn/Kconfig

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,6 @@ config PDN_INIT_PRIORITY
2727
int "Initialization priority"
2828
default APPLICATION_INIT_PRIORITY
2929

30-
config PDN_DYNAMIC_INFO_AT_BUF_SIZE
31-
int "Dynamic info AT buffer size"
32-
default 512
33-
help
34-
Buffer size for storing the response of the AT+CGCONTRDP AT command used in the
35-
pdn_dynamic_info_get() function.
36-
3730
config PDN_DEFAULTS_OVERRIDE
3831
bool "Override defaults for PDP context 0"
3932
help

lib/pdn/pdn.c

Lines changed: 64 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
#include <zephyr/net/socket.h>
1616
#include <zephyr/sys/slist.h>
1717
#include <zephyr/logging/log.h>
18-
#include <zephyr/posix/arpa/inet.h>
1918
#include <nrf_modem_at.h>
2019
#include <modem/pdn.h>
2120
#include <modem/at_monitor.h>
@@ -36,15 +35,22 @@ LOG_MODULE_REGISTER(pdn, CONFIG_PDN_LOG_LEVEL);
3635
#define MODEM_CFUN_NORMAL 1
3736
#define MODEM_CFUN_ACTIVATE_LTE 21
3837

39-
#define AT_CMD_PDN_CONTEXT_READ_IP_ADDR_STR_MAX_LEN (255)
40-
41-
#define AT_CMD_PDN_CONTEXT_READ_INFO "AT+CGCONTRDP=%d"
38+
#define AT_CMD_PDN_CONTEXT_READ_INFO "AT+CGCONTRDP=%u"
4239
#define AT_CMD_PDN_CONTEXT_READ_INFO_DNS_ADDR_PRIMARY_INDEX 6
4340
#define AT_CMD_PDN_CONTEXT_READ_INFO_DNS_ADDR_SECONDARY_INDEX 7
4441
#define AT_CMD_PDN_CONTEXT_READ_INFO_MTU_INDEX 12
4542

4643
#define AT_CMD_PDN_CONTEXT_READ_RSP_DELIM "\r\n"
4744

45+
/* "+CGCONTRDP: 0,,"example.com","","","198.276.154.230","12.34.56.78",,,,,1464\r\n
46+
* +CGCONTRDP: 0,,"example.com","","","1111:2222:3:FFF::55","1111:2222:3:FFF::55",,,,,1464"
47+
*/
48+
#define AT_CMD_PDN_CONTEXT_READ_INFO_PARSE_LINE1 \
49+
"+CGCONTRDP: %*u,,\"%*[^\"]\",\"\",\"\",\"%15[0-9.]\",\"%15[0-9.]\",,,,,%u"
50+
#define AT_CMD_PDN_CONTEXT_READ_INFO_PARSE_LINE2 \
51+
"+%*[^+]"\
52+
"+CGCONTRDP: %*u,,\"%*[^\"]\",\"\",\"\",\"%39[0-9A-Fa-f:]\",\"%39[0-9A-Fa-f:]\",,,,,%u"
53+
4854
static K_MUTEX_DEFINE(list_mutex);
4955

5056
static sys_slist_t pdn_contexts = SYS_SLIST_STATIC_INIT(&pdn_context);
@@ -633,13 +639,13 @@ int pdn_dynamic_params_get(uint8_t cid, struct in_addr *dns4_pri,
633639
unsigned int mtu;
634640
char dns4_pri_str[INET_ADDRSTRLEN];
635641
char dns4_sec_str[INET_ADDRSTRLEN];
636-
char at_cmd[sizeof("AT+CGCONTRDP=10")];
642+
char at_cmd[sizeof("AT+CGCONTRDP=###")];
637643

638-
if (snprintf(at_cmd, sizeof(at_cmd), "AT+CGCONTRDP=%u", cid) >= sizeof(at_cmd)) {
644+
if (snprintf(at_cmd, sizeof(at_cmd), AT_CMD_PDN_CONTEXT_READ_INFO, cid) >= sizeof(at_cmd)) {
639645
return -E2BIG;
640646
}
641-
/* "+CGCONTRDP: 0,,"example.com","","","198.276.154.230","12.34.56.78",,,,,1464" */
642-
fmt = "+CGCONTRDP: %*u,,\"%*[^\"]\",\"\",\"\",\"%15[0-9.]\",\"%15[0-9.]\",,,,,%u";
647+
648+
fmt = AT_CMD_PDN_CONTEXT_READ_INFO_PARSE_LINE1;
643649

644650
/* If IPv4 is enabled, it will be the first response line. */
645651
matched = nrf_modem_at_scanf(at_cmd, fmt, &dns4_pri_str, &dns4_sec_str, &mtu);
@@ -674,153 +680,79 @@ static int pdn_sa_family_from_ip_string(const char *src)
674680
{
675681
char buf[INET6_ADDRSTRLEN];
676682

677-
if (inet_pton(AF_INET, src, buf)) {
683+
if (zsock_inet_pton(AF_INET, src, buf)) {
678684
return AF_INET;
679-
} else if (inet_pton(AF_INET6, src, buf)) {
685+
} else if (zsock_inet_pton(AF_INET6, src, buf)) {
680686
return AF_INET6;
681687
}
682688
return -1;
683689
}
684690

685-
int pdn_dynamic_info_get(uint32_t cid, struct pdn_dynamic_info *pdn_info)
691+
/** @brief Fill PDN dynamic info with DNS addresses adnd mtu. */
692+
static void pdn_dynamic_info_dns_addr_fill(struct pdn_dynamic_info *pdn_info, uint32_t mtu,
693+
const char *dns_addr_str_primary,
694+
const char *dns_addr_str_secondary)
686695
{
687-
int ret = 0;
688-
struct at_parser parser;
689-
size_t param_str_len;
690-
691-
char *cgcontrdp_at_rsp_buf;
692-
693-
char *at_ptr;
694-
char *tmp_ptr;
695-
int lines = 0;
696-
int iterator = 0;
697-
char dns_addr_str[AT_CMD_PDN_CONTEXT_READ_IP_ADDR_STR_MAX_LEN];
696+
const int family = pdn_sa_family_from_ip_string(dns_addr_str_primary);
698697

699-
char at_cmd_pdn_context_read_info_cmd_str[15];
698+
if (family == AF_INET) {
699+
(void)zsock_inet_pton(AF_INET, dns_addr_str_primary,
700+
&(pdn_info->dns_addr4_primary));
701+
(void)zsock_inet_pton(AF_INET, dns_addr_str_secondary,
702+
&(pdn_info->dns_addr4_secondary));
703+
pdn_info->ipv4_mtu = mtu;
704+
} else if (family == AF_INET6) {
705+
(void)zsock_inet_pton(AF_INET6, dns_addr_str_primary,
706+
&(pdn_info->dns_addr6_primary));
707+
(void)zsock_inet_pton(AF_INET6, dns_addr_str_secondary,
708+
&(pdn_info->dns_addr6_secondary));
709+
pdn_info->ipv6_mtu = mtu;
710+
}
711+
}
700712

701-
int family;
702-
struct in_addr *addr;
703-
struct in6_addr *addr6;
713+
int pdn_dynamic_info_get(uint8_t cid, struct pdn_dynamic_info *pdn_info)
714+
{
715+
int ret;
716+
char at_cmd_buf[sizeof("AT+CGCONTRDP=###")];
717+
char dns_addr_str_primary[INET6_ADDRSTRLEN];
718+
char dns_addr_str_secondary[INET6_ADDRSTRLEN];
719+
uint32_t mtu = 0;
704720

705721
if (!pdn_info) {
706722
return -EINVAL;
707723
}
708724

709-
cgcontrdp_at_rsp_buf = k_malloc(CONFIG_PDN_DYNAMIC_INFO_AT_BUF_SIZE);
710-
if (!cgcontrdp_at_rsp_buf) {
711-
LOG_ERR("k_malloc failed for CGDCONTRDP response buffer");
712-
return -ENOMEM;
713-
}
725+
/* Reset PDN dynamic info. */
726+
memset(pdn_info, 0, sizeof(struct pdn_dynamic_info));
714727

715-
at_ptr = cgcontrdp_at_rsp_buf;
716-
tmp_ptr = cgcontrdp_at_rsp_buf;
728+
/* Clear secondary DNS address buffer. */
729+
memset(dns_addr_str_secondary, 0, sizeof(dns_addr_str_secondary));
717730

718-
sprintf(at_cmd_pdn_context_read_info_cmd_str, AT_CMD_PDN_CONTEXT_READ_INFO, cid);
719-
ret = nrf_modem_at_cmd(cgcontrdp_at_rsp_buf, CONFIG_PDN_DYNAMIC_INFO_AT_BUF_SIZE, "%s",
720-
at_cmd_pdn_context_read_info_cmd_str);
721-
if (ret) {
722-
LOG_ERR(
723-
"nrf_modem_at_cmd returned err: %d for %s",
724-
ret,
725-
at_cmd_pdn_context_read_info_cmd_str);
726-
goto clean_exit;
731+
(void)snprintf(at_cmd_buf, sizeof(at_cmd_buf), AT_CMD_PDN_CONTEXT_READ_INFO, cid);
732+
ret = nrf_modem_at_scanf(at_cmd_buf, AT_CMD_PDN_CONTEXT_READ_INFO_PARSE_LINE1,
733+
dns_addr_str_primary, dns_addr_str_secondary, &mtu);
734+
if (ret < 1) {
735+
LOG_ERR("nrf_modem_at_scanf failed, ret: %d", ret);
736+
return ret;
727737
}
728738

729-
/* Check how many rows of info do we have */
730-
while (strncmp(tmp_ptr, "OK", 2) &&
731-
(tmp_ptr = strstr(tmp_ptr, AT_CMD_PDN_CONTEXT_READ_RSP_DELIM)) != NULL) {
732-
tmp_ptr += 2;
733-
lines++;
734-
}
739+
pdn_dynamic_info_dns_addr_fill(pdn_info, mtu, dns_addr_str_primary, dns_addr_str_secondary);
735740

736-
/* Parse the response */
737-
ret = at_parser_init(&parser, at_ptr);
738-
if (ret) {
739-
LOG_ERR("Could not init AT parser for %s, error: %d\n",
740-
at_cmd_pdn_context_read_info_cmd_str, ret);
741-
goto clean_exit;
742-
}
741+
/* Reset secondary DNS address buffer and mtu. */
742+
memset(dns_addr_str_secondary, 0, sizeof(dns_addr_str_secondary));
743+
mtu = 0;
743744

744-
parse:
745-
/* Read primary DNS address */
746-
param_str_len = sizeof(dns_addr_str);
747-
ret = at_parser_string_get(
748-
&parser,
749-
AT_CMD_PDN_CONTEXT_READ_INFO_DNS_ADDR_PRIMARY_INDEX,
750-
dns_addr_str, &param_str_len);
751-
if (ret) {
752-
LOG_ERR("Could not parse dns str for cid %d, err: %d", cid, ret);
753-
goto clean_exit;
745+
/* Scan second line if PDN has dual stack capabilities. */
746+
ret = nrf_modem_at_scanf(at_cmd_buf, AT_CMD_PDN_CONTEXT_READ_INFO_PARSE_LINE2,
747+
dns_addr_str_primary, dns_addr_str_secondary, &mtu);
748+
if (ret < 1) {
749+
/* We only got one entry, but that is ok. */
750+
return 0;
754751
}
755-
dns_addr_str[param_str_len] = '\0';
756752

757-
family = pdn_sa_family_from_ip_string(dns_addr_str);
753+
pdn_dynamic_info_dns_addr_fill(pdn_info, mtu, dns_addr_str_primary, dns_addr_str_secondary);
758754

759-
if (family == AF_INET) {
760-
addr = &(pdn_info->dns_addr4_primary);
761-
(void)inet_pton(AF_INET, dns_addr_str, addr);
762-
} else if (family == AF_INET6) {
763-
addr6 = &(pdn_info->dns_addr6_primary);
764-
(void)inet_pton(AF_INET6, dns_addr_str, addr6);
765-
}
766-
767-
/* Read secondary DNS address */
768-
param_str_len = sizeof(dns_addr_str);
769-
770-
ret = at_parser_string_get(
771-
&parser,
772-
AT_CMD_PDN_CONTEXT_READ_INFO_DNS_ADDR_SECONDARY_INDEX,
773-
dns_addr_str, &param_str_len);
774-
if (ret) {
775-
LOG_ERR("Could not parse dns str, err: %d", ret);
776-
goto clean_exit;
777-
}
778-
dns_addr_str[param_str_len] = '\0';
779-
780-
family = pdn_sa_family_from_ip_string(dns_addr_str);
781-
782-
if (family == AF_INET) {
783-
addr = &(pdn_info->dns_addr4_secondary);
784-
(void)inet_pton(AF_INET, dns_addr_str, addr);
785-
} else if (family == AF_INET6) {
786-
addr6 = &(pdn_info->dns_addr6_secondary);
787-
(void)inet_pton(AF_INET6, dns_addr_str, addr6);
788-
}
789-
790-
/* Read link MTU if exists:
791-
* AT command spec:
792-
* Note: If the PDN connection has dual stack capabilities, at least one pair of
793-
* lines with information is returned per <cid>: First one line with the IPv4
794-
* parameters followed by one line with the IPv6 parameters.
795-
*/
796-
if (iterator == 1) {
797-
ret = at_parser_num_get(&parser, AT_CMD_PDN_CONTEXT_READ_INFO_MTU_INDEX,
798-
&(pdn_info->ipv6_mtu));
799-
if (ret) {
800-
/* Don't care if it fails */
801-
ret = 0;
802-
pdn_info->ipv6_mtu = 0;
803-
}
804-
} else {
805-
ret = at_parser_num_get(&parser, AT_CMD_PDN_CONTEXT_READ_INFO_MTU_INDEX,
806-
&(pdn_info->ipv4_mtu));
807-
if (ret) {
808-
/* Don't care if it fails */
809-
ret = 0;
810-
pdn_info->ipv4_mtu = 0;
811-
}
812-
}
813-
814-
if (at_parser_cmd_next(&parser) == 0) {
815-
iterator++;
816-
if (iterator < lines) {
817-
goto parse;
818-
}
819-
}
820-
821-
clean_exit:
822-
k_free(cgcontrdp_at_rsp_buf);
823-
return ret;
755+
return 0;
824756
}
825757

826758
int pdn_default_apn_get(char *buf, size_t len)

samples/cellular/pdn/README.rst

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,26 +62,39 @@ The sample shows the following output, which may vary based on the network provi
6262

6363
.. code-block:: console
6464
65+
*** Booting nRF Connect SDK v2.9.99-0f7da9c375d1 ***
66+
*** Using Zephyr OS v3.7.99-2d1e173dfed0 ***
6567
PDN sample started
6668
Event: PDP context 0 activated
67-
Default APN is telenor.iot
69+
Default APN is telenor.smart
6870
Created new PDP context 1
69-
PDP contEvent: PDP context 0 IPv6 up
70-
ext 1 configured: APN telenor.iot, Family IPV4V6
71+
PDP context 1 configured: APN telenor.smart, Family IPV4V6
7172
Event: PDP context 1 activated
73+
Event: PDP context 0 IPv6 up
7274
Event: PDP context 1 IPv6 up
7375
PDP Context 0, PDN ID 0
7476
PDP Context 1, PDN ID 0
77+
Dynamic info for cid 0:
78+
Primary IPv4 DNS address: 111.222.233.4
79+
Secondary IPv4 DNS address: 111.222.233.4
80+
Primary IPv6 DNS address: 1111:2222:3:fff::55
81+
Secondary IPv6 DNS address: 1111:2222:3:fff::55
82+
IPv4 MTU: 1500, IPv6 MTU: 1500
83+
Dynamic info for cid 1:
84+
Primary IPv4 DNS address: 111.222.233.4
85+
Secondary IPv4 DNS address: 111.222.233.4
86+
Primary IPv6 DNS address: 1111:2222:3:fff::55
87+
Secondary IPv6 DNS address: 1111:2222:3:fff::55
88+
IPv4 MTU: 1500, IPv6 MTU: 1500
7589
7690
Interface addresses:
77-
l0: (AF_INET) 10.243.140.208
78-
l0: (AF_INET6) fe80::63:b639:ab01
79-
l0: (AF_INET6) 2a02:2121:20d:175d:0:63:b639:ab01
91+
l0: (AF_INET) 10.22.233.44
92+
l0: (AF_INET6) aaaa::bbbb:cccc
93+
l0: (AF_INET6) aaa:bbbbb:cccc:dddd::eeee:2cd2
8094
81-
Event: PDP context 0 deactivated
82-
Event: PDP context 1 deactivated
8395
Event: PDP context 0 network detach
8496
Event: PDP context 1 network detach
97+
Event: PDP context 1 context destroyed
8598
Bye
8699
87100
Dependencies

0 commit comments

Comments
 (0)