MCTP extended addressing
Following on from the MCTP introduction, this document describes one of the newer features of the MCTP stack: extended addressing. This allows utilities to directly address specific physical endpoints; for example, when no endpoint IDs have been assigned.
One note on usage: typical MCTP applications won't need to use this extended addressing facility. This is mostly used for hardware-specific operations, like an MCTP Control Protocol implementation, or MCTP applications that need to deal with endpoint hardware in unusual states.
Standard addressing: struct sockaddr_mctp
🔗
The initial MCTP patches defined our socket addressing scheme (struct sockaddr_mctp
) as roughly:
;
(some types have been changed for simplicity here, but this definition will work as-is)
Where you'd typically address a remote peer through its EID, by setting
smctp_addr
:
addr.smctp_family = AF_MCTP;
addr.smctp_addr.s_addr = 8; /* send to EID 8 */
However, we might have a scenario where the remote endpoint doesn't yet have an
EID, and we want to assign one by sending a MCTP Control Protocol message
— the MCTP equivalent to the DHCP process for IP. In this case, we don't have an
EID to populate smctp_addr
, so we will need a different method of addressing
this peer.
For this, we have introduced an "extended" addressing facility, allowing physical addresses to be used instead:
Extended addressing: struct sockadr_mctp_ext
🔗
The sendto()
and recvfrom()
calls on a MCTP socket can be passed an
alternate addressing scheme: struct sockaddr_mctp_ext
. This is defined as:
;
Importantly, this structure has an embedded struct sockaddr_mctp
as its first
member, so the standard addressing fields are available, and are in a compatible
layout. This allows a sockaddr_mctp_ext
to be converted to a sockaddr_mctp
if necessary.
With this new struct, we can provide three new bits of address data:
-
smctp_ifindex
: the physical network interface to use for message TX, or the interface through which the message was received. -
smctp_haddr
: the hardware address of the remote endpoint (think ethernet MAC addresses). This may vary in size, depending on the properties of the physical protocol - for example, i2c/SMBus links use a 1-byte address here, corresponding to the i2c address byte. -
smctp_halen
: the length ofsmctp_haddr
data, dependent on the physical layer.
We can then pass a struct sockaddr_mctp_ext
to the recvfrom()
and sendto()
calls, and retrieve (for recvfrom
) or specify (for sendto
) the low-level
addressing information.
This is a little like the struct in_pktinfo
ancillary message used for
IPv4/IPv6 datagrams, but instead of being contained in the msg_control
data of
a struct msghdr
, it's available directly in the sockaddr
structures.
Using extended addresses is enabled through a new socket option for MCTP:
MCTP_OPT_ADDR_EXT
, which takes a single int
value to enable or disable the
option:
/* 1 to enable extended addressing, 0 to disable */
int opt = 1
rc = ;
if
;
The extended addressing facility was introduced in kernel v5.16. As with any
setsockopt
call, this will fail if not supported by the kernel.
As a more complete example, to retrieve extended addressing details for incoming
messages (assuming our socket (as sd
) is already opened and bound to receive):
struct sockaddr_mctp_ext peer_addr;
socklen_t peer_addr_len;
int rc, opt;
/* enable extended addressing */
opt = 1;
rc = ;
if
/* receive a message */
peer_addr_len = sizeof;
rc = ;
/* check that we received OK */
if
return -1;
/* check that we have an extended address returned */
if
return -1;
/* we have info about the incoming MCTP interface... */
;
/* ... and the physical address - assuming one-byte
* addresses (eg i2c) for this example */
;
With the sockaddr_mctp_ext
returned from recvmsg
, we have access to specific
physical addressing data if necessary, or we can treat it as an opaque structure
and pass it back to a sendto()
call when replying to the message.
For example, for a reply to a message received above:
/* clear the tag-owner bit for a reply */
peer_addr.smctp_base.smctp_tag &= ~MCTP_TAG_OWNER;
/* send using the original message's physical addressing info */
rc = ;
This will transmit the message back to the sender's interface and physical address, as passed from the originally-received message.
And that's it! Note that you'll generally be fine using the standard addressing structures for most MCTP-messaging purposes, but the extended addressing may be useful if you need more control over the low-level message parameters.
If you have any questions about extended address, or the MCTP stack on Linux in general, feel free to email me on jk@codeconstruct.com.au.