Skip to content

Commit

Permalink
lib: pdn: destroy context on CFUN 0
Browse files Browse the repository at this point in the history
Destroy context on CFUN 0 as that is done in the modem. This does not
apply for the default context. Add context destroyed event to ATv2,
MoSh and LTE Net IF.

Signed-off-by: Eivind Jølsgard <eivind.jolsgard@nordicsemi.no>
  • Loading branch information
eivindj-nordic authored and nordicjm committed Sep 24, 2024
1 parent 268dbd7 commit 45b0325
Show file tree
Hide file tree
Showing 9 changed files with 168 additions and 25 deletions.
2 changes: 2 additions & 0 deletions applications/asset_tracker_v2/src/modules/modem_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,8 @@ void pdn_event_handler(uint8_t cid, enum pdn_event event, int reason)
case PDN_EVENT_NETWORK_DETACH:
LOG_DBG("PDN_EVENT_NETWORK_DETACH");
break;
case PDN_EVENT_CTX_DESTROYED:
LOG_DBG("PDN_EVENT_CTX_DESTROYED");
default:
LOG_WRN("Unexpected PDN event!");
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -725,16 +725,18 @@ Modem libraries

* :ref:`nrf_modem_lib_readme`:

* Updated the RTT trace backend to allocate the RTT channel at boot, instead of when the modem is activated.
* Rename the nRF91 socket offload layer from ``nrf91_sockets`` to ``nrf9x_sockets`` to reflect that the offload layer is not exclusive to the nRF91 Series SiPs.
* Removed support for deprecated RAI socket options ``SO_RAI_LAST``, ``SO_RAI_NO_DATA``, ``SO_RAI_ONE_RESP``, ``SO_RAI_ONGOING``, and ``SO_RAI_WAIT_MORE``.

* :ref:`modem_info_readme` library:

* Fixed a potential issue with scanf in the :c:func:`modem_info_get_current_band` function, which could lead to memory corruption.

* :ref:`nrf_modem_lib_readme` library:
* :ref:`pdn_readme` library:

* Updated the RTT trace backend to allocate the RTT channel at boot, instead of when the modem is activated.
* Removed support for deprecated RAI socket options ``SO_RAI_LAST``, ``SO_RAI_NO_DATA``, ``SO_RAI_ONE_RESP``, ``SO_RAI_ONGOING``, and ``SO_RAI_WAIT_MORE``.
* Added the event ``PDN_EVENT_CTX_DESTROYED`` to indicate when a PDP context is destroyed.
This happens when the modem is switched to minimum functionality mode (``CFUN=0``).

* :ref:`sms_readme` library:

