xref: /linux/drivers/net/mctp/mctp-serial.c (revision 3a39d672e7f48b8d6b91a09afa4b55352773b4b5)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Management Component Transport Protocol (MCTP) - serial transport
4  * binding. This driver is an implementation of the DMTF specificiation
5  * "DSP0253 - Management Component Transport Protocol (MCTP) Serial Transport
6  * Binding", available at:
7  *
8  *  https://www.dmtf.org/sites/default/files/standards/documents/DSP0253_1.0.0.pdf
9  *
10  * This driver provides DSP0253-type MCTP-over-serial transport using a Linux
11  * tty device, by setting the N_MCTP line discipline on the tty.
12  *
13  * Copyright (c) 2021 Code Construct
14  */
15 
16 #include <linux/idr.h>
17 #include <linux/if_arp.h>
18 #include <linux/module.h>
19 #include <linux/skbuff.h>
20 #include <linux/tty.h>
21 #include <linux/workqueue.h>
22 #include <linux/crc-ccitt.h>
23 
24 #include <linux/mctp.h>
25 #include <net/mctp.h>
26 #include <net/pkt_sched.h>
27 
28 #define MCTP_SERIAL_MTU		68 /* base mtu (64) + mctp header */
29 #define MCTP_SERIAL_FRAME_MTU	(MCTP_SERIAL_MTU + 6) /* + serial framing */
30 
31 #define MCTP_SERIAL_VERSION	0x1 /* DSP0253 defines a single version: 1 */
32 
33 #define BUFSIZE			MCTP_SERIAL_FRAME_MTU
34 
35 #define BYTE_FRAME		0x7e
36 #define BYTE_ESC		0x7d
37 
38 #define FCS_INIT		0xffff
39 
40 static DEFINE_IDA(mctp_serial_ida);
41 
42 enum mctp_serial_state {
43 	STATE_IDLE,
44 	STATE_START,
45 	STATE_HEADER,
46 	STATE_DATA,
47 	STATE_ESCAPE,
48 	STATE_TRAILER,
49 	STATE_DONE,
50 	STATE_ERR,
51 };
52 
53 struct mctp_serial {
54 	struct net_device	*netdev;
55 	struct tty_struct	*tty;
56 
57 	int			idx;
58 
59 	/* protects our rx & tx state machines; held during both paths */
60 	spinlock_t		lock;
61 
62 	struct work_struct	tx_work;
63 	enum mctp_serial_state	txstate, rxstate;
64 	u16			txfcs, rxfcs, rxfcs_rcvd;
65 	unsigned int		txlen, rxlen;
66 	unsigned int		txpos, rxpos;
67 	u8			txbuf[BUFSIZE],
68 				rxbuf[BUFSIZE];
69 };
70 
needs_escape(u8 c)71 static bool needs_escape(u8 c)
72 {
73 	return c == BYTE_ESC || c == BYTE_FRAME;
74 }
75 
next_chunk_len(struct mctp_serial * dev)76 static unsigned int next_chunk_len(struct mctp_serial *dev)
77 {
78 	unsigned int i;
79 
80 	/* either we have no bytes to send ... */
81 	if (dev->txpos == dev->txlen)
82 		return 0;
83 
84 	/* ... or the next byte to send is an escaped byte; requiring a
85 	 * single-byte chunk...
86 	 */
87 	if (needs_escape(dev->txbuf[dev->txpos]))
88 		return 1;
89 
90 	/* ... or we have one or more bytes up to the next escape - this chunk
91 	 * will be those non-escaped bytes, and does not include the escaped
92 	 * byte.
93 	 */
94 	for (i = 1; i + dev->txpos < dev->txlen; i++) {
95 		if (needs_escape(dev->txbuf[dev->txpos + i]))
96 			break;
97 	}
98 
99 	return i;
100 }
101 
write_chunk(struct mctp_serial * dev,u8 * buf,size_t len)102 static ssize_t write_chunk(struct mctp_serial *dev, u8 *buf, size_t len)
103 {
104 	return dev->tty->ops->write(dev->tty, buf, len);
105 }
106 
mctp_serial_tx_work(struct work_struct * work)107 static void mctp_serial_tx_work(struct work_struct *work)
108 {
109 	struct mctp_serial *dev = container_of(work, struct mctp_serial,
110 					       tx_work);
111 	unsigned long flags;
112 	ssize_t txlen;
113 	unsigned int len;
114 	u8 c, buf[3];
115 
116 	spin_lock_irqsave(&dev->lock, flags);
117 
118 	/* txstate represents the next thing to send */
119 	switch (dev->txstate) {
120 	case STATE_START:
121 		dev->txpos = 0;
122 		fallthrough;
123 	case STATE_HEADER:
124 		buf[0] = BYTE_FRAME;
125 		buf[1] = MCTP_SERIAL_VERSION;
126 		buf[2] = dev->txlen;
127 
128 		if (!dev->txpos)
129 			dev->txfcs = crc_ccitt(FCS_INIT, buf + 1, 2);
130 
131 		txlen = write_chunk(dev, buf + dev->txpos, 3 - dev->txpos);
132 		if (txlen <= 0) {
133 			dev->txstate = STATE_ERR;
134 		} else {
135 			dev->txpos += txlen;
136 			if (dev->txpos == 3) {
137 				dev->txstate = STATE_DATA;
138 				dev->txpos = 0;
139 			}
140 		}
141 		break;
142 
143 	case STATE_ESCAPE:
144 		buf[0] = dev->txbuf[dev->txpos] & ~0x20;
145 		txlen = write_chunk(dev, buf, 1);
146 		if (txlen <= 0) {
147 			dev->txstate = STATE_ERR;
148 		} else {
149 			dev->txpos += txlen;
150 			if (dev->txpos == dev->txlen) {
151 				dev->txstate = STATE_TRAILER;
152 				dev->txpos = 0;
153 			}
154 		}
155 
156 		break;
157 
158 	case STATE_DATA:
159 		len = next_chunk_len(dev);
160 		if (len) {
161 			c = dev->txbuf[dev->txpos];
162 			if (len == 1 && needs_escape(c)) {
163 				buf[0] = BYTE_ESC;
164 				buf[1] = c & ~0x20;
165 				dev->txfcs = crc_ccitt_byte(dev->txfcs, c);
166 				txlen = write_chunk(dev, buf, 2);
167 				if (txlen == 2)
168 					dev->txpos++;
169 				else if (txlen == 1)
170 					dev->txstate = STATE_ESCAPE;
171 				else
172 					dev->txstate = STATE_ERR;
173 			} else {
174 				txlen = write_chunk(dev,
175 						    dev->txbuf + dev->txpos,
176 						    len);
177 				if (txlen <= 0) {
178 					dev->txstate = STATE_ERR;
179 				} else {
180 					dev->txfcs = crc_ccitt(dev->txfcs,
181 							       dev->txbuf +
182 							       dev->txpos,
183 							       txlen);
184 					dev->txpos += txlen;
185 				}
186 			}
187 			if (dev->txstate == STATE_DATA &&
188 			    dev->txpos == dev->txlen) {
189 				dev->txstate = STATE_TRAILER;
190 				dev->txpos = 0;
191 			}
192 			break;
193 		}
194 		dev->txstate = STATE_TRAILER;
195 		dev->txpos = 0;
196 		fallthrough;
197 
198 	case STATE_TRAILER:
199 		buf[0] = dev->txfcs >> 8;
200 		buf[1] = dev->txfcs & 0xff;
201 		buf[2] = BYTE_FRAME;
202 		txlen = write_chunk(dev, buf + dev->txpos, 3 - dev->txpos);
203 		if (txlen <= 0) {
204 			dev->txstate = STATE_ERR;
205 		} else {
206 			dev->txpos += txlen;
207 			if (dev->txpos == 3) {
208 				dev->txstate = STATE_DONE;
209 				dev->txpos = 0;
210 			}
211 		}
212 		break;
213 	default:
214 		netdev_err_once(dev->netdev, "invalid tx state %d\n",
215 				dev->txstate);
216 	}
217 
218 	if (dev->txstate == STATE_DONE) {
219 		dev->netdev->stats.tx_packets++;
220 		dev->netdev->stats.tx_bytes += dev->txlen;
221 		dev->txlen = 0;
222 		dev->txpos = 0;
223 		clear_bit(TTY_DO_WRITE_WAKEUP, &dev->tty->flags);
224 		dev->txstate = STATE_IDLE;
225 		spin_unlock_irqrestore(&dev->lock, flags);
226 
227 		netif_wake_queue(dev->netdev);
228 	} else {
229 		spin_unlock_irqrestore(&dev->lock, flags);
230 	}
231 }
232 
mctp_serial_tx(struct sk_buff * skb,struct net_device * ndev)233 static netdev_tx_t mctp_serial_tx(struct sk_buff *skb, struct net_device *ndev)
234 {
235 	struct mctp_serial *dev = netdev_priv(ndev);
236 	unsigned long flags;
237 
238 	WARN_ON(dev->txstate != STATE_IDLE);
239 
240 	if (skb->len > MCTP_SERIAL_MTU) {
241 		dev->netdev->stats.tx_dropped++;
242 		goto out;
243 	}
244 
245 	spin_lock_irqsave(&dev->lock, flags);
246 	netif_stop_queue(dev->netdev);
247 	skb_copy_bits(skb, 0, dev->txbuf, skb->len);
248 	dev->txpos = 0;
249 	dev->txlen = skb->len;
250 	dev->txstate = STATE_START;
251 	spin_unlock_irqrestore(&dev->lock, flags);
252 
253 	set_bit(TTY_DO_WRITE_WAKEUP, &dev->tty->flags);
254 	schedule_work(&dev->tx_work);
255 
256 out:
257 	kfree_skb(skb);
258 	return NETDEV_TX_OK;
259 }
260 
mctp_serial_tty_write_wakeup(struct tty_struct * tty)261 static void mctp_serial_tty_write_wakeup(struct tty_struct *tty)
262 {
263 	struct mctp_serial *dev = tty->disc_data;
264 
265 	schedule_work(&dev->tx_work);
266 }
267 
mctp_serial_rx(struct mctp_serial * dev)268 static void mctp_serial_rx(struct mctp_serial *dev)
269 {
270 	struct mctp_skb_cb *cb;
271 	struct sk_buff *skb;
272 
273 	if (dev->rxfcs != dev->rxfcs_rcvd) {
274 		dev->netdev->stats.rx_dropped++;
275 		dev->netdev->stats.rx_crc_errors++;
276 		return;
277 	}
278 
279 	skb = netdev_alloc_skb(dev->netdev, dev->rxlen);
280 	if (!skb) {
281 		dev->netdev->stats.rx_dropped++;
282 		return;
283 	}
284 
285 	skb->protocol = htons(ETH_P_MCTP);
286 	skb_put_data(skb, dev->rxbuf, dev->rxlen);
287 	skb_reset_network_header(skb);
288 
289 	cb = __mctp_cb(skb);
290 	cb->halen = 0;
291 
292 	netif_rx(skb);
293 	dev->netdev->stats.rx_packets++;
294 	dev->netdev->stats.rx_bytes += dev->rxlen;
295 }
296 
mctp_serial_push_header(struct mctp_serial * dev,u8 c)297 static void mctp_serial_push_header(struct mctp_serial *dev, u8 c)
298 {
299 	switch (dev->rxpos) {
300 	case 0:
301 		if (c == BYTE_FRAME)
302 			dev->rxpos++;
303 		else
304 			dev->rxstate = STATE_ERR;
305 		break;
306 	case 1:
307 		if (c == MCTP_SERIAL_VERSION) {
308 			dev->rxpos++;
309 			dev->rxfcs = crc_ccitt_byte(FCS_INIT, c);
310 		} else {
311 			dev->rxstate = STATE_ERR;
312 		}
313 		break;
314 	case 2:
315 		if (c > MCTP_SERIAL_FRAME_MTU) {
316 			dev->rxstate = STATE_ERR;
317 		} else {
318 			dev->rxlen = c;
319 			dev->rxpos = 0;
320 			dev->rxstate = STATE_DATA;
321 			dev->rxfcs = crc_ccitt_byte(dev->rxfcs, c);
322 		}
323 		break;
324 	}
325 }
326 
mctp_serial_push_trailer(struct mctp_serial * dev,u8 c)327 static void mctp_serial_push_trailer(struct mctp_serial *dev, u8 c)
328 {
329 	switch (dev->rxpos) {
330 	case 0:
331 		dev->rxfcs_rcvd = c << 8;
332 		dev->rxpos++;
333 		break;
334 	case 1:
335 		dev->rxfcs_rcvd |= c;
336 		dev->rxpos++;
337 		break;
338 	case 2:
339 		if (c != BYTE_FRAME) {
340 			dev->rxstate = STATE_ERR;
341 		} else {
342 			mctp_serial_rx(dev);
343 			dev->rxlen = 0;
344 			dev->rxpos = 0;
345 			dev->rxstate = STATE_IDLE;
346 		}
347 		break;
348 	}
349 }
350 
mctp_serial_push(struct mctp_serial * dev,u8 c)351 static void mctp_serial_push(struct mctp_serial *dev, u8 c)
352 {
353 	switch (dev->rxstate) {
354 	case STATE_IDLE:
355 		dev->rxstate = STATE_HEADER;
356 		fallthrough;
357 	case STATE_HEADER:
358 		mctp_serial_push_header(dev, c);
359 		break;
360 
361 	case STATE_ESCAPE:
362 		c |= 0x20;
363 		fallthrough;
364 	case STATE_DATA:
365 		if (dev->rxstate != STATE_ESCAPE && c == BYTE_ESC) {
366 			dev->rxstate = STATE_ESCAPE;
367 		} else {
368 			dev->rxfcs = crc_ccitt_byte(dev->rxfcs, c);
369 			dev->rxbuf[dev->rxpos] = c;
370 			dev->rxpos++;
371 			dev->rxstate = STATE_DATA;
372 			if (dev->rxpos == dev->rxlen) {
373 				dev->rxpos = 0;
374 				dev->rxstate = STATE_TRAILER;
375 			}
376 		}
377 		break;
378 
379 	case STATE_TRAILER:
380 		mctp_serial_push_trailer(dev, c);
381 		break;
382 
383 	case STATE_ERR:
384 		if (c == BYTE_FRAME)
385 			dev->rxstate = STATE_IDLE;
386 		break;
387 
388 	default:
389 		netdev_err_once(dev->netdev, "invalid rx state %d\n",
390 				dev->rxstate);
391 	}
392 }
393 
mctp_serial_tty_receive_buf(struct tty_struct * tty,const u8 * c,const u8 * f,size_t len)394 static void mctp_serial_tty_receive_buf(struct tty_struct *tty, const u8 *c,
395 					const u8 *f, size_t len)
396 {
397 	struct mctp_serial *dev = tty->disc_data;
398 	size_t i;
399 
400 	if (!netif_running(dev->netdev))
401 		return;
402 
403 	/* we don't (currently) use the flag bytes, just data. */
404 	for (i = 0; i < len; i++)
405 		mctp_serial_push(dev, c[i]);
406 }
407 
mctp_serial_uninit(struct net_device * ndev)408 static void mctp_serial_uninit(struct net_device *ndev)
409 {
410 	struct mctp_serial *dev = netdev_priv(ndev);
411 
412 	cancel_work_sync(&dev->tx_work);
413 }
414 
415 static const struct net_device_ops mctp_serial_netdev_ops = {
416 	.ndo_start_xmit = mctp_serial_tx,
417 	.ndo_uninit = mctp_serial_uninit,
418 };
419 
mctp_serial_setup(struct net_device * ndev)420 static void mctp_serial_setup(struct net_device *ndev)
421 {
422 	ndev->type = ARPHRD_MCTP;
423 
424 	/* we limit at the fixed MTU, which is also the MCTP-standard
425 	 * baseline MTU, so is also our minimum
426 	 */
427 	ndev->mtu = MCTP_SERIAL_MTU;
428 	ndev->max_mtu = MCTP_SERIAL_MTU;
429 	ndev->min_mtu = MCTP_SERIAL_MTU;
430 
431 	ndev->hard_header_len = 0;
432 	ndev->addr_len = 0;
433 	ndev->tx_queue_len = DEFAULT_TX_QUEUE_LEN;
434 	ndev->flags = IFF_NOARP;
435 	ndev->netdev_ops = &mctp_serial_netdev_ops;
436 	ndev->needs_free_netdev = true;
437 }
438 
mctp_serial_open(struct tty_struct * tty)439 static int mctp_serial_open(struct tty_struct *tty)
440 {
441 	struct mctp_serial *dev;
442 	struct net_device *ndev;
443 	char name[32];
444 	int idx, rc;
445 
446 	if (!capable(CAP_NET_ADMIN))
447 		return -EPERM;
448 
449 	if (!tty->ops->write)
450 		return -EOPNOTSUPP;
451 
452 	idx = ida_alloc(&mctp_serial_ida, GFP_KERNEL);
453 	if (idx < 0)
454 		return idx;
455 
456 	snprintf(name, sizeof(name), "mctpserial%d", idx);
457 	ndev = alloc_netdev(sizeof(*dev), name, NET_NAME_ENUM,
458 			    mctp_serial_setup);
459 	if (!ndev) {
460 		rc = -ENOMEM;
461 		goto free_ida;
462 	}
463 
464 	dev = netdev_priv(ndev);
465 	dev->idx = idx;
466 	dev->tty = tty;
467 	dev->netdev = ndev;
468 	dev->txstate = STATE_IDLE;
469 	dev->rxstate = STATE_IDLE;
470 	spin_lock_init(&dev->lock);
471 	INIT_WORK(&dev->tx_work, mctp_serial_tx_work);
472 
473 	rc = register_netdev(ndev);
474 	if (rc)
475 		goto free_netdev;
476 
477 	tty->receive_room = 64 * 1024;
478 	tty->disc_data = dev;
479 
480 	return 0;
481 
482 free_netdev:
483 	free_netdev(ndev);
484 
485 free_ida:
486 	ida_free(&mctp_serial_ida, idx);
487 	return rc;
488 }
489 
mctp_serial_close(struct tty_struct * tty)490 static void mctp_serial_close(struct tty_struct *tty)
491 {
492 	struct mctp_serial *dev = tty->disc_data;
493 	int idx = dev->idx;
494 
495 	unregister_netdev(dev->netdev);
496 	ida_free(&mctp_serial_ida, idx);
497 }
498 
499 static struct tty_ldisc_ops mctp_ldisc = {
500 	.owner		= THIS_MODULE,
501 	.num		= N_MCTP,
502 	.name		= "mctp",
503 	.open		= mctp_serial_open,
504 	.close		= mctp_serial_close,
505 	.receive_buf	= mctp_serial_tty_receive_buf,
506 	.write_wakeup	= mctp_serial_tty_write_wakeup,
507 };
508 
mctp_serial_init(void)509 static int __init mctp_serial_init(void)
510 {
511 	return tty_register_ldisc(&mctp_ldisc);
512 }
513 
mctp_serial_exit(void)514 static void __exit mctp_serial_exit(void)
515 {
516 	tty_unregister_ldisc(&mctp_ldisc);
517 }
518 
519 module_init(mctp_serial_init);
520 module_exit(mctp_serial_exit);
521 
522 MODULE_LICENSE("GPL v2");
523 MODULE_AUTHOR("Jeremy Kerr <jk@codeconstruct.com.au>");
524 MODULE_DESCRIPTION("MCTP Serial transport");
525 
526 #if IS_ENABLED(CONFIG_MCTP_SERIAL_TEST)
527 #include <kunit/test.h>
528 
529 #define MAX_CHUNKS 6
530 struct test_chunk_tx {
531 	u8 input_len;
532 	u8 input[MCTP_SERIAL_MTU];
533 	u8 chunks[MAX_CHUNKS];
534 };
535 
test_next_chunk_len(struct kunit * test)536 static void test_next_chunk_len(struct kunit *test)
537 {
538 	struct mctp_serial devx;
539 	struct mctp_serial *dev = &devx;
540 	int next;
541 
542 	const struct test_chunk_tx *params = test->param_value;
543 
544 	memset(dev, 0x0, sizeof(*dev));
545 	memcpy(dev->txbuf, params->input, params->input_len);
546 	dev->txlen = params->input_len;
547 
548 	for (size_t i = 0; i < MAX_CHUNKS; i++) {
549 		next = next_chunk_len(dev);
550 		dev->txpos += next;
551 		KUNIT_EXPECT_EQ(test, next, params->chunks[i]);
552 
553 		if (next == 0) {
554 			KUNIT_EXPECT_EQ(test, dev->txpos, dev->txlen);
555 			return;
556 		}
557 	}
558 
559 	KUNIT_FAIL_AND_ABORT(test, "Ran out of chunks");
560 }
561 
562 static struct test_chunk_tx chunk_tx_tests[] = {
563 	{
564 		.input_len = 5,
565 		.input = { 0x00, 0x11, 0x22, 0x7e, 0x80 },
566 		.chunks = { 3, 1, 1, 0},
567 	},
568 	{
569 		.input_len = 5,
570 		.input = { 0x00, 0x11, 0x22, 0x7e, 0x7d },
571 		.chunks = { 3, 1, 1, 0},
572 	},
573 	{
574 		.input_len = 3,
575 		.input = { 0x7e, 0x11, 0x22, },
576 		.chunks = { 1, 2, 0},
577 	},
578 	{
579 		.input_len = 3,
580 		.input = { 0x7e, 0x7e, 0x7d, },
581 		.chunks = { 1, 1, 1, 0},
582 	},
583 	{
584 		.input_len = 4,
585 		.input = { 0x7e, 0x7e, 0x00, 0x7d, },
586 		.chunks = { 1, 1, 1, 1, 0},
587 	},
588 	{
589 		.input_len = 6,
590 		.input = { 0x7e, 0x7e, 0x00, 0x7d, 0x10, 0x10},
591 		.chunks = { 1, 1, 1, 1, 2, 0},
592 	},
593 	{
594 		.input_len = 1,
595 		.input = { 0x7e },
596 		.chunks = { 1, 0 },
597 	},
598 	{
599 		.input_len = 1,
600 		.input = { 0x80 },
601 		.chunks = { 1, 0 },
602 	},
603 	{
604 		.input_len = 3,
605 		.input = { 0x80, 0x80, 0x00 },
606 		.chunks = { 3, 0 },
607 	},
608 	{
609 		.input_len = 7,
610 		.input = { 0x01, 0x00, 0x08, 0xc8, 0x00, 0x80, 0x02 },
611 		.chunks = { 7, 0 },
612 	},
613 	{
614 		.input_len = 7,
615 		.input = { 0x01, 0x00, 0x08, 0xc8, 0x7e, 0x80, 0x02 },
616 		.chunks = { 4, 1, 2, 0 },
617 	},
618 };
619 
620 KUNIT_ARRAY_PARAM(chunk_tx, chunk_tx_tests, NULL);
621 
622 static struct kunit_case mctp_serial_test_cases[] = {
623 	KUNIT_CASE_PARAM(test_next_chunk_len, chunk_tx_gen_params),
624 };
625 
626 static struct kunit_suite mctp_serial_test_suite = {
627 	.name = "mctp_serial",
628 	.test_cases = mctp_serial_test_cases,
629 };
630 
631 kunit_test_suite(mctp_serial_test_suite);
632 
633 #endif /* CONFIG_MCTP_SERIAL_TEST */
634