Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

modem: modem_cellular: Configurable MTU for CMUX #87115

Merged
merged 3 commits into from
Mar 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions doc/releases/migration-guide-4.2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,13 @@ Timer
:kconfig:option:`CONFIG_NATIVE_POSIX_TIMER` has been deprecated in favor of
:kconfig:option:`CONFIG_NATIVE_SIM_TIMER`, (:github:`86612`).

Modem
=====

* Removed Kconfig option :kconfig:option:`CONFIG_MODEM_CELLULAR_CMUX_MAX_FRAME_SIZE` in favor of
:kconfig:option:`CONFIG_MODEM_CMUX_WORK_BUFFER_SIZE` and :kconfig:option:`CONFIG_MODEM_CMUX_MTU`.


Bluetooth
*********

Expand Down
11 changes: 2 additions & 9 deletions drivers/modem/Kconfig.cellular
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 5 additions & 5 deletions drivers/modem/modem_cellular.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,22 +90,22 @@ 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;
struct modem_pipe *dlci1_pipe;
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];
Expand Down
1 change: 0 additions & 1 deletion samples/net/cellular_modem/boards/mg100.conf
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
CONFIG_MODEM_HL7800=n
CONFIG_MODEM_CELLULAR_CMUX_MAX_FRAME_SIZE=255
CONFIG_NET_BUF_TX_COUNT=32
1 change: 0 additions & 1 deletion samples/net/cellular_modem/boards/nrf9160dk_nrf52840.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 0 additions & 1 deletion samples/net/cellular_modem/boards/pinnacle_100_dvk.conf
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
CONFIG_MODEM_HL7800=n
CONFIG_MODEM_CELLULAR_CMUX_MAX_FRAME_SIZE=255
CONFIG_NET_BUF_TX_COUNT=32
28 changes: 26 additions & 2 deletions subsys/modem/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
27 changes: 21 additions & 6 deletions subsys/modem/modem_cmux.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -358,15 +359,15 @@ static int16_t modem_cmux_transmit_data_frame(struct modem_cmux *cmux,
space = ring_buf_space_get(&cmux->transmit_rb);

/*
* Two command frames are reserved for command channel, and we shall prefer
* One command frame is reserved for command channel, and we shall prefer
* waiting for more than MODEM_CMUX_DATA_FRAME_SIZE_MIN bytes available in the
* transmit buffer rather than transmitting a few bytes at a time. This avoids
* excessive wrapping overhead, since transmitting a single byte will require 8
* bytes of wrapping.
*/
if (space < ((MODEM_CMUX_CMD_FRAME_SIZE_MAX * 2) + MODEM_CMUX_DATA_FRAME_SIZE_MIN)) {
if (space < (MODEM_CMUX_CMD_FRAME_SIZE_MAX + MODEM_CMUX_DATA_FRAME_SIZE_MIN)) {
k_mutex_unlock(&cmux->transmit_rb_lock);
return -ENOMEM;
return 0;
}

modem_cmux_log_transmit_frame(frame);
Expand Down Expand Up @@ -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 */
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions tests/subsys/modem/modem_cmux/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ CONFIG_NO_OPTIMIZATIONS=y

CONFIG_MODEM_MODULES=y
CONFIG_MODEM_CMUX=y
CONFIG_MODEM_CMUX_MTU=64

CONFIG_ZTEST=y
22 changes: 22 additions & 0 deletions tests/subsys/modem/modem_cmux/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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);
1 change: 1 addition & 0 deletions tests/subsys/modem/modem_cmux_pair/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ CONFIG_NO_OPTIMIZATIONS=y

CONFIG_MODEM_MODULES=y
CONFIG_MODEM_CMUX=y
CONFIG_MODEM_CMUX_MTU=64

CONFIG_ZTEST=y
Loading