Expand Down
28 changes: 20 additions & 8 deletions include/modem/pdn.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,26 @@ struct pdn_pdp_opt {

/** @brief PDN library event */
enum pdn_event {
PDN_EVENT_CNEC_ESM, /**< +CNEC ESM error code */
PDN_EVENT_ACTIVATED, /**< PDN connection activated */
PDN_EVENT_DEACTIVATED, /**< PDN connection deactivated */
PDN_EVENT_IPV6_UP, /**< PDN has IPv6 connectivity */
PDN_EVENT_IPV6_DOWN, /**< PDN has lost IPv6 connectivity */
PDN_EVENT_NETWORK_DETACH, /**< Network detached */
PDN_EVENT_APN_RATE_CONTROL_ON, /**< APN rate control is ON for given PDN */
PDN_EVENT_APN_RATE_CONTROL_OFF, /**< APN rate control is OFF for given PDN */
/** +CNEC ESM error code */
PDN_EVENT_CNEC_ESM,
/** PDN connection activated */
PDN_EVENT_ACTIVATED,
/** PDN connection deactivated */
PDN_EVENT_DEACTIVATED,
/** PDN has IPv6 connectivity */
PDN_EVENT_IPV6_UP,
/** PDN has lost IPv6 connectivity */
PDN_EVENT_IPV6_DOWN,
/** Network detached */
PDN_EVENT_NETWORK_DETACH,
/** APN rate control is ON for given PDN */
PDN_EVENT_APN_RATE_CONTROL_ON,
/** APN rate control is OFF for given PDN */
PDN_EVENT_APN_RATE_CONTROL_OFF,
/** PDP context is destroyed for given PDN.
* This happens if modem is switched to minimum functionality mode.
*/
PDN_EVENT_CTX_DESTROYED,
};

/** @brief PDN authentication method */
Expand Down
3 changes: 3 additions & 0 deletions lib/nrf_modem_lib/lte_net_if/lte_net_if.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,9 @@ static void pdn_event_handler(uint8_t cid, enum pdn_event event, int reason)
on_pdn_ipv6_down();
break;
#endif /* CONFIG_NET_IPV6 */
case PDN_EVENT_CTX_DESTROYED:
LOG_DBG("PDN context destroyed");
break;
default:
LOG_ERR("Unexpected PDN event: %d", event);
break;
Expand Down
54 changes: 43 additions & 11 deletions lib/pdn/pdn.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,11 +300,21 @@ static void on_modem_init(int ret, void *ctx)
int pdn_default_ctx_cb_reg(pdn_event_handler_t cb)
{
struct pdn *pdn;
struct pdn *tmp;

if (!cb) {
return -EFAULT;
}

k_mutex_lock(&list_mutex, K_FOREVER);
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&pdn_contexts, pdn, tmp, node) {
if (pdn->context_id == 0 && pdn->callback == cb) {
/* Already registered */
return 0;
}
}
k_mutex_unlock(&list_mutex);

pdn = pdn_ctx_new();
if (!pdn) {
return -ENOMEM;
Expand All @@ -318,23 +328,25 @@ int pdn_default_ctx_cb_reg(pdn_event_handler_t cb)
return 0;
}

static void pdn_ctx_free(struct pdn *pdn)
static bool pdn_ctx_free(struct pdn *pdn)
{
bool removed;

if (!pdn) {
return;
return false;
}

k_mutex_lock(&list_mutex, K_FOREVER);
removed = sys_slist_find_and_remove(&pdn_contexts, &pdn->node);
k_mutex_unlock(&list_mutex);

if (!removed) {
return;
return false;
}

k_free(pdn);

return true;
}

int pdn_default_ctx_cb_dereg(pdn_event_handler_t cb)
Expand All @@ -351,7 +363,7 @@ int pdn_default_ctx_cb_dereg(pdn_event_handler_t cb)
k_mutex_lock(&list_mutex, K_FOREVER);
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&pdn_contexts, pdn, tmp, node) {
if (pdn->callback == cb) {
removed = sys_slist_find_and_remove(&pdn_contexts, &pdn->node);
removed = pdn_ctx_free(pdn);
break;
}
}
Expand All @@ -362,7 +374,6 @@ int pdn_default_ctx_cb_dereg(pdn_event_handler_t cb)
}

LOG_DBG("Default PDP ctx callback %p unregistered", pdn->callback);
k_free(pdn);

return 0;
}
Expand All @@ -384,17 +395,17 @@ int pdn_ctx_create(uint8_t *cid, pdn_event_handler_t cb)

err = nrf_modem_at_scanf("AT%XNEWCID?", "%%XNEWCID: %d", &ctx_id_tmp);
if (err < 0) {
pdn_ctx_free(pdn);
(void)pdn_ctx_free(pdn);
return err;
} else if (err == 0) {
/* no argument matched */
pdn_ctx_free(pdn);
(void)pdn_ctx_free(pdn);
return -EBADMSG;
}

if (ctx_id_tmp > SCHAR_MAX || ctx_id_tmp < SCHAR_MIN) {
LOG_ERR("Context ID (%d) out of bounds", ctx_id_tmp);
pdn_ctx_free(pdn);
(void)pdn_ctx_free(pdn);
return -EFAULT;
}

Expand Down Expand Up @@ -512,7 +523,7 @@ int pdn_ctx_destroy(uint8_t cid)
/* cleanup regardless */
}

