Skip to content

Commit 61e5849

Browse files
SeppoTakalonordicjm
authored andcommitted
[nrf fromtree] modem: modem_cellular: Configurable MTU for CMUX
Allow configuring MTU for CMUX. Some AT manual and specification define this as a frame size. Linux ldattach default to 127 bytes, 3GPP TS 27.010 defaults to 31. We should limit our CMUX frames to a size that remote end is capable of handling. Linux silently drops oversized frames. Also, remove MODEM_CELLULAR_CMUX_MAX_FRAME_SIZE as this was only limiting a buffer sizes, and resulted CMUX frames to be capped to same value. Use MODEM_CMUX_WORK_BUFFER_SIZE and MODEM_CMUX_MTU instead. Also rename CONFIG_MODEM_CELLULAR_CHAT_BUFFER_SIZES to CONFIG_MODEM_CELLULAR_CHAT_BUFFER_SIZE as it is now only used as a Chat module. DLCI pipes use CONFIG_MODEM_CMUX_WORK_BUFFER_SIZE. Signed-off-by: Seppo Takalo <[email protected]> (cherry picked from commit c78081e)
1 parent 999e700 commit 61e5849

File tree

11 files changed

+75
-23
lines changed

11 files changed

+75
-23
lines changed

drivers/modem/Kconfig.cellular

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,8 @@ config MODEM_CELLULAR_UART_BUFFER_SIZES
4242
int "The UART receive and transmit buffer sizes in bytes."
4343
default 512
4444

45-
config MODEM_CELLULAR_CMUX_MAX_FRAME_SIZE
46-
int "The maximum CMUX frame size in bytes."
47-
default 32 if DT_HAS_U_BLOX_LARA_R6_ENABLED
48-
default 128
49-
help
50-
This value affects the size of buffers used to receive and transmit CMUX frames.
51-
52-
config MODEM_CELLULAR_CHAT_BUFFER_SIZES
53-
int "The size of the buffers used for the chat scripts in bytes."
45+
config MODEM_CELLULAR_CHAT_BUFFER_SIZE
46+
int "The size of the buffer used for the chat scripts in bytes."
5447
default 128
5548

5649
config MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES

