diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst index 7ff5b78a6829..bcb6d782f5a9 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst @@ -492,6 +492,8 @@ Modem libraries * Fixed an issue with the :c:func:`modem_key_mgmt_clear` function where it returned ``-ENOENT`` when the credential was cleared. +* Updated the :ref:`nrf_modem_lib_lte_net_if` to automatically set the actual link :term:`Maximum Transmission Unit (MTU)` on the network interface when PDN connectivity is gained. + Multiprotocol Service Layer libraries ------------------------------------- diff --git a/lib/nrf_modem_lib/lte_net_if/lte_net_if.c b/lib/nrf_modem_lib/lte_net_if/lte_net_if.c index 15476b1a400b..ec237779e83b 100644 --- a/lib/nrf_modem_lib/lte_net_if/lte_net_if.c +++ b/lib/nrf_modem_lib/lte_net_if/lte_net_if.c @@ -60,13 +60,29 @@ void lte_net_if_modem_fault_handler(void) net_if_dormant_on(iface_bound); } +static uint16_t pdn_mtu(void) +{ + struct pdn_dynamic_info info; + int rc; + + rc = pdn_dynamic_info_get(0, &info); + if ((rc != 0) || (info.ipv4_mtu == 0)) { + LOG_WRN("MTU query failed, error: %d, MTU: %d", rc, info.ipv4_mtu); + /* Fallback to the minimum value that IPv4 is required to support */ + info.ipv4_mtu = NET_IPV4_MTU; + } + LOG_DBG("Network MTU: %d", info.ipv4_mtu); + return info.ipv4_mtu; +} + /* Called when we detect LTE connectivity has been gained. * - * Marks the iface as active and cancels any pending timeout. + * Queries the network MTU, marks the iface as active, and cancels any pending timeout. */ static void become_active(void) { LOG_DBG("Becoming active"); + net_if_set_mtu(iface_bound, pdn_mtu()); net_if_dormant_off(iface_bound); k_work_cancel_delayable(&connection_timeout_work); } diff --git a/lib/nrf_modem_lib/nrf9x_sockets.c b/lib/nrf_modem_lib/nrf9x_sockets.c index a593b22222f0..da8c84266366 100644 --- a/lib/nrf_modem_lib/nrf9x_sockets.c +++ b/lib/nrf_modem_lib/nrf9x_sockets.c @@ -1168,7 +1168,7 @@ static struct offloaded_if_api nrf9x_iface_offload_api = { .enable = nrf9x_iface_enable, }; -/* TODO Get the actual MTU for the nRF9x LTE link. */ +/* Actual MTU for the nRF9x LTE link is handled by `lte_net_if.c` */ NET_DEVICE_OFFLOAD_INIT(nrf9x_socket, "nrf9x_socket", nrf9x_socket_offload_init, NULL, diff --git a/tests/lib/nrf_modem_lib/lte_net_if/src/main.c b/tests/lib/nrf_modem_lib/lte_net_if/src/main.c index 89c90ea1fe55..463b6d0bdc0a 100644 --- a/tests/lib/nrf_modem_lib/lte_net_if/src/main.c +++ b/tests/lib/nrf_modem_lib/lte_net_if/src/main.c @@ -44,6 +44,14 @@ static void lte_lc_register_handler_stub(lte_lc_evt_handler_t cb, int num_of_cal lte_lc_event_handler_callback = cb; } +/* Stub used to report a non-default link MTU */ +static int pdn_dynamic_info_get_1000_stub(uint32_t cid, struct pdn_dynamic_info *pdn_info, + int num_of_calls) +{ + pdn_info->ipv4_mtu = 1000; + return 0; +} + static void bring_network_interface_up(void) { struct net_if *net_if = net_if_get_default(); @@ -442,11 +450,17 @@ void test_pdn_act_with_cereg_should_activate_iface(void) "AT+CGPADDR=0", "+CGPADDR: %*d,\"%46[.:0-9A-F]\",\"%46[:0-9A-F]\"", 1); __mock_nrf_modem_at_scanf_ReturnVarg_string("192.9.201.39"); + /* Netowrk MTU is 1000 */ + __cmock_pdn_dynamic_info_get_Stub(&pdn_dynamic_info_get_1000_stub); + /* Fire PDN active */ pdn_event_handler_callback(0, PDN_EVENT_ACTIVATED, 0); /* Check that iface becomes active */ TEST_ASSERT_FALSE(net_if_is_dormant(net_if)); + + /* MTU should have been set to reported value */ + TEST_ASSERT_EQUAL(1000, net_if_get_mtu(net_if)); } @@ -504,6 +518,9 @@ void test_cereg_registered_home_with_pdn_should_activate_iface(void) "AT+CGPADDR=0", "+CGPADDR: %*d,\"%46[.:0-9A-F]\",\"%46[:0-9A-F]\"", 1); __mock_nrf_modem_at_scanf_ReturnVarg_string("192.9.201.39"); + /* MTU query fails */ + __cmock_pdn_dynamic_info_get_IgnoreAndReturn(-1); + /* Fire PDN active */ pdn_event_handler_callback(0, PDN_EVENT_ACTIVATED, 0); @@ -516,6 +533,9 @@ void test_cereg_registered_home_with_pdn_should_activate_iface(void) /* Check that iface becomes active */ TEST_ASSERT_FALSE(net_if_is_dormant(net_if)); + + /* MTU should have reverted to default minimum */ + TEST_ASSERT_EQUAL(NET_IPV4_MTU, net_if_get_mtu(net_if)); } /* Verify that CEREG registration (roaming) does activate iface if PDN is active */ @@ -542,6 +562,9 @@ void test_cereg_registered_roaming_with_pdn_should_activate_iface(void) "AT+CGPADDR=0", "+CGPADDR: %*d,\"%46[.:0-9A-F]\",\"%46[:0-9A-F]\"", 1); __mock_nrf_modem_at_scanf_ReturnVarg_string("192.9.201.39"); + /* MTU not set by function */ + __cmock_pdn_dynamic_info_get_IgnoreAndReturn(0); + /* Fire PDN active */ pdn_event_handler_callback(0, PDN_EVENT_ACTIVATED, 0); @@ -554,6 +577,9 @@ void test_cereg_registered_roaming_with_pdn_should_activate_iface(void) /* Check that iface becomes active */ TEST_ASSERT_FALSE(net_if_is_dormant(net_if)); + + /* MTU should have reverted to default minimum */ + TEST_ASSERT_EQUAL(NET_IPV4_MTU, net_if_get_mtu(net_if)); } /* Verify that CEREG searching does not affect iface activation (from inactive to active) */ @@ -602,6 +628,7 @@ void test_cereg_searching_should_not_deactivate_iface(void) */ __cmock_nrf_modem_is_initialized_IgnoreAndReturn(1); __cmock_lte_lc_func_mode_set_IgnoreAndReturn(0); + __cmock_pdn_dynamic_info_get_IgnoreAndReturn(0); /* Take the iface admin-up */ net_if_up(net_if); @@ -644,6 +671,7 @@ void test_cereg_unregistered_should_deactivate_iface(void) */ __cmock_nrf_modem_is_initialized_IgnoreAndReturn(1); __cmock_lte_lc_func_mode_set_IgnoreAndReturn(0); + __cmock_pdn_dynamic_info_get_IgnoreAndReturn(0); /* Take the iface admin-up */ net_if_up(net_if); @@ -686,6 +714,7 @@ void test_pdn_deact_should_deactivate_iface(void) */ __cmock_nrf_modem_is_initialized_IgnoreAndReturn(1); __cmock_lte_lc_func_mode_set_IgnoreAndReturn(0); + __cmock_pdn_dynamic_info_get_IgnoreAndReturn(0); /* Take the iface admin-up */ net_if_up(net_if);