Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

can: isotp: add module parameter for maximum pdu size

With ISO 15765-2:2016 the PDU size is not limited to 2^12 - 1 (4095)
bytes but can be represented as a 32 bit unsigned integer value which
allows 2^32 - 1 bytes (~4GB). The use-cases like automotive unified
diagnostic services (UDS) and flashing of ECUs still use the small
static buffers which are provided at socket creation time.

When a use-case requires to transfer PDUs up to 1025 kByte the maximum
PDU size can now be extended by setting the module parameter
max_pdu_size. The extended size buffers are only allocated on a
per-socket/connection base when needed at run-time.

changes since v2: https://lore.kernel.org/all/20230313172510.3851-1-socketcan@hartkopp.net
- use ARRAY_SIZE() to reference DEFAULT_MAX_PDU_SIZE only at one place

changes since v1: https://lore.kernel.org/all/20230311143446.3183-1-socketcan@hartkopp.net
- limit the minimum 'max_pdu_size' to 4095 to maintain the classic
behavior before ISO 15765-2:2016

Link: https://github.com/raspberrypi/linux/issues/5371
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Link: https://lore.kernel.org/all/20230326115911.15094-1-socketcan@hartkopp.net
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

authored by

Oliver Hartkopp and committed by
Marc Kleine-Budde
96d1c81e 4cee0fb9

+56 -9
+56 -9
net/can/isotp.c
··· 85 85 86 86 /* ISO 15765-2:2016 supports more than 4095 byte per ISO PDU as the FF_DL can 87 87 * take full 32 bit values (4 Gbyte). We would need some good concept to handle 88 - * this between user space and kernel space. For now increase the static buffer 89 - * to something about 64 kbyte to be able to test this new functionality. 88 + * this between user space and kernel space. For now set the static buffer to 89 + * something about 8 kbyte to be able to test this new functionality. 90 90 */ 91 - #define MAX_MSG_LENGTH 66000 91 + #define DEFAULT_MAX_PDU_SIZE 8300 92 + 93 + /* maximum PDU size before ISO 15765-2:2016 extension was 4095 */ 94 + #define MAX_12BIT_PDU_SIZE 4095 95 + 96 + /* limit the isotp pdu size from the optional module parameter to 1MByte */ 97 + #define MAX_PDU_SIZE (1025 * 1024U) 98 + 99 + static unsigned int max_pdu_size __read_mostly = DEFAULT_MAX_PDU_SIZE; 100 + module_param(max_pdu_size, uint, 0444); 101 + MODULE_PARM_DESC(max_pdu_size, "maximum isotp pdu size (default " 102 + __stringify(DEFAULT_MAX_PDU_SIZE) ")"); 92 103 93 104 /* N_PCI type values in bits 7-4 of N_PCI bytes */ 94 105 #define N_PCI_SF 0x00 /* single frame */ ··· 134 123 }; 135 124 136 125 struct tpcon { 137 - unsigned int idx; 126 + u8 *buf; 127 + unsigned int buflen; 138 128 unsigned int len; 129 + unsigned int idx; 139 130 u32 state; 140 131 u8 bs; 141 132 u8 sn; 142 133 u8 ll_dl; 143 - u8 buf[MAX_MSG_LENGTH + 1]; 134 + u8 sbuf[DEFAULT_MAX_PDU_SIZE]; 144 135 }; 145 136 146 137 struct isotp_sock { ··· 516 503 if (so->rx.len + ae + off + ff_pci_sz < so->rx.ll_dl) 517 504 return 1; 518 505 519 - if (so->rx.len > MAX_MSG_LENGTH) { 506 + /* PDU size > default => try max_pdu_size */ 507 + if (so->rx.len > so->rx.buflen && so->rx.buflen < max_pdu_size) { 508 + u8 *newbuf = kmalloc(max_pdu_size, GFP_ATOMIC); 509 + 510 + if (newbuf) { 511 + so->rx.buf = newbuf; 512 + so->rx.buflen = max_pdu_size; 513 + } 514 + } 515 + 516 + if (so->rx.len > so->rx.buflen) { 520 517 /* send FC frame with overflow status */ 521 518 isotp_send_fc(sk, ae, ISOTP_FC_OVFLW); 522 519 return 1; ··· 830 807 cf->data[0] = so->opt.ext_address; 831 808 832 809 /* create N_PCI bytes with 12/32 bit FF_DL data length */ 833 - if (so->tx.len > 4095) { 810 + if (so->tx.len > MAX_12BIT_PDU_SIZE) { 834 811 /* use 32 bit FF_DL notation */ 835 812 cf->data[ae] = N_PCI_FF; 836 813 cf->data[ae + 1] = 0; ··· 970 947 so->tx.state = ISOTP_SENDING; 971 948 } 972 949 973 - if (!size || size > MAX_MSG_LENGTH) { 950 + /* PDU size > default => try max_pdu_size */ 951 + if (size > so->tx.buflen && so->tx.buflen < max_pdu_size) { 952 + u8 *newbuf = kmalloc(max_pdu_size, GFP_KERNEL); 953 + 954 + if (newbuf) { 955 + so->tx.buf = newbuf; 956 + so->tx.buflen = max_pdu_size; 957 + } 958 + } 959 + 960 + if (!size || size > so->tx.buflen) { 974 961 err = -EINVAL; 975 962 goto err_out_drop; 976 963 } ··· 1227 1194 1228 1195 so->ifindex = 0; 1229 1196 so->bound = 0; 1197 + 1198 + if (so->rx.buf != so->rx.sbuf) 1199 + kfree(so->rx.buf); 1200 + 1201 + if (so->tx.buf != so->tx.sbuf) 1202 + kfree(so->tx.buf); 1230 1203 1231 1204 sock_orphan(sk); 1232 1205 sock->sk = NULL; ··· 1630 1591 so->rx.state = ISOTP_IDLE; 1631 1592 so->tx.state = ISOTP_IDLE; 1632 1593 1594 + so->rx.buf = so->rx.sbuf; 1595 + so->tx.buf = so->tx.sbuf; 1596 + so->rx.buflen = ARRAY_SIZE(so->rx.sbuf); 1597 + so->tx.buflen = ARRAY_SIZE(so->tx.sbuf); 1598 + 1633 1599 hrtimer_init(&so->rxtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT); 1634 1600 so->rxtimer.function = isotp_rx_timer_handler; 1635 1601 hrtimer_init(&so->txtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT); ··· 1702 1658 { 1703 1659 int err; 1704 1660 1705 - pr_info("can: isotp protocol\n"); 1661 + max_pdu_size = max_t(unsigned int, max_pdu_size, MAX_12BIT_PDU_SIZE); 1662 + max_pdu_size = min_t(unsigned int, max_pdu_size, MAX_PDU_SIZE); 1663 + 1664 + pr_info("can: isotp protocol (max_pdu_size %d)\n", max_pdu_size); 1706 1665 1707 1666 err = can_proto_register(&isotp_can_proto); 1708 1667 if (err < 0)