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.
 
     
   
   
   
   
    
   