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_haddrdata, 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.