drivers/modem/modem_cellular.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,22 +90,22 @@ struct modem_cellular_data {
9090

9191
/* CMUX */
9292
struct modem_cmux cmux;
93-
uint8_t cmux_receive_buf[CONFIG_MODEM_CELLULAR_CMUX_MAX_FRAME_SIZE];
94-
uint8_t cmux_transmit_buf[2 * CONFIG_MODEM_CELLULAR_CMUX_MAX_FRAME_SIZE];
93+
uint8_t cmux_receive_buf[CONFIG_MODEM_CMUX_WORK_BUFFER_SIZE];
94+
uint8_t cmux_transmit_buf[CONFIG_MODEM_CMUX_WORK_BUFFER_SIZE];
9595

9696
struct modem_cmux_dlci dlci1;
9797
struct modem_cmux_dlci dlci2;
9898
struct modem_pipe *dlci1_pipe;
9999
struct modem_pipe *dlci2_pipe;
100100
/* Points to dlci2_pipe or NULL. Used for shutdown script if not NULL */
101101
struct modem_pipe *cmd_pipe;
102-
uint8_t dlci1_receive_buf[CONFIG_MODEM_CELLULAR_CMUX_MAX_FRAME_SIZE];
102+
uint8_t dlci1_receive_buf[CONFIG_MODEM_CMUX_WORK_BUFFER_SIZE];
103103
/* DLCI 2 is only used for chat scripts. */
104-
uint8_t dlci2_receive_buf[CONFIG_MODEM_CELLULAR_CHAT_BUFFER_SIZES];
104+
uint8_t dlci2_receive_buf[CONFIG_MODEM_CMUX_WORK_BUFFER_SIZE];
105105

106106
/* Modem chat */
107107
struct modem_chat chat;
108-
uint8_t chat_receive_buf[CONFIG_MODEM_CELLULAR_CHAT_BUFFER_SIZES];
108+
uint8_t chat_receive_buf[CONFIG_MODEM_CELLULAR_CHAT_BUFFER_SIZE];
109109
uint8_t *chat_delimiter;
110110
uint8_t *chat_filter;
111111
uint8_t *chat_argv[32];
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
CONFIG_MODEM_HL7800=n
2-
CONFIG_MODEM_CELLULAR_CMUX_MAX_FRAME_SIZE=255
32
CONFIG_NET_BUF_TX_COUNT=32

samples/net/cellular_modem/boards/nrf9160dk_nrf52840.conf

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ CONFIG_UART_1_ASYNC=y
33
CONFIG_UART_1_INTERRUPT_DRIVEN=n
44

55
# Align with the Serial LTE Modem (SLM) application.
6-
CONFIG_MODEM_CELLULAR_CMUX_MAX_FRAME_SIZE=1500
76
CONFIG_MODEM_CELLULAR_UART_BUFFER_SIZES=6000
87

98
# Print logs and printk() output on uart0.

samples/net/cellular_modem/boards/nrf9160dk_nrf9160_ns.conf

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ CONFIG_UART_1_ASYNC=y
33
CONFIG_UART_1_INTERRUPT_DRIVEN=n
44

55
# Align with the Serial LTE Modem (SLM) application.
6-
CONFIG_MODEM_CELLULAR_CMUX_MAX_FRAME_SIZE=1500
76
CONFIG_MODEM_CELLULAR_UART_BUFFER_SIZES=6000
87

98
# Prevent sockets getting offloaded to the modem.
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
CONFIG_MODEM_HL7800=n
2-
CONFIG_MODEM_CELLULAR_CMUX_MAX_FRAME_SIZE=255
32
CONFIG_NET_BUF_TX_COUNT=32

subsys/modem/Kconfig

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,34 @@ config MODEM_CMUX
2929

3030
if MODEM_CMUX
3131

32+
config MODEM_CMUX_DEFAULT_MTU_127
33+
bool
34+
default y if (DT_HAS_QUECTEL_BG95_ENABLED || DT_HAS_QUECTEL_EG25_G_ENABLED || \
35+
DT_HAS_SIMCOM_SIM7080_ENABLED || DT_HAS_U_BLOX_SARA_R4_ENABLED || \
36+
DT_HAS_U_BLOX_SARA_R5_ENABLED || DT_HAS_SWIR_HL7800_ENABLED || \
37+
DT_HAS_TELIT_ME910G1_ENABLED || DT_HAS_TELIT_ME310G1_ENABLED || \
38+
DT_HAS_SQN_GM02S_ENABLED)
39+
help
40+
Use the default MTU size of 127 bytes for the CMUX module on certain modems.
41+
This must match the AT+CMUX commands in the modem_cellular driver.
42+
43+
config MODEM_CMUX_MTU
44+
int "CMUX MTU size in bytes"
45+
range 16 1500
46+
default 127 if MODEM_CMUX_DEFAULT_MTU_127
47+
default 31
48+
help
49+
Maximum Transmission Unit (MTU) size for the CMUX module.
50+
Linux ldattach defaults to 127 bytes, 3GPP TS 27.010 to 31.
51+
3252
config MODEM_CMUX_WORK_BUFFER_SIZE
3353
int "CMUX module work buffer size in bytes"
34-
range 16 1500
35-
default 64
54+
range 23 1507
55+
default 134 if MODEM_CMUX_DEFAULT_MTU_127
56+
default 38
57+
help
58+
Size of the work buffer used by the CMUX module.
59+
Recommended size is MODEM_CMUX_MTU + 7 (CMUX header size).
3660

3761
module = MODEM_CMUX
3862
module-str = modem_cmux

subsys/modem/modem_cmux.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ LOG_MODULE_REGISTER(modem_cmux, CONFIG_MODEM_CMUX_LOG_LEVEL);
1818
#define MODEM_CMUX_EA (0x01)
1919
#define MODEM_CMUX_CR (0x02)
2020
#define MODEM_CMUX_PF (0x10)
21-
#define MODEM_CMUX_FRAME_SIZE_MAX (0x08)
21+
#define MODEM_CMUX_FRAME_SIZE_MAX (0x07)
2222
#define MODEM_CMUX_DATA_SIZE_MIN (0x08)
2323
#define MODEM_CMUX_DATA_FRAME_SIZE_MIN (MODEM_CMUX_FRAME_SIZE_MAX + \
2424
MODEM_CMUX_DATA_SIZE_MIN)
@@ -274,6 +274,7 @@ static uint16_t modem_cmux_transmit_frame(struct modem_cmux *cmux,
274274

275275
space = ring_buf_space_get(&cmux->transmit_rb) - MODEM_CMUX_FRAME_SIZE_MAX;
276276
data_len = MIN(space, frame->data_len);
277+
data_len = MIN(data_len, CONFIG_MODEM_CMUX_MTU);
277278

278279
/* SOF */
279280
buf[0] = 0xF9;
@@ -797,6 +798,12 @@ static void modem_cmux_process_received_byte(struct modem_cmux *cmux, uint8_t by
797798
break;
798799
}
799800

801+
if (cmux->frame.data_len > CONFIG_MODEM_CMUX_MTU) {
802+
LOG_ERR("Too large frame");
803+
cmux->receive_state = MODEM_CMUX_RECEIVE_STATE_DROP;
804+
break;
805+
}
806+
800807
/* Check if no data field */
801808
if (cmux->frame.data_len == 0) {
802809
/* Await FCS */
@@ -816,6 +823,12 @@ static void modem_cmux_process_received_byte(struct modem_cmux *cmux, uint8_t by
816823
/* Get last 8 bits of data length */
817824
cmux->frame.data_len |= ((uint16_t)byte) << 7;
818825

826+
if (cmux->frame.data_len > CONFIG_MODEM_CMUX_MTU) {
827+
LOG_ERR("Too large frame");
828+
cmux->receive_state = MODEM_CMUX_RECEIVE_STATE_DROP;
829+
break;
830+
}
831+
819832
if (cmux->frame.data_len > cmux->receive_buf_size) {
820833
LOG_ERR("Indicated frame data length %u exceeds receive buffer size %u",
821834
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
12391252
__ASSERT_NO_MSG(cmux != NULL);
12401253
__ASSERT_NO_MSG(config != NULL);
12411254
__ASSERT_NO_MSG(config->receive_buf != NULL);
1242-
__ASSERT_NO_MSG(config->receive_buf_size >= 126);
1255+
__ASSERT_NO_MSG(config->receive_buf_size >=
1256+
(CONFIG_MODEM_CMUX_MTU + MODEM_CMUX_FRAME_SIZE_MAX));
12431257
__ASSERT_NO_MSG(config->transmit_buf != NULL);
1244-
__ASSERT_NO_MSG(config->transmit_buf_size >= 148);
1258+
__ASSERT_NO_MSG(config->transmit_buf_size >=
1259+
(CONFIG_MODEM_CMUX_MTU + MODEM_CMUX_FRAME_SIZE_MAX));
12451260

12461261
memset(cmux, 0x00, sizeof(*cmux));
12471262
cmux->callback = config->callback;

tests/subsys/modem/modem_cmux/prj.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ CONFIG_NO_OPTIMIZATIONS=y
55

66
CONFIG_MODEM_MODULES=y
77
CONFIG_MODEM_CMUX=y
8+
CONFIG_MODEM_CMUX_MTU=64
89

910
CONFIG_ZTEST=y

tests/subsys/modem/modem_cmux/src/main.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
#define EVENT_CMUX_DLCI1_CLOSED BIT(7)
2828
#define EVENT_CMUX_DLCI2_CLOSED BIT(8)
2929
#define EVENT_CMUX_DISCONNECTED BIT(9)
30+
#define CMUX_BASIC_HRD_SMALL_SIZE 6
31+
#define CMUX_BASIC_HRD_LARGE_SIZE 7
3032

3133
/*************************************************************************************************/
3234
/* Instances */
@@ -195,6 +197,8 @@ static uint8_t cmux_frame_data_dlci2_ppp_18[] = {0x7E, 0xFF, 0x7D, 0x23, 0xC0, 0
195197
0x7D, 0x22, 0x7D, 0x21, 0x7D, 0x20,
196198
0x7D, 0x24, 0x7D, 0x3C, 0x90, 0x7E};
197199

200+
static uint8_t cmux_frame_data_large[127] = { [0 ... 126] = 0xAA };
201+
198202
const static struct modem_backend_mock_transaction transaction_control_cld = {
199203
.get = cmux_frame_control_cld_cmd,
200204
.get_size = sizeof(cmux_frame_control_cld_cmd),
@@ -864,4 +868,22 @@ ZTEST(modem_cmux, test_modem_drop_frames_with_invalid_length)
864868
"Incorrect data received");
865869
}
866870

871+
ZTEST(modem_cmux, test_modem_cmux_split_large_data)
872+
{
873+
int ret;
874+
uint32_t events;
875+
876+
ret = modem_pipe_transmit(dlci2_pipe, cmux_frame_data_large,
877+
sizeof(cmux_frame_data_large));
878+
zassert_true(ret == CONFIG_MODEM_CMUX_MTU, "Failed to split large data %d", ret);
879+
880+
events = k_event_wait(&cmux_event, EVENT_CMUX_DLCI2_TRANSMIT_IDLE, false, K_MSEC(200));
881+
zassert_equal(events, EVENT_CMUX_DLCI2_TRANSMIT_IDLE,
882+
"Transmit idle event not received for DLCI2 pipe");
883+
884+
ret = modem_backend_mock_get(&bus_mock, buffer2, sizeof(buffer2));
885+
zassert_true(ret == CONFIG_MODEM_CMUX_MTU + CMUX_BASIC_HRD_SMALL_SIZE,
886+
"Incorrect number of bytes transmitted %d", ret);
887+
}
888+
867889
ZTEST_SUITE(modem_cmux, NULL, test_modem_cmux_setup, test_modem_cmux_before, NULL, NULL);

0 commit comments

Comments
 (0)