pdn_ctx_free(pdn);
(void)pdn_ctx_free(pdn);

return err;
}
Expand Down Expand Up @@ -672,11 +683,17 @@ int pdn_default_apn_get(char *buf, size_t len)
return 0;
}

NRF_MODEM_LIB_ON_CFUN(pdn_cfun_hook, on_cfun, NULL);
#if defined(CONFIG_UNITY)
void pdn_on_modem_cfun(int mode, void *ctx)
#else
NRF_MODEM_LIB_ON_CFUN(pdn_cfun_hook, pdn_on_modem_cfun, NULL);

static void on_cfun(int mode, void *ctx)
static void pdn_on_modem_cfun(int mode, void *ctx)
#endif
{
int err;
struct pdn *pdn;
struct pdn *tmp;

if (mode == MODEM_CFUN_NORMAL ||
mode == MODEM_CFUN_ACTIVATE_LTE) {
Expand All @@ -692,6 +709,21 @@ static void on_cfun(int mode, void *ctx)
}

if (mode == MODEM_CFUN_POWER_OFF) {
k_mutex_lock(&list_mutex, K_FOREVER);
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&pdn_contexts, pdn, tmp, node) {
if (pdn->context_id == 0) {
/* Default context is not destroyed */
continue;
}

if (pdn->callback) {
pdn->callback(pdn->context_id, PDN_EVENT_CTX_DESTROYED, 0);
}

(void)pdn_ctx_free(pdn);
}
k_mutex_unlock(&list_mutex);

#if defined(CONFIG_PDN_DEFAULTS_OVERRIDE)
pdn_defaults_override();
#endif
Expand Down
1 change: 1 addition & 0 deletions samples/cellular/modem_shell/src/link/link_shell_pdn.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ static const char *const event_str[] = {
[PDN_EVENT_IPV6_UP] = "IPv6 up",
[PDN_EVENT_IPV6_DOWN] = "IPv6 down",
[PDN_EVENT_NETWORK_DETACH] = "network detach",
[PDN_EVENT_CTX_DESTROYED] = "context destroyed",
};

void link_pdn_event_handler(uint8_t cid, enum pdn_event event, int reason)
Expand Down
1 change: 1 addition & 0 deletions samples/cellular/pdn/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ static const char * const event_str[] = {
[PDN_EVENT_IPV6_UP] = "IPv6 up",
[PDN_EVENT_IPV6_DOWN] = "IPv6 down",
[PDN_EVENT_NETWORK_DETACH] = "network detach",
[PDN_EVENT_CTX_DESTROYED] = "context destroyed",
};

static void snprintaddr(char *str, size_t size, struct nrf_sockaddr *addr)
Expand Down
3 changes: 3 additions & 0 deletions tests/lib/pdn/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,6 @@ zephyr_include_directories(${ZEPHYR_NRF_MODULE_DIR}/include/modem/)
zephyr_include_directories(${ZEPHYR_BASE}/subsys/testsuite/include)

add_compile_definitions(CONFIG_PDN_ESM_TIMEOUT=1000)
add_compile_definitions(CONFIG_PDN_DEFAULTS_OVERRIDE)
add_compile_definitions(CONFIG_PDN_DEFAULT_APN="apn0")
add_compile_definitions(CONFIG_PDN_DEFAULT_FAM=2)
93 changes: 90 additions & 3 deletions tests/lib/pdn/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -463,9 +463,43 @@ static int nrf_modem_at_printf_cgact_deactivate(const char *cmd, va_list args)
return 0;
}

static int nrf_modem_at_printf_xepco(const char *cmd, va_list args)
static int nrf_modem_at_printf_on_cfun_pwr_off(const char *cmd, va_list args)
{
TEST_ASSERT_EQUAL_STRING("AT%%XEPCO=1", cmd);
TEST_ASSERT_EQUAL_STRING("AT+CGDCONT=%u,%s,%s", cmd);

return 0;
}

