Skip to content

Commit 4b729a0

Browse files
hartkopppelwell
authored andcommitted
can: isotp: add module parameter for maximum pdu size
commit 96d1c81 upstream. 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/[email protected] - use ARRAY_SIZE() to reference DEFAULT_MAX_PDU_SIZE only at one place changes since v1: https://lore.kernel.org/all/[email protected] - limit the minimum 'max_pdu_size' to 4095 to maintain the classic behavior before ISO 15765-2:2016 Link: #5371 Signed-off-by: Oliver Hartkopp <[email protected]> Link: https://lore.kernel.org/all/[email protected] Signed-off-by: Marc Kleine-Budde <[email protected]>
1 parent e1016d6 commit 4b729a0

File tree

1 file changed

+56
-9
lines changed

1 file changed

+56
-9
lines changed

net/can/isotp.c

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,21 @@ MODULE_ALIAS("can-proto-6");
8585

8686
/* ISO 15765-2:2016 supports more than 4095 byte per ISO PDU as the FF_DL can
8787
* 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.
9090
*/
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) ")");
92103

93104
/* N_PCI type values in bits 7-4 of N_PCI bytes */
94105
#define N_PCI_SF 0x00 /* single frame */
@@ -124,13 +135,15 @@ enum {
124135
};
125136

126137
struct tpcon {
127-
unsigned int idx;
138+
u8 *buf;
139+
unsigned int buflen;
128140
unsigned int len;
141+
unsigned int idx;
129142
u32 state;
130143
u8 bs;
131144
u8 sn;
132145
u8 ll_dl;
133-
u8 buf[MAX_MSG_LENGTH + 1];
146+
u8 sbuf[DEFAULT_MAX_PDU_SIZE];
134147
};
135148

136149
struct isotp_sock {
@@ -504,7 +517,17 @@ static int isotp_rcv_ff(struct sock *sk, struct canfd_frame *cf, int ae)
504517
if (so->rx.len + ae + off + ff_pci_sz < so->rx.ll_dl)
505518
return 1;
506519

507-
if (so->rx.len > MAX_MSG_LENGTH) {
520+
/* PDU size > default => try max_pdu_size */
521+
if (so->rx.len > so->rx.buflen && so->rx.buflen < max_pdu_size) {
522+
u8 *newbuf = kmalloc(max_pdu_size, GFP_ATOMIC);
523+
524+
if (newbuf) {
525+
so->rx.buf = newbuf;
526+
so->rx.buflen = max_pdu_size;
527+
}
528+
}
529+
530+
if (so->rx.len > so->rx.buflen) {
508531
/* send FC frame with overflow status */
509532
isotp_send_fc(sk, ae, ISOTP_FC_OVFLW);
510533
return 1;
@@ -808,7 +831,7 @@ static void isotp_create_fframe(struct canfd_frame *cf, struct isotp_sock *so,
808831
cf->data[0] = so->opt.ext_address;
809832

810833
/* create N_PCI bytes with 12/32 bit FF_DL data length */
811-
if (so->tx.len > 4095) {
834+
if (so->tx.len > MAX_12BIT_PDU_SIZE) {
812835
/* use 32 bit FF_DL notation */
813836
cf->data[ae] = N_PCI_FF;
814837
cf->data[ae + 1] = 0;
@@ -948,7 +971,17 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
948971
goto wait_free_buffer;
949972
}
950973

951-
if (!size || size > MAX_MSG_LENGTH) {
974+
/* PDU size > default => try max_pdu_size */
975+
if (size > so->tx.buflen && so->tx.buflen < max_pdu_size) {
976+
u8 *newbuf = kmalloc(max_pdu_size, GFP_KERNEL);
977+
978+
if (newbuf) {
979+
so->tx.buf = newbuf;
980+
so->tx.buflen = max_pdu_size;
981+
}
982+
}
983+
984+
if (!size || size > so->tx.buflen) {
952985
err = -EINVAL;
953986
goto err_out_drop;
954987
}
@@ -1203,6 +1236,12 @@ static int isotp_release(struct socket *sock)
12031236
so->ifindex = 0;
12041237
so->bound = 0;
12051238

1239+
if (so->rx.buf != so->rx.sbuf)
1240+
kfree(so->rx.buf);
1241+
1242+
if (so->tx.buf != so->tx.sbuf)
1243+
kfree(so->tx.buf);
1244+
12061245
sock_orphan(sk);
12071246
sock->sk = NULL;
12081247

@@ -1599,6 +1638,11 @@ static int isotp_init(struct sock *sk)
15991638
so->rx.state = ISOTP_IDLE;
16001639
so->tx.state = ISOTP_IDLE;
16011640

1641+
so->rx.buf = so->rx.sbuf;
1642+
so->tx.buf = so->tx.sbuf;
1643+
so->rx.buflen = ARRAY_SIZE(so->rx.sbuf);
1644+
so->tx.buflen = ARRAY_SIZE(so->tx.sbuf);
1645+
16021646
hrtimer_init(&so->rxtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);
16031647
so->rxtimer.function = isotp_rx_timer_handler;
16041648
hrtimer_init(&so->txtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);
@@ -1681,7 +1725,10 @@ static __init int isotp_module_init(void)
16811725
{
16821726
int err;
16831727

1684-
pr_info("can: isotp protocol\n");
1728+
max_pdu_size = max_t(unsigned int, max_pdu_size, MAX_12BIT_PDU_SIZE);
1729+
max_pdu_size = min_t(unsigned int, max_pdu_size, MAX_PDU_SIZE);
1730+
1731+
pr_info("can: isotp protocol (max_pdu_size %d)\n", max_pdu_size);
16851732

16861733
err = can_proto_register(&isotp_can_proto);
16871734
if (err < 0)

0 commit comments

Comments
 (0)