diff --git a/drivers/modem/Kconfig.cellular b/drivers/modem/Kconfig.cellular index 5e1a38b99dd..adc66f574b7 100644 --- a/drivers/modem/Kconfig.cellular +++ b/drivers/modem/Kconfig.cellular @@ -42,15 +42,8 @@ config MODEM_CELLULAR_UART_BUFFER_SIZES int "The UART receive and transmit buffer sizes in bytes." default 512 -config MODEM_CELLULAR_CMUX_MAX_FRAME_SIZE - int "The maximum CMUX frame size in bytes." - default 32 if DT_HAS_U_BLOX_LARA_R6_ENABLED - default 128 - help - This value affects the size of buffers used to receive and transmit CMUX frames. - -config MODEM_CELLULAR_CHAT_BUFFER_SIZES - int "The size of the buffers used for the chat scripts in bytes." +config MODEM_CELLULAR_CHAT_BUFFER_SIZE + int "The size of the buffer used for the chat scripts in bytes." default 128 config MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES diff --git a/drivers/modem/modem_cellular.c b/drivers/modem/modem_cellular.c index 01702787875..2af67a01c7a 100644 --- a/drivers/modem/modem_cellular.c +++ b/drivers/modem/modem_cellular.c @@ -90,8 +90,8 @@ struct modem_cellular_data { /* CMUX */ struct modem_cmux cmux; - uint8_t cmux_receive_buf[CONFIG_MODEM_CELLULAR_CMUX_MAX_FRAME_SIZE]; - uint8_t cmux_transmit_buf[2 * CONFIG_MODEM_CELLULAR_CMUX_MAX_FRAME_SIZE]; + uint8_t cmux_receive_buf[CONFIG_MODEM_CMUX_WORK_BUFFER_SIZE]; + uint8_t cmux_transmit_buf[CONFIG_MODEM_CMUX_WORK_BUFFER_SIZE]; struct modem_cmux_dlci dlci1; struct modem_cmux_dlci dlci2; @@ -99,13 +99,13 @@ struct modem_cellular_data { struct modem_pipe *dlci2_pipe; /* Points to dlci2_pipe or NULL. Used for shutdown script if not NULL */ struct modem_pipe *cmd_pipe; - uint8_t dlci1_receive_buf[CONFIG_MODEM_CELLULAR_CMUX_MAX_FRAME_SIZE]; + uint8_t dlci1_receive_buf[CONFIG_MODEM_CMUX_WORK_BUFFER_SIZE]; /* DLCI 2 is only used for chat scripts. */ - uint8_t dlci2_receive_buf[CONFIG_MODEM_CELLULAR_CHAT_BUFFER_SIZES]; + uint8_t dlci2_receive_buf[CONFIG_MODEM_CMUX_WORK_BUFFER_SIZE]; /* Modem chat */ struct modem_chat chat; - uint8_t chat_receive_buf[CONFIG_MODEM_CELLULAR_CHAT_BUFFER_SIZES]; + uint8_t chat_receive_buf[CONFIG_MODEM_CELLULAR_CHAT_BUFFER_SIZE]; uint8_t *chat_delimiter; uint8_t *chat_filter; uint8_t *chat_argv[32]; diff --git a/samples/net/cellular_modem/boards/mg100.conf b/samples/net/cellular_modem/boards/mg100.conf index 3b6ae6e7d57..636c416d838 100644 --- a/samples/net/cellular_modem/boards/mg100.conf +++ b/samples/net/cellular_modem/boards/mg100.conf @@ -1,3 +1,2 @@ CONFIG_MODEM_HL7800=n -CONFIG_MODEM_CELLULAR_CMUX_MAX_FRAME_SIZE=255 CONFIG_NET_BUF_TX_COUNT=32 diff --git a/samples/net/cellular_modem/boards/nrf9160dk_nrf52840.conf b/samples/net/cellular_modem/boards/nrf9160dk_nrf52840.conf index 78e64e0c4c9..226ce728a19 100644 --- a/samples/net/cellular_modem/boards/nrf9160dk_nrf52840.conf +++ b/samples/net/cellular_modem/boards/nrf9160dk_nrf52840.conf @@ -3,7 +3,6 @@ CONFIG_UART_1_ASYNC=y CONFIG_UART_1_INTERRUPT_DRIVEN=n # Align with the Serial LTE Modem (SLM) application. -CONFIG_MODEM_CELLULAR_CMUX_MAX_FRAME_SIZE=1500 CONFIG_MODEM_CELLULAR_UART_BUFFER_SIZES=6000 # Print logs and printk() output on uart0. diff --git a/samples/net/cellular_modem/boards/nrf9160dk_nrf9160_ns.conf b/samples/net/cellular_modem/boards/nrf9160dk_nrf9160_ns.conf index c0586115e19..907cc9baed1 100644 --- a/samples/net/cellular_modem/boards/nrf9160dk_nrf9160_ns.conf +++ b/samples/net/cellular_modem/boards/nrf9160dk_nrf9160_ns.conf @@ -3,7 +3,6 @@ CONFIG_UART_1_ASYNC=y CONFIG_UART_1_INTERRUPT_DRIVEN=n # Align with the Serial LTE Modem (SLM) application. -CONFIG_MODEM_CELLULAR_CMUX_MAX_FRAME_SIZE=1500 CONFIG_MODEM_CELLULAR_UART_BUFFER_SIZES=6000 # Prevent sockets getting offloaded to the modem. diff --git a/samples/net/cellular_modem/boards/pinnacle_100_dvk.conf b/samples/net/cellular_modem/boards/pinnacle_100_dvk.conf index 3b6ae6e7d57..636c416d838 100644 --- a/samples/net/cellular_modem/boards/pinnacle_100_dvk.conf +++ b/samples/net/cellular_modem/boards/pinnacle_100_dvk.conf @@ -1,3 +1,2 @@ CONFIG_MODEM_HL7800=n -CONFIG_MODEM_CELLULAR_CMUX_MAX_FRAME_SIZE=255 CONFIG_NET_BUF_TX_COUNT=32 diff --git a/subsys/modem/Kconfig b/subsys/modem/Kconfig index 90a4ded36e7..211c5fa084f 100644 --- a/subsys/modem/Kconfig +++ b/subsys/modem/Kconfig @@ -29,10 +29,34 @@ config MODEM_CMUX if MODEM_CMUX +config MODEM_CMUX_DEFAULT_MTU_127 + bool + default y if (DT_HAS_QUECTEL_BG95_ENABLED || DT_HAS_QUECTEL_EG25_G_ENABLED || \ + DT_HAS_SIMCOM_SIM7080_ENABLED || DT_HAS_U_BLOX_SARA_R4_ENABLED || \ + DT_HAS_U_BLOX_SARA_R5_ENABLED || DT_HAS_SWIR_HL7800_ENABLED || \ + DT_HAS_TELIT_ME910G1_ENABLED || DT_HAS_TELIT_ME310G1_ENABLED || \ + DT_HAS_SQN_GM02S_ENABLED) + help + Use the default MTU size of 127 bytes for the CMUX module on certain modems. + This must match the AT+CMUX commands in the modem_cellular driver. + +config MODEM_CMUX_MTU + int "CMUX MTU size in bytes" + range 16 1500 + default 127 if MODEM_CMUX_DEFAULT_MTU_127 + default 31 + help + Maximum Transmission Unit (MTU) size for the CMUX module. + Linux ldattach defaults to 127 bytes, 3GPP TS 27.010 to 31. + config MODEM_CMUX_WORK_BUFFER_SIZE int "CMUX module work buffer size in bytes" - range 16 1500 - default 64 + range 23 1507 + default 134 if MODEM_CMUX_DEFAULT_MTU_127 + default 38 + help + Size of the work buffer used by the CMUX module. + Recommended size is MODEM_CMUX_MTU + 7 (CMUX header size). module = MODEM_CMUX module-str = modem_cmux diff --git a/subsys/modem/modem_cmux.c b/subsys/modem/modem_cmux.c index 7a78b06a8f3..74542aeda66 100644 --- a/subsys/modem/modem_cmux.c +++ b/subsys/modem/modem_cmux.c @@ -18,7 +18,7 @@ LOG_MODULE_REGISTER(modem_cmux, CONFIG_MODEM_CMUX_LOG_LEVEL); #define MODEM_CMUX_EA (0x01) #define MODEM_CMUX_CR (0x02) #define MODEM_CMUX_PF (0x10) -#define MODEM_CMUX_FRAME_SIZE_MAX (0x08) +#define MODEM_CMUX_FRAME_SIZE_MAX (0x07) #define MODEM_CMUX_DATA_SIZE_MIN (0x08) #define MODEM_CMUX_DATA_FRAME_SIZE_MIN (MODEM_CMUX_FRAME_SIZE_MAX + \ MODEM_CMUX_DATA_SIZE_MIN) @@ -274,6 +274,7 @@ static uint16_t modem_cmux_transmit_frame(struct modem_cmux *cmux, space = ring_buf_space_get(&cmux->transmit_rb) - MODEM_CMUX_FRAME_SIZE_MAX; data_len = MIN(space, frame->data_len); + data_len = MIN(data_len, CONFIG_MODEM_CMUX_MTU); /* SOF */ buf[0] = 0xF9; @@ -797,6 +798,12 @@ static void modem_cmux_process_received_byte(struct modem_cmux *cmux, uint8_t by break; } + if (cmux->frame.data_len > CONFIG_MODEM_CMUX_MTU) { + LOG_ERR("Too large frame"); + cmux->receive_state = MODEM_CMUX_RECEIVE_STATE_DROP; + break; + } + /* Check if no data field */ if (cmux->frame.data_len == 0) { /* Await FCS */ @@ -816,6 +823,12 @@ static void modem_cmux_process_received_byte(struct modem_cmux *cmux, uint8_t by /* Get last 8 bits of data length */ cmux->frame.data_len |= ((uint16_t)byte) << 7; + if (cmux->frame.data_len > CONFIG_MODEM_CMUX_MTU) { + LOG_ERR("Too large frame"); + cmux->receive_state = MODEM_CMUX_RECEIVE_STATE_DROP; + break; + } + if (cmux->frame.data_len > cmux->receive_buf_size) { LOG_ERR("Indicated frame data length %u exceeds receive buffer size %u", cmux->frame.data_len, cmux->receive_buf_size); @@ -1239,9 +1252,11 @@ void modem_cmux_init(struct modem_cmux *cmux, const struct modem_cmux_config *co __ASSERT_NO_MSG(cmux != NULL); __ASSERT_NO_MSG(config != NULL); __ASSERT_NO_MSG(config->receive_buf != NULL); - __ASSERT_NO_MSG(config->receive_buf_size >= 126); + __ASSERT_NO_MSG(config->receive_buf_size >= + (CONFIG_MODEM_CMUX_MTU + MODEM_CMUX_FRAME_SIZE_MAX)); __ASSERT_NO_MSG(config->transmit_buf != NULL); - __ASSERT_NO_MSG(config->transmit_buf_size >= 148); + __ASSERT_NO_MSG(config->transmit_buf_size >= + (CONFIG_MODEM_CMUX_MTU + MODEM_CMUX_FRAME_SIZE_MAX)); memset(cmux, 0x00, sizeof(*cmux)); cmux->callback = config->callback; diff --git a/tests/subsys/modem/modem_cmux/prj.conf b/tests/subsys/modem/modem_cmux/prj.conf index 905fe8235d6..55e5ef14f85 100644 --- a/tests/subsys/modem/modem_cmux/prj.conf +++ b/tests/subsys/modem/modem_cmux/prj.conf @@ -5,5 +5,6 @@ CONFIG_NO_OPTIMIZATIONS=y CONFIG_MODEM_MODULES=y CONFIG_MODEM_CMUX=y +CONFIG_MODEM_CMUX_MTU=64 CONFIG_ZTEST=y diff --git a/tests/subsys/modem/modem_cmux/src/main.c b/tests/subsys/modem/modem_cmux/src/main.c index 579dbb8635e..b1adce37cc4 100644 --- a/tests/subsys/modem/modem_cmux/src/main.c +++ b/tests/subsys/modem/modem_cmux/src/main.c @@ -27,6 +27,8 @@ #define EVENT_CMUX_DLCI1_CLOSED BIT(7) #define EVENT_CMUX_DLCI2_CLOSED BIT(8) #define EVENT_CMUX_DISCONNECTED BIT(9) +#define CMUX_BASIC_HRD_SMALL_SIZE 6 +#define CMUX_BASIC_HRD_LARGE_SIZE 7 /*************************************************************************************************/ /* Instances */ @@ -195,6 +197,8 @@ static uint8_t cmux_frame_data_dlci2_ppp_18[] = {0x7E, 0xFF, 0x7D, 0x23, 0xC0, 0 0x7D, 0x22, 0x7D, 0x21, 0x7D, 0x20, 0x7D, 0x24, 0x7D, 0x3C, 0x90, 0x7E}; +static uint8_t cmux_frame_data_large[127] = { [0 ... 126] = 0xAA }; + const static struct modem_backend_mock_transaction transaction_control_cld = { .get = cmux_frame_control_cld_cmd, .get_size = sizeof(cmux_frame_control_cld_cmd), @@ -864,4 +868,22 @@ ZTEST(modem_cmux, test_modem_drop_frames_with_invalid_length) "Incorrect data received"); } +ZTEST(modem_cmux, test_modem_cmux_split_large_data) +{ + int ret; + uint32_t events; + + ret = modem_pipe_transmit(dlci2_pipe, cmux_frame_data_large, + sizeof(cmux_frame_data_large)); + zassert_true(ret == CONFIG_MODEM_CMUX_MTU, "Failed to split large data %d", ret); + + events = k_event_wait(&cmux_event, EVENT_CMUX_DLCI2_TRANSMIT_IDLE, false, K_MSEC(200)); + zassert_equal(events, EVENT_CMUX_DLCI2_TRANSMIT_IDLE, + "Transmit idle event not received for DLCI2 pipe"); + + ret = modem_backend_mock_get(&bus_mock, buffer2, sizeof(buffer2)); + zassert_true(ret == CONFIG_MODEM_CMUX_MTU + CMUX_BASIC_HRD_SMALL_SIZE, + "Incorrect number of bytes transmitted %d", ret); +} + ZTEST_SUITE(modem_cmux, NULL, test_modem_cmux_setup, test_modem_cmux_before, NULL, NULL); diff --git a/tests/subsys/modem/modem_cmux_pair/prj.conf b/tests/subsys/modem/modem_cmux_pair/prj.conf index bf21fcb42ac..57838ca67e3 100644 --- a/tests/subsys/modem/modem_cmux_pair/prj.conf +++ b/tests/subsys/modem/modem_cmux_pair/prj.conf @@ -5,5 +5,6 @@ CONFIG_NO_OPTIMIZATIONS=y CONFIG_MODEM_MODULES=y CONFIG_MODEM_CMUX=y +CONFIG_MODEM_CMUX_MTU=64 CONFIG_ZTEST=y