162306a36Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci============================================== 462306a36Sopenharmony_ciManagement Component Transport Protocol (MCTP) 562306a36Sopenharmony_ci============================================== 662306a36Sopenharmony_ci 762306a36Sopenharmony_cinet/mctp/ contains protocol support for MCTP, as defined by DMTF standard 862306a36Sopenharmony_ciDSP0236. Physical interface drivers ("bindings" in the specification) are 962306a36Sopenharmony_ciprovided in drivers/net/mctp/. 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ciThe core code provides a socket-based interface to send and receive MCTP 1262306a36Sopenharmony_cimessages, through an AF_MCTP, SOCK_DGRAM socket. 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ciStructure: interfaces & networks 1562306a36Sopenharmony_ci================================ 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ciThe kernel models the local MCTP topology through two items: interfaces and 1862306a36Sopenharmony_cinetworks. 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ciAn interface (or "link") is an instance of an MCTP physical transport binding 2162306a36Sopenharmony_ci(as defined by DSP0236, section 3.2.47), likely connected to a specific hardware 2262306a36Sopenharmony_cidevice. This is represented as a ``struct netdevice``. 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ciA network defines a unique address space for MCTP endpoints by endpoint-ID 2562306a36Sopenharmony_ci(described by DSP0236, section 3.2.31). A network has a user-visible identifier 2662306a36Sopenharmony_cito allow references from userspace. Route definitions are specific to one 2762306a36Sopenharmony_cinetwork. 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ciInterfaces are associated with one network. A network may be associated with one 3062306a36Sopenharmony_cior more interfaces. 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ciIf multiple networks are present, each may contain endpoint IDs (EIDs) that are 3362306a36Sopenharmony_cialso present on other networks. 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ciSockets API 3662306a36Sopenharmony_ci=========== 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ciProtocol definitions 3962306a36Sopenharmony_ci-------------------- 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ciMCTP uses ``AF_MCTP`` / ``PF_MCTP`` for the address- and protocol- families. 4262306a36Sopenharmony_ciSince MCTP is message-based, only ``SOCK_DGRAM`` sockets are supported. 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci.. code-block:: C 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci int sd = socket(AF_MCTP, SOCK_DGRAM, 0); 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ciThe only (current) value for the ``protocol`` argument is 0. 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ciAs with all socket address families, source and destination addresses are 5162306a36Sopenharmony_cispecified with a ``sockaddr`` type, with a single-byte endpoint address: 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci.. code-block:: C 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci typedef __u8 mctp_eid_t; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci struct mctp_addr { 5862306a36Sopenharmony_ci mctp_eid_t s_addr; 5962306a36Sopenharmony_ci }; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci struct sockaddr_mctp { 6262306a36Sopenharmony_ci __kernel_sa_family_t smctp_family; 6362306a36Sopenharmony_ci unsigned int smctp_network; 6462306a36Sopenharmony_ci struct mctp_addr smctp_addr; 6562306a36Sopenharmony_ci __u8 smctp_type; 6662306a36Sopenharmony_ci __u8 smctp_tag; 6762306a36Sopenharmony_ci }; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci #define MCTP_NET_ANY 0x0 7062306a36Sopenharmony_ci #define MCTP_ADDR_ANY 0xff 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ciSyscall behaviour 7462306a36Sopenharmony_ci----------------- 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ciThe following sections describe the MCTP-specific behaviours of the standard 7762306a36Sopenharmony_cisocket system calls. These behaviours have been chosen to map closely to the 7862306a36Sopenharmony_ciexisting sockets APIs. 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci``bind()`` : set local socket address 8162306a36Sopenharmony_ci^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ciSockets that receive incoming request packets will bind to a local address, 8462306a36Sopenharmony_ciusing the ``bind()`` syscall. 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci.. code-block:: C 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci struct sockaddr_mctp addr; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci addr.smctp_family = AF_MCTP; 9162306a36Sopenharmony_ci addr.smctp_network = MCTP_NET_ANY; 9262306a36Sopenharmony_ci addr.smctp_addr.s_addr = MCTP_ADDR_ANY; 9362306a36Sopenharmony_ci addr.smctp_type = MCTP_TYPE_PLDM; 9462306a36Sopenharmony_ci addr.smctp_tag = MCTP_TAG_OWNER; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci int rc = bind(sd, (struct sockaddr *)&addr, sizeof(addr)); 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ciThis establishes the local address of the socket. Incoming MCTP messages that 9962306a36Sopenharmony_cimatch the network, address, and message type will be received by this socket. 10062306a36Sopenharmony_ciThe reference to 'incoming' is important here; a bound socket will only receive 10162306a36Sopenharmony_cimessages with the TO bit set, to indicate an incoming request message, rather 10262306a36Sopenharmony_cithan a response. 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ciThe ``smctp_tag`` value will configure the tags accepted from the remote side of 10562306a36Sopenharmony_cithis socket. Given the above, the only valid value is ``MCTP_TAG_OWNER``, which 10662306a36Sopenharmony_ciwill result in remotely "owned" tags being routed to this socket. Since 10762306a36Sopenharmony_ci``MCTP_TAG_OWNER`` is set, the 3 least-significant bits of ``smctp_tag`` are not 10862306a36Sopenharmony_ciused; callers must set them to zero. 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ciA ``smctp_network`` value of ``MCTP_NET_ANY`` will configure the socket to 11162306a36Sopenharmony_cireceive incoming packets from any locally-connected network. A specific network 11262306a36Sopenharmony_civalue will cause the socket to only receive incoming messages from that network. 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ciThe ``smctp_addr`` field specifies a local address to bind to. A value of 11562306a36Sopenharmony_ci``MCTP_ADDR_ANY`` configures the socket to receive messages addressed to any 11662306a36Sopenharmony_cilocal destination EID. 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ciThe ``smctp_type`` field specifies which message types to receive. Only the 11962306a36Sopenharmony_cilower 7 bits of the type is matched on incoming messages (ie., the 12062306a36Sopenharmony_cimost-significant IC bit is not part of the match). This results in the socket 12162306a36Sopenharmony_cireceiving packets with and without a message integrity check footer. 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci``sendto()``, ``sendmsg()``, ``send()`` : transmit an MCTP message 12462306a36Sopenharmony_ci^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ciAn MCTP message is transmitted using one of the ``sendto()``, ``sendmsg()`` or 12762306a36Sopenharmony_ci``send()`` syscalls. Using ``sendto()`` as the primary example: 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci.. code-block:: C 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci struct sockaddr_mctp addr; 13262306a36Sopenharmony_ci char buf[14]; 13362306a36Sopenharmony_ci ssize_t len; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci /* set message destination */ 13662306a36Sopenharmony_ci addr.smctp_family = AF_MCTP; 13762306a36Sopenharmony_ci addr.smctp_network = 0; 13862306a36Sopenharmony_ci addr.smctp_addr.s_addr = 8; 13962306a36Sopenharmony_ci addr.smctp_tag = MCTP_TAG_OWNER; 14062306a36Sopenharmony_ci addr.smctp_type = MCTP_TYPE_ECHO; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci /* arbitrary message to send, with message-type header */ 14362306a36Sopenharmony_ci buf[0] = MCTP_TYPE_ECHO; 14462306a36Sopenharmony_ci memcpy(buf + 1, "hello, world!", sizeof(buf) - 1); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci len = sendto(sd, buf, sizeof(buf), 0, 14762306a36Sopenharmony_ci (struct sockaddr_mctp *)&addr, sizeof(addr)); 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ciThe network and address fields of ``addr`` define the remote address to send to. 15062306a36Sopenharmony_ciIf ``smctp_tag`` has the ``MCTP_TAG_OWNER``, the kernel will ignore any bits set 15162306a36Sopenharmony_ciin ``MCTP_TAG_VALUE``, and generate a tag value suitable for the destination 15262306a36Sopenharmony_ciEID. If ``MCTP_TAG_OWNER`` is not set, the message will be sent with the tag 15362306a36Sopenharmony_civalue as specified. If a tag value cannot be allocated, the system call will 15462306a36Sopenharmony_cireport an errno of ``EAGAIN``. 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ciThe application must provide the message type byte as the first byte of the 15762306a36Sopenharmony_cimessage buffer passed to ``sendto()``. If a message integrity check is to be 15862306a36Sopenharmony_ciincluded in the transmitted message, it must also be provided in the message 15962306a36Sopenharmony_cibuffer, and the most-significant bit of the message type byte must be 1. 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ciThe ``sendmsg()`` system call allows a more compact argument interface, and the 16262306a36Sopenharmony_cimessage buffer to be specified as a scatter-gather list. At present no ancillary 16362306a36Sopenharmony_cimessage types (used for the ``msg_control`` data passed to ``sendmsg()``) are 16462306a36Sopenharmony_cidefined. 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ciTransmitting a message on an unconnected socket with ``MCTP_TAG_OWNER`` 16762306a36Sopenharmony_cispecified will cause an allocation of a tag, if no valid tag is already 16862306a36Sopenharmony_ciallocated for that destination. The (destination-eid,tag) tuple acts as an 16962306a36Sopenharmony_ciimplicit local socket address, to allow the socket to receive responses to this 17062306a36Sopenharmony_cioutgoing message. If any previous allocation has been performed (to for a 17162306a36Sopenharmony_cidifferent remote EID), that allocation is lost. 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ciSockets will only receive responses to requests they have sent (with TO=1) and 17462306a36Sopenharmony_cimay only respond (with TO=0) to requests they have received. 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci``recvfrom()``, ``recvmsg()``, ``recv()`` : receive an MCTP message 17762306a36Sopenharmony_ci^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ciAn MCTP message can be received by an application using one of the 18062306a36Sopenharmony_ci``recvfrom()``, ``recvmsg()``, or ``recv()`` system calls. Using ``recvfrom()`` 18162306a36Sopenharmony_cias the primary example: 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci.. code-block:: C 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci struct sockaddr_mctp addr; 18662306a36Sopenharmony_ci socklen_t addrlen; 18762306a36Sopenharmony_ci char buf[14]; 18862306a36Sopenharmony_ci ssize_t len; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci addrlen = sizeof(addr); 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci len = recvfrom(sd, buf, sizeof(buf), 0, 19362306a36Sopenharmony_ci (struct sockaddr_mctp *)&addr, &addrlen); 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci /* We can expect addr to describe an MCTP address */ 19662306a36Sopenharmony_ci assert(addrlen >= sizeof(buf)); 19762306a36Sopenharmony_ci assert(addr.smctp_family == AF_MCTP); 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci printf("received %zd bytes from remote EID %d\n", rc, addr.smctp_addr); 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ciThe address argument to ``recvfrom`` and ``recvmsg`` is populated with the 20262306a36Sopenharmony_ciremote address of the incoming message, including tag value (this will be needed 20362306a36Sopenharmony_ciin order to reply to the message). 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ciThe first byte of the message buffer will contain the message type byte. If an 20662306a36Sopenharmony_ciintegrity check follows the message, it will be included in the received buffer. 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ciThe ``recv()`` system call behaves in a similar way, but does not provide a 20962306a36Sopenharmony_ciremote address to the application. Therefore, these are only useful if the 21062306a36Sopenharmony_ciremote address is already known, or the message does not require a reply. 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ciLike the send calls, sockets will only receive responses to requests they have 21362306a36Sopenharmony_cisent (TO=1) and may only respond (TO=0) to requests they have received. 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci``ioctl(SIOCMCTPALLOCTAG)`` and ``ioctl(SIOCMCTPDROPTAG)`` 21662306a36Sopenharmony_ci^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ciThese tags give applications more control over MCTP message tags, by allocating 21962306a36Sopenharmony_ci(and dropping) tag values explicitly, rather than the kernel automatically 22062306a36Sopenharmony_ciallocating a per-message tag at ``sendmsg()`` time. 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ciIn general, you will only need to use these ioctls if your MCTP protocol does 22362306a36Sopenharmony_cinot fit the usual request/response model. For example, if you need to persist 22462306a36Sopenharmony_citags across multiple requests, or a request may generate more than one response. 22562306a36Sopenharmony_ciIn these cases, the ioctls allow you to decouple the tag allocation (and 22662306a36Sopenharmony_cirelease) from individual message send and receive operations. 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ciBoth ioctls are passed a pointer to a ``struct mctp_ioc_tag_ctl``: 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci.. code-block:: C 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci struct mctp_ioc_tag_ctl { 23362306a36Sopenharmony_ci mctp_eid_t peer_addr; 23462306a36Sopenharmony_ci __u8 tag; 23562306a36Sopenharmony_ci __u16 flags; 23662306a36Sopenharmony_ci }; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci``SIOCMCTPALLOCTAG`` allocates a tag for a specific peer, which an application 23962306a36Sopenharmony_cican use in future ``sendmsg()`` calls. The application populates the 24062306a36Sopenharmony_ci``peer_addr`` member with the remote EID. Other fields must be zero. 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ciOn return, the ``tag`` member will be populated with the allocated tag value. 24362306a36Sopenharmony_ciThe allocated tag will have the following tag bits set: 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci - ``MCTP_TAG_OWNER``: it only makes sense to allocate tags if you're the tag 24662306a36Sopenharmony_ci owner 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci - ``MCTP_TAG_PREALLOC``: to indicate to ``sendmsg()`` that this is a 24962306a36Sopenharmony_ci preallocated tag. 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci - ... and the actual tag value, within the least-significant three bits 25262306a36Sopenharmony_ci (``MCTP_TAG_MASK``). Note that zero is a valid tag value. 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ciThe tag value should be used as-is for the ``smctp_tag`` member of ``struct 25562306a36Sopenharmony_cisockaddr_mctp``. 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci``SIOCMCTPDROPTAG`` releases a tag that has been previously allocated by a 25862306a36Sopenharmony_ci``SIOCMCTPALLOCTAG`` ioctl. The ``peer_addr`` must be the same as used for the 25962306a36Sopenharmony_ciallocation, and the ``tag`` value must match exactly the tag returned from the 26062306a36Sopenharmony_ciallocation (including the ``MCTP_TAG_OWNER`` and ``MCTP_TAG_PREALLOC`` bits). 26162306a36Sopenharmony_ciThe ``flags`` field must be zero. 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ciKernel internals 26462306a36Sopenharmony_ci================ 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ciThere are a few possible packet flows in the MCTP stack: 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci1. local TX to remote endpoint, message <= MTU:: 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci sendmsg() 27162306a36Sopenharmony_ci -> mctp_local_output() 27262306a36Sopenharmony_ci : route lookup 27362306a36Sopenharmony_ci -> rt->output() (== mctp_route_output) 27462306a36Sopenharmony_ci -> dev_queue_xmit() 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci2. local TX to remote endpoint, message > MTU:: 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci sendmsg() 27962306a36Sopenharmony_ci -> mctp_local_output() 28062306a36Sopenharmony_ci -> mctp_do_fragment_route() 28162306a36Sopenharmony_ci : creates packet-sized skbs. For each new skb: 28262306a36Sopenharmony_ci -> rt->output() (== mctp_route_output) 28362306a36Sopenharmony_ci -> dev_queue_xmit() 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci3. remote TX to local endpoint, single-packet message:: 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci mctp_pkttype_receive() 28862306a36Sopenharmony_ci : route lookup 28962306a36Sopenharmony_ci -> rt->output() (== mctp_route_input) 29062306a36Sopenharmony_ci : sk_key lookup 29162306a36Sopenharmony_ci -> sock_queue_rcv_skb() 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci4. remote TX to local endpoint, multiple-packet message:: 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci mctp_pkttype_receive() 29662306a36Sopenharmony_ci : route lookup 29762306a36Sopenharmony_ci -> rt->output() (== mctp_route_input) 29862306a36Sopenharmony_ci : sk_key lookup 29962306a36Sopenharmony_ci : stores skb in struct sk_key->reasm_head 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci mctp_pkttype_receive() 30262306a36Sopenharmony_ci : route lookup 30362306a36Sopenharmony_ci -> rt->output() (== mctp_route_input) 30462306a36Sopenharmony_ci : sk_key lookup 30562306a36Sopenharmony_ci : finds existing reassembly in sk_key->reasm_head 30662306a36Sopenharmony_ci : appends new fragment 30762306a36Sopenharmony_ci -> sock_queue_rcv_skb() 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ciKey refcounts 31062306a36Sopenharmony_ci------------- 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci * keys are refed by: 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci - a skb: during route output, stored in ``skb->cb``. 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci - netns and sock lists. 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci * keys can be associated with a device, in which case they hold a 31962306a36Sopenharmony_ci reference to the dev (set through ``key->dev``, counted through 32062306a36Sopenharmony_ci ``dev->key_count``). Multiple keys can reference the device. 321