Version 6.15 of the Linux kernel has been released, which includes a new transport driver for the MCTP stack: MCTP over USB. This transport gives us a higher-speed (but low pin-count) option for MCTP communication, suitable for operations that involve transfers of larger amounts of data, like firmware updates, crashdumps, and extended logging.

The driver itself is a fairly straightforward implementation of DMTF's DSP0238 standard, which covers the USB encapsulation of MCTP packets, and the USB descriptors required for a MCTP-over-USB device.

The driver is at drivers/net/mctp/mctp-usb.c, and can be enabled with the CONFIG_MCTP_TRANSPORT_USB config option. When enabled, and a MCTP-capable device is discovered, a new MCTP interface will appear, named as mctpusbN.

$ mctp link
dev lo index 1 address 00:00:00:00:00:00 net 1 mtu 65536 up
dev mctpusb0 index 3 address none net 1 mtu 68 down

This link represents a peer-to-peer connection with the remote MCTP device. Since it is peer-to-peer, no hardware addressing information is required on the device itself, nor for packets sent over the device. This is in contrast to MCTP-over-I2C, where packets must be sent to a predefined physical address (ie., the I2C address of the neighbouring MCTP endpoint).

Setting up the MCTP-over-USB link is much the same as any other, covered in our MCTP on Linux Introduction document.

First, assign a local endpoint ID (EID) to the device:

$ mctp addr add 8 dev mctpusb0

And bring it up:

$ mctp link set mctpusb0 up

Routes to remote endpoints can be added manually:

$ mctp route add 9 via mctpusb0

or via mctpd, which will perform device enumeration, address assignment, and set up local routes:

$ busctl call \
    au.com.codeconstruct.MCTP1 \
    /au/com/codeconstruct/mctp1/interfaces/mctpusb0 \
    au.com.codeconstruct.MCTP.BusOwner1 \
    SetupEndpoint ay 0
yisb 9 1 "/au/com/codeconstruct/mctp1/networks/1/endpoints/9" true

Note the arguments to SetupEndpoint: an array of bytes (ay) that is zero-length (0). This reflects the absence of physical addresses when using the USB transport.

As with other transport types, the MCTP-over-USB driver does not require any application-specific support. MCTP applications are able to use the generic sockets API, and the kernel handles the rest of the MCTP routing, packet-handling and hardware control functions.

MTU: MCTP packets and USB transfers🔗

When setting the Maximum Transmit Unit (MTU) size on the MCTP device, we are limited to the header format of USB packet transfers. As defined in DSP0283:

So, given the maximum value that can be described in the length field is 255, the maximum MTU value for MCTP-over-USB transports is 251. This value includes the transport-independent MCTP packet header.

Upcoming development🔗

We have a couple of in-progress updates for the MCTP-over-USB driver: support for transmitting multiple MCTP packets per USB transfer (multi-packet receive is already implemented in the upstream driver), and queuing improvements for IN transfer URBs. Both of these are aimed at improving transfer performance, and will not require any non-kernel changes to adopt.