static int nrf_modem_at_printf_on_cfun_lte_on(const char *cmd, va_list args)
{
switch (nrf_modem_at_printf_fake.call_count) {
case 1:
TEST_ASSERT_EQUAL_STRING("AT+CNEC=16", cmd);
break;
case 2:
TEST_ASSERT_EQUAL_STRING("AT+CGEREP=1", cmd);
break;
default:
TEST_ASSERT_TRUE(false);
break;
}

return 0;
}

static int nrf_modem_at_printf_on_init(const char *cmd, va_list args)
{
switch (nrf_modem_at_printf_fake.call_count) {
case 1:
TEST_ASSERT_EQUAL_STRING("AT%%XEPCO=1", cmd);
break;
case 2:
TEST_ASSERT_EQUAL_STRING("AT+CGDCONT=%u,%s,%s", cmd);
break;
default:
TEST_ASSERT_TRUE(false);
break;
}

return 0;
}
Expand Down Expand Up @@ -626,6 +660,11 @@ void test_pdn_pdn_default_ctx_cb_reg(void)

ret = pdn_default_ctx_cb_reg(pdn_event_handler);
TEST_ASSERT_EQUAL(0, ret);

/* If already registered we should allow tha call but not register again */
ret = pdn_default_ctx_cb_reg(pdn_event_handler);
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(1, k_malloc_fake.call_count);
}

void test_pdn_default_ctx_cb_dereg_efault(void)
Expand Down Expand Up @@ -1229,6 +1268,48 @@ void test_pdn_esm_strerror(void)
TEST_ASSERT_EQUAL_STRING("<unknown>", str);
}

extern void pdn_on_modem_cfun(int mode, void *ctx);
void test_on_modem_cfun_pwr_off(void)
{
int ret;

nrf_modem_at_printf_fake.custom_fake = nrf_modem_at_printf_on_cfun_pwr_off;

/* we don't expect anything to happen in this case. */
pdn_on_modem_cfun(0, NULL);

TEST_ASSERT_EQUAL(1, nrf_modem_at_printf_fake.call_count);


RESET_FAKE(nrf_modem_at_printf);
nrf_modem_at_printf_fake.custom_fake = nrf_modem_at_printf_on_cfun_pwr_off;
test_pdn_ctx_create_cid1();

pdn_on_modem_cfun(0, NULL);

TEST_ASSERT_EQUAL(1, nrf_modem_at_printf_fake.call_count);

/* Context destroyed on FCUN=0 */
ret = pdn_ctx_destroy(1);
TEST_ASSERT_EQUAL(-EINVAL, ret);
}

void test_on_modem_cfun_lte_on(void)
{
nrf_modem_at_printf_fake.custom_fake = nrf_modem_at_printf_on_cfun_lte_on;

pdn_on_modem_cfun(1, NULL);

TEST_ASSERT_EQUAL(2, nrf_modem_at_printf_fake.call_count);

RESET_FAKE(nrf_modem_at_printf);
nrf_modem_at_printf_fake.custom_fake = nrf_modem_at_printf_on_cfun_lte_on;
pdn_on_modem_cfun(21, NULL);

TEST_ASSERT_EQUAL(2, nrf_modem_at_printf_fake.call_count);

}

extern void on_modem_init(int ret, void *ctx);
void test_on_modem_init(void)
{
Expand All @@ -1239,9 +1320,15 @@ void test_on_modem_init(void)

on_modem_init(0, NULL);

nrf_modem_at_printf_fake.custom_fake = nrf_modem_at_printf_xepco;
TEST_ASSERT_EQUAL(1, nrf_modem_at_printf_fake.call_count);

nrf_modem_at_printf_fake.custom_fake = nrf_modem_at_printf_on_init;

RESET_FAKE(nrf_modem_at_printf);

on_modem_init(0, NULL);

TEST_ASSERT_EQUAL(2, nrf_modem_at_printf_fake.call_count);
}

/* It is required to be added to each test. That is because unity's
Expand Down

0 comments on commit 45b0325

Please sign in to comment.