← Documents Documentation/networking/mctp.rst GitHub 원문 ↗

Linux 6.18.37 · Networking

Management Component Transport Protocol (MCTP)

MCTP topology, socket address와 syscall, tag lifecycle 및 kernel packet 흐름을 설명합니다.

Source pathDocumentation/networking/mctp.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약·해설

mctp.rst:1-320

MCTP는 network별 EID address space와 physical binding interface를 연결하고 datagram socket으로 request와 response를 교환합니다. TO bit와 tag ownership이 socket delivery를 결정하며 비표준 교환에는 tag allocation ioctl을 사용할 수 있습니다.

MCTP request/response
RequesterTO=1, allocated tagRemote endpoint
Remote endpointTO=0, same tagRequester socket

Address와 tag가 왕복하는 기본 경로입니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 .. SPDX-License-Identifier: GPL-2.0
2
3 ==============================================
4 Management Component Transport Protocol (MCTP)
5 ==============================================
6
7 net/mctp/ contains protocol support for MCTP, as defined by DMTF standard
8 DSP0236. Physical interface drivers ("bindings" in the specification) are
9 provided in drivers/net/mctp/.
10
11 The core code provides a socket-based interface to send and receive MCTP
12 messages, through an AF_MCTP, SOCK_DGRAM socket.
13
14 Structure: interfaces & networks
15 ================================
16
17 The kernel models the local MCTP topology through two items: interfaces and
18 networks.
19
20 An interface (or "link") is an instance of an MCTP physical transport binding
21 (as defined by DSP0236, section 3.2.47), likely connected to a specific hardware
22 device. This is represented as a ``struct netdevice``.
23
24 A network defines a unique address space for MCTP endpoints by endpoint-ID
25 (described by DSP0236, section 3.2.31). A network has a user-visible identifier
26 to allow references from userspace. Route definitions are specific to one
27 network.
28
29 Interfaces are associated with one network. A network may be associated with one
30 or more interfaces.
31
32 If multiple networks are present, each may contain endpoint IDs (EIDs) that are
33 also present on other networks.
34
35 Sockets API
36 ===========
37
38 Protocol definitions
39 --------------------
40
41 MCTP uses ``AF_MCTP`` / ``PF_MCTP`` for the address- and protocol- families.
42 Since MCTP is message-based, only ``SOCK_DGRAM`` sockets are supported.
43
44 .. code-block:: C
45
46 int sd = socket(AF_MCTP, SOCK_DGRAM, 0);
47
48 The only (current) value for the ``protocol`` argument is 0.
49
50 As with all socket address families, source and destination addresses are
51 specified with a ``sockaddr`` type, with a single-byte endpoint address:
52
53 .. code-block:: C
54
55 typedef __u8 mctp_eid_t;
56
57 struct mctp_addr {
58 mctp_eid_t s_addr;
59 };
60
61 struct sockaddr_mctp {
62 __kernel_sa_family_t smctp_family;
63 unsigned int smctp_network;
64 struct mctp_addr smctp_addr;
65 __u8 smctp_type;
66 __u8 smctp_tag;
67 };
68
69 #define MCTP_NET_ANY 0x0
70 #define MCTP_ADDR_ANY 0xff
71
72
73 Syscall behaviour
74 -----------------
75
76 The following sections describe the MCTP-specific behaviours of the standard
77 socket system calls. These behaviours have been chosen to map closely to the
78 existing sockets APIs.
79
80 ``bind()`` : set local socket address
81 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
82
83 Sockets that receive incoming request packets will bind to a local address,
84 using the ``bind()`` syscall.
85
86 .. code-block:: C
87
88 struct sockaddr_mctp addr;
89
90 addr.smctp_family = AF_MCTP;
91 addr.smctp_network = MCTP_NET_ANY;
92 addr.smctp_addr.s_addr = MCTP_ADDR_ANY;
93 addr.smctp_type = MCTP_TYPE_PLDM;
94 addr.smctp_tag = MCTP_TAG_OWNER;
95
96 int rc = bind(sd, (struct sockaddr *)&addr, sizeof(addr));
97
98 This establishes the local address of the socket. Incoming MCTP messages that
99 match the network, address, and message type will be received by this socket.
100 The reference to 'incoming' is important here; a bound socket will only receive
101 messages with the TO bit set, to indicate an incoming request message, rather
102 than a response.
103
104 The ``smctp_tag`` value will configure the tags accepted from the remote side of
105 this socket. Given the above, the only valid value is ``MCTP_TAG_OWNER``, which
106 will result in remotely "owned" tags being routed to this socket. Since
107 ``MCTP_TAG_OWNER`` is set, the 3 least-significant bits of ``smctp_tag`` are not
108 used; callers must set them to zero.
109
110 A ``smctp_network`` value of ``MCTP_NET_ANY`` will configure the socket to
111 receive incoming packets from any locally-connected network. A specific network
112 value will cause the socket to only receive incoming messages from that network.
113
114 The ``smctp_addr`` field specifies a local address to bind to. A value of
115 ``MCTP_ADDR_ANY`` configures the socket to receive messages addressed to any
116 local destination EID.
117
118 The ``smctp_type`` field specifies which message types to receive. Only the
119 lower 7 bits of the type is matched on incoming messages (ie., the
120 most-significant IC bit is not part of the match). This results in the socket
121 receiving packets with and without a message integrity check footer.
122
123 ``sendto()``, ``sendmsg()``, ``send()`` : transmit an MCTP message
124 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
125
126 An MCTP message is transmitted using one of the ``sendto()``, ``sendmsg()`` or
127 ``send()`` syscalls. Using ``sendto()`` as the primary example:
128
129 .. code-block:: C
130
131 struct sockaddr_mctp addr;
132 char buf[14];
133 ssize_t len;
134
135 /* set message destination */
136 addr.smctp_family = AF_MCTP;
137 addr.smctp_network = 0;
138 addr.smctp_addr.s_addr = 8;
139 addr.smctp_tag = MCTP_TAG_OWNER;
140 addr.smctp_type = MCTP_TYPE_ECHO;
141
142 /* arbitrary message to send, with message-type header */
143 buf[0] = MCTP_TYPE_ECHO;
144 memcpy(buf + 1, "hello, world!", sizeof(buf) - 1);
145
146 len = sendto(sd, buf, sizeof(buf), 0,
147 (struct sockaddr_mctp *)&addr, sizeof(addr));
148
149 The network and address fields of ``addr`` define the remote address to send to.
150 If ``smctp_tag`` has the ``MCTP_TAG_OWNER``, the kernel will ignore any bits set
151 in ``MCTP_TAG_VALUE``, and generate a tag value suitable for the destination
152 EID. If ``MCTP_TAG_OWNER`` is not set, the message will be sent with the tag
153 value as specified. If a tag value cannot be allocated, the system call will
154 report an errno of ``EAGAIN``.
155
156 The application must provide the message type byte as the first byte of the
157 message buffer passed to ``sendto()``. If a message integrity check is to be
158 included in the transmitted message, it must also be provided in the message
159 buffer, and the most-significant bit of the message type byte must be 1.
160
161 The ``sendmsg()`` system call allows a more compact argument interface, and the
162 message buffer to be specified as a scatter-gather list. At present no ancillary
163 message types (used for the ``msg_control`` data passed to ``sendmsg()``) are
164 defined.
165
166 Transmitting a message on an unconnected socket with ``MCTP_TAG_OWNER``
167 specified will cause an allocation of a tag, if no valid tag is already
168 allocated for that destination. The (destination-eid,tag) tuple acts as an
169 implicit local socket address, to allow the socket to receive responses to this
170 outgoing message. If any previous allocation has been performed (to for a
171 different remote EID), that allocation is lost.
172
173 Sockets will only receive responses to requests they have sent (with TO=1) and
174 may only respond (with TO=0) to requests they have received.
175
176 ``recvfrom()``, ``recvmsg()``, ``recv()`` : receive an MCTP message
177 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
178
179 An MCTP message can be received by an application using one of the
180 ``recvfrom()``, ``recvmsg()``, or ``recv()`` system calls. Using ``recvfrom()``
181 as the primary example:
182
183 .. code-block:: C
184
185 struct sockaddr_mctp addr;
186 socklen_t addrlen;
187 char buf[14];
188 ssize_t len;
189
190 addrlen = sizeof(addr);
191
192 len = recvfrom(sd, buf, sizeof(buf), 0,
193 (struct sockaddr_mctp *)&addr, &addrlen);
194
195 /* We can expect addr to describe an MCTP address */
196 assert(addrlen >= sizeof(buf));
197 assert(addr.smctp_family == AF_MCTP);
198
199 printf("received %zd bytes from remote EID %d\n", rc, addr.smctp_addr);
200
201 The address argument to ``recvfrom`` and ``recvmsg`` is populated with the
202 remote address of the incoming message, including tag value (this will be needed
203 in order to reply to the message).
204
205 The first byte of the message buffer will contain the message type byte. If an
206 integrity check follows the message, it will be included in the received buffer.
207
208 The ``recv()`` system call behaves in a similar way, but does not provide a
209 remote address to the application. Therefore, these are only useful if the
210 remote address is already known, or the message does not require a reply.
211
212 Like the send calls, sockets will only receive responses to requests they have
213 sent (TO=1) and may only respond (TO=0) to requests they have received.
214
215 ``ioctl(SIOCMCTPALLOCTAG)`` and ``ioctl(SIOCMCTPDROPTAG)``
216 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
217
218 These tags give applications more control over MCTP message tags, by allocating
219 (and dropping) tag values explicitly, rather than the kernel automatically
220 allocating a per-message tag at ``sendmsg()`` time.
221
222 In general, you will only need to use these ioctls if your MCTP protocol does
223 not fit the usual request/response model. For example, if you need to persist
224 tags across multiple requests, or a request may generate more than one response.
225 In these cases, the ioctls allow you to decouple the tag allocation (and
226 release) from individual message send and receive operations.
227
228 Both ioctls are passed a pointer to a ``struct mctp_ioc_tag_ctl``:
229
230 .. code-block:: C
231
232 struct mctp_ioc_tag_ctl {
233 mctp_eid_t peer_addr;
234 __u8 tag;
235 __u16 flags;
236 };
237
238 ``SIOCMCTPALLOCTAG`` allocates a tag for a specific peer, which an application
239 can use in future ``sendmsg()`` calls. The application populates the
240 ``peer_addr`` member with the remote EID. Other fields must be zero.
241
242 On return, the ``tag`` member will be populated with the allocated tag value.
243 The allocated tag will have the following tag bits set:
244
245 - ``MCTP_TAG_OWNER``: it only makes sense to allocate tags if you're the tag
246 owner
247
248 - ``MCTP_TAG_PREALLOC``: to indicate to ``sendmsg()`` that this is a
249 preallocated tag.
250
251 - ... and the actual tag value, within the least-significant three bits
252 (``MCTP_TAG_MASK``). Note that zero is a valid tag value.
253
254 The tag value should be used as-is for the ``smctp_tag`` member of ``struct
255 sockaddr_mctp``.
256
257 ``SIOCMCTPDROPTAG`` releases a tag that has been previously allocated by a
258 ``SIOCMCTPALLOCTAG`` ioctl. The ``peer_addr`` must be the same as used for the
259 allocation, and the ``tag`` value must match exactly the tag returned from the
260 allocation (including the ``MCTP_TAG_OWNER`` and ``MCTP_TAG_PREALLOC`` bits).
261 The ``flags`` field must be zero.
262
263 Kernel internals
264 ================
265
266 There are a few possible packet flows in the MCTP stack:
267
268 1. local TX to remote endpoint, message <= MTU::
269
270 sendmsg()
271 -> mctp_local_output()
272 : route lookup
273 -> rt->output() (== mctp_route_output)
274 -> dev_queue_xmit()
275
276 2. local TX to remote endpoint, message > MTU::
277
278 sendmsg()
279 -> mctp_local_output()
280 -> mctp_do_fragment_route()
281 : creates packet-sized skbs. For each new skb:
282 -> rt->output() (== mctp_route_output)
283 -> dev_queue_xmit()
284
285 3. remote TX to local endpoint, single-packet message::
286
287 mctp_pkttype_receive()
288 : route lookup
289 -> rt->output() (== mctp_route_input)
290 : sk_key lookup
291 -> sock_queue_rcv_skb()
292
293 4. remote TX to local endpoint, multiple-packet message::
294
295 mctp_pkttype_receive()
296 : route lookup
297 -> rt->output() (== mctp_route_input)
298 : sk_key lookup
299 : stores skb in struct sk_key->reasm_head
300
301 mctp_pkttype_receive()
302 : route lookup
303 -> rt->output() (== mctp_route_input)
304 : sk_key lookup
305 : finds existing reassembly in sk_key->reasm_head
306 : appends new fragment
307 -> sock_queue_rcv_skb()
308
309 Key refcounts
310 -------------
311
312 * keys are refed by:
313
314 - a skb: during route output, stored in ``skb->cb``.
315
316 - netns and sock lists.
317
318 * keys can be associated with a device, in which case they hold a
319 reference to the dev (set through ``key->dev``, counted through
320 ``dev->key_count``). Multiple keys can reference the device.
321

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

Protocol과 interface·network topology

1-34

`net/mctp/`는 DMTF 표준 DSP0236의 MCTP protocol을 구현하고, specification에서 binding이라 부르는 물리 interface driver는 `drivers/net/mctp/`에 둡니다. Core는 `AF_MCTP`, `SOCK_DGRAM` socket을 통해 MCTP message를 보내고 받는 interface를 제공합니다.

Kernel은 local MCTP topology를 interface와 network로 모델링합니다. Interface 또는 link는 특정 hardware device에 연결되는 MCTP physical transport binding의 instance이며 `struct netdevice`로 나타냅니다. Network는 EID(endpoint ID)로 endpoint를 식별하는 고유 address space이고 userspace에서 참조할 identifier를 가지며 route도 network별로 정의됩니다.

각 interface는 하나의 network에 속하지만 한 network에는 하나 이상의 interface가 연결될 수 있습니다. 여러 network가 존재하면 서로 다른 network가 같은 EID를 포함해도 충돌하지 않습니다.

MCTP topology
MCTP network identifierinterface A / netdevicephysical binding A
MCTP network identifierinterface B / netdevicephysical binding B
각 network의 독립 EID 공간network별 route

Interface와 EID address space의 관계입니다.

.. SPDX-License-Identifier: GPL-2.0

==============================================
Management Component Transport Protocol (MCTP)
==============================================

net/mctp/ contains protocol support for MCTP, as defined by DMTF standard
DSP0236. Physical interface drivers ("bindings" in the specification) are
provided in drivers/net/mctp/.

The core code provides a socket-based interface to send and receive MCTP
messages, through an AF_MCTP, SOCK_DGRAM socket.

Structure: interfaces & networks
================================

The kernel models the local MCTP topology through two items: interfaces and
networks.

An interface (or "link") is an instance of an MCTP physical transport binding
(as defined by DSP0236, section 3.2.47), likely connected to a specific hardware
device. This is represented as a ``struct netdevice``.

A network defines a unique address space for MCTP endpoints by endpoint-ID
(described by DSP0236, section 3.2.31). A network has a user-visible identifier
to allow references from userspace. Route definitions are specific to one
network.

Interfaces are associated with one network. A network may be associated with one
or more interfaces.

If multiple networks are present, each may contain endpoint IDs (EIDs) that are
also present on other networks.

Socket family와 address 구조

35-78

MCTP는 address family와 protocol family로 각각 `AF_MCTP`와 `PF_MCTP`를 사용합니다. Message 기반 protocol이므로 `SOCK_DGRAM`만 지원하며 현재 `socket(AF_MCTP, SOCK_DGRAM, protocol)`의 `protocol`에는 0만 사용할 수 있습니다.

Endpoint address는 한 byte인 `mctp_eid_t`이고 `struct mctp_addr.s_addr`에 저장됩니다. `struct sockaddr_mctp`는 family, network identifier, endpoint address, message type, tag를 담습니다. `MCTP_NET_ANY`는 모든 network를 뜻하는 0이고 `MCTP_ADDR_ANY`는 모든 local EID를 뜻하는 `0xff`입니다.

sockaddr_mctp field
Field의미
smctp_familyAF_MCTP
smctp_networkMCTP network identifier
smctp_addr한 byte endpoint ID
smctp_typeMCTP message type
smctp_tagtag owner와 tag value

MCTP socket address를 구성하는 field입니다.

Sockets API
===========

Protocol definitions
--------------------

MCTP uses ``AF_MCTP`` / ``PF_MCTP`` for the address- and protocol- families.
Since MCTP is message-based, only ``SOCK_DGRAM`` sockets are supported.

.. code-block:: C

    int sd = socket(AF_MCTP, SOCK_DGRAM, 0);

The only (current) value for the ``protocol`` argument is 0.

As with all socket address families, source and destination addresses are
specified with a ``sockaddr`` type, with a single-byte endpoint address:

.. code-block:: C

    typedef __u8                mctp_eid_t;

    struct mctp_addr {
            mctp_eid_t                s_addr;
    };

    struct sockaddr_mctp {
            __kernel_sa_family_t smctp_family;
            unsigned int         smctp_network;
            struct mctp_addr     smctp_addr;
            __u8                 smctp_type;
            __u8                 smctp_tag;
    };

    #define MCTP_NET_ANY        0x0
    #define MCTP_ADDR_ANY        0xff


Syscall behaviour
-----------------

The following sections describe the MCTP-specific behaviours of the standard
socket system calls. These behaviours have been chosen to map closely to the
existing sockets APIs.

bind(): local 수신 address

79-121

들어오는 request packet을 받을 socket은 `bind()`로 local address를 설정합니다. Kernel은 network, address, message type이 일치하는 incoming MCTP message를 이 socket에 전달합니다. 여기서 incoming은 TO(tag owner) bit가 설정된 request를 뜻하며, bound socket이 response까지 무조건 받는다는 뜻은 아닙니다.

`smctp_tag`에는 remote가 소유한 tag를 받도록 `MCTP_TAG_OWNER`만 지정할 수 있습니다. 이 flag를 쓸 때 최하위 3개 tag value bit는 사용하지 않으므로 caller가 0으로 설정해야 합니다. `smctp_network`가 `MCTP_NET_ANY`이면 locally connected인 모든 network, 특정 값이면 그 network에서 온 message만 받습니다.

`smctp_addr`의 `MCTP_ADDR_ANY`는 모든 local destination EID를 허용합니다. `smctp_type` 비교에는 하위 7 bit만 사용하고 최상위 IC(integrity check) bit는 제외하므로 integrity check footer가 있는 packet과 없는 packet을 모두 받을 수 있습니다.


``bind()`` : set local socket address
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Sockets that receive incoming request packets will bind to a local address,
using the ``bind()`` syscall.

.. code-block:: C

    struct sockaddr_mctp addr;

    addr.smctp_family = AF_MCTP;
    addr.smctp_network = MCTP_NET_ANY;
    addr.smctp_addr.s_addr = MCTP_ADDR_ANY;
    addr.smctp_type = MCTP_TYPE_PLDM;
    addr.smctp_tag = MCTP_TAG_OWNER;

    int rc = bind(sd, (struct sockaddr *)&addr, sizeof(addr));

This establishes the local address of the socket. Incoming MCTP messages that
match the network, address, and message type will be received by this socket.
The reference to 'incoming' is important here; a bound socket will only receive
messages with the TO bit set, to indicate an incoming request message, rather
than a response.

The ``smctp_tag`` value will configure the tags accepted from the remote side of
this socket. Given the above, the only valid value is ``MCTP_TAG_OWNER``, which
will result in remotely "owned" tags being routed to this socket. Since
``MCTP_TAG_OWNER`` is set, the 3 least-significant bits of ``smctp_tag`` are not
used; callers must set them to zero.

A ``smctp_network`` value of ``MCTP_NET_ANY`` will configure the socket to
receive incoming packets from any locally-connected network. A specific network
value will cause the socket to only receive incoming messages from that network.

The ``smctp_addr`` field specifies a local address to bind to. A value of
``MCTP_ADDR_ANY`` configures the socket to receive messages addressed to any
local destination EID.

The ``smctp_type`` field specifies which message types to receive. Only the
lower 7 bits of the type is matched on incoming messages (ie., the
most-significant IC bit is not part of the match). This results in the socket
receiving packets with and without a message integrity check footer.

sendto·sendmsg·send(): message 송신

122-175

`sendto()`, `sendmsg()`, `send()`로 MCTP message를 전송합니다. Destination address의 network와 EID가 remote 목적지를 정합니다. `smctp_tag`에 `MCTP_TAG_OWNER`가 있으면 kernel은 `MCTP_TAG_VALUE` bit를 무시하고 destination EID에 알맞은 tag를 생성합니다. Owner bit가 없으면 지정한 tag value를 그대로 사용하며 tag를 할당할 수 없으면 `EAGAIN`을 반환합니다.

Application은 송신 buffer의 첫 byte에 message type을 직접 넣어야 합니다. Integrity check가 필요하면 footer도 buffer에 포함하고 type byte의 최상위 bit를 1로 설정합니다. `sendmsg()`는 scatter-gather list를 사용할 수 있지만 현재 `msg_control`에 넣을 ancillary message type은 정의되어 있지 않습니다.

연결되지 않은 socket에서 `MCTP_TAG_OWNER`로 보낼 때 destination용 유효 tag가 없으면 새 tag를 할당합니다. `(destination-eid, tag)` tuple은 outgoing request의 response를 받기 위한 암시적 local socket address가 됩니다. 다른 remote EID에 대한 이전 할당은 사라집니다. Socket은 자신이 TO=1로 보낸 request의 response만 받고, 자신이 받은 request에는 TO=0으로만 응답할 수 있습니다.


``sendto()``, ``sendmsg()``, ``send()`` : transmit an MCTP message
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

An MCTP message is transmitted using one of the ``sendto()``, ``sendmsg()`` or
``send()`` syscalls. Using ``sendto()`` as the primary example:

.. code-block:: C

    struct sockaddr_mctp addr;
    char buf[14];
    ssize_t len;

    /* set message destination */
    addr.smctp_family = AF_MCTP;
    addr.smctp_network = 0;
    addr.smctp_addr.s_addr = 8;
    addr.smctp_tag = MCTP_TAG_OWNER;
    addr.smctp_type = MCTP_TYPE_ECHO;

    /* arbitrary message to send, with message-type header */
    buf[0] = MCTP_TYPE_ECHO;
    memcpy(buf + 1, "hello, world!", sizeof(buf) - 1);

    len = sendto(sd, buf, sizeof(buf), 0,
                    (struct sockaddr_mctp *)&addr, sizeof(addr));

The network and address fields of ``addr`` define the remote address to send to.
If ``smctp_tag`` has the ``MCTP_TAG_OWNER``, the kernel will ignore any bits set
in ``MCTP_TAG_VALUE``, and generate a tag value suitable for the destination
EID. If ``MCTP_TAG_OWNER`` is not set, the message will be sent with the tag
value as specified. If a tag value cannot be allocated, the system call will
report an errno of ``EAGAIN``.

The application must provide the message type byte as the first byte of the
message buffer passed to ``sendto()``. If a message integrity check is to be
included in the transmitted message, it must also be provided in the message
buffer, and the most-significant bit of the message type byte must be 1.

The ``sendmsg()`` system call allows a more compact argument interface, and the
message buffer to be specified as a scatter-gather list. At present no ancillary
message types (used for the ``msg_control`` data passed to ``sendmsg()``) are
defined.

Transmitting a message on an unconnected socket with ``MCTP_TAG_OWNER``
specified will cause an allocation of a tag, if no valid tag is already
allocated for that destination. The (destination-eid,tag) tuple acts as an
implicit local socket address, to allow the socket to receive responses to this
outgoing message. If any previous allocation has been performed (to for a
different remote EID), that allocation is lost.

Sockets will only receive responses to requests they have sent (with TO=1) and
may only respond (with TO=0) to requests they have received.

recvfrom·recvmsg·recv(): message 수신

176-214

Application은 `recvfrom()`, `recvmsg()`, `recv()`로 MCTP message를 받습니다. `recvfrom()`과 `recvmsg()`의 address argument에는 incoming message의 remote EID와 reply에 필요한 tag value를 포함한 remote address가 채워집니다.

수신 buffer의 첫 byte는 message type이며 integrity check가 뒤따르면 그것도 buffer에 포함됩니다. `recv()`는 비슷하게 동작하지만 remote address를 돌려주지 않으므로 상대 address를 이미 알거나 reply가 필요 없는 경우에만 유용합니다. 송신과 마찬가지로 socket은 자신이 TO=1로 보낸 request의 response만 받을 수 있고, 수신한 request에는 TO=0으로 응답합니다.

``recvfrom()``, ``recvmsg()``, ``recv()`` : receive an MCTP message
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

An MCTP message can be received by an application using one of the
``recvfrom()``, ``recvmsg()``, or ``recv()`` system calls. Using ``recvfrom()``
as the primary example:

.. code-block:: C

    struct sockaddr_mctp addr;
    socklen_t addrlen;
    char buf[14];
    ssize_t len;

    addrlen = sizeof(addr);

    len = recvfrom(sd, buf, sizeof(buf), 0,
                    (struct sockaddr_mctp *)&addr, &addrlen);

    /* We can expect addr to describe an MCTP address */
    assert(addrlen >= sizeof(buf));
    assert(addr.smctp_family == AF_MCTP);

    printf("received %zd bytes from remote EID %d\n", rc, addr.smctp_addr);

The address argument to ``recvfrom`` and ``recvmsg`` is populated with the
remote address of the incoming message, including tag value (this will be needed
in order to reply to the message).

The first byte of the message buffer will contain the message type byte. If an
integrity check follows the message, it will be included in the received buffer.

The ``recv()`` system call behaves in a similar way, but does not provide a
remote address to the application. Therefore, these are only useful if the
remote address is already known, or the message does not require a reply.

Like the send calls, sockets will only receive responses to requests they have
sent (TO=1) and may only respond (TO=0) to requests they have received.

Tag 명시 할당과 해제 ioctl

215-262

`SIOCMCTPALLOCTAG`와 `SIOCMCTPDROPTAG`는 `sendmsg()`마다 kernel이 자동 할당하는 방식 대신 application이 MCTP tag를 명시적으로 할당하고 해제하게 합니다. 여러 request에 같은 tag를 유지하거나 하나의 request가 여러 response를 만드는 등 일반적인 request/response model에 맞지 않을 때 사용합니다.

두 ioctl은 `peer_addr`, `tag`, `flags`를 가진 `struct mctp_ioc_tag_ctl` pointer를 받습니다. `SIOCMCTPALLOCTAG` 호출 전에는 remote EID인 `peer_addr`만 채우고 나머지는 0으로 둡니다. 성공하면 `tag`에 `MCTP_TAG_OWNER`, preallocated임을 나타내는 `MCTP_TAG_PREALLOC`, 그리고 하위 3 bit의 실제 `MCTP_TAG_MASK` 값이 함께 반환됩니다. 실제 값 0도 유효하며 반환된 값을 `sockaddr_mctp.smctp_tag`에 그대로 사용해야 합니다.

`SIOCMCTPDROPTAG`는 앞서 할당한 tag를 해제합니다. `peer_addr`는 할당 때와 같아야 하고 `tag`도 OWNER와 PREALLOC bit를 포함한 반환값 전체가 정확히 일치해야 하며 `flags`는 0이어야 합니다.

``ioctl(SIOCMCTPALLOCTAG)`` and ``ioctl(SIOCMCTPDROPTAG)``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

These tags give applications more control over MCTP message tags, by allocating
(and dropping) tag values explicitly, rather than the kernel automatically
allocating a per-message tag at ``sendmsg()`` time.

In general, you will only need to use these ioctls if your MCTP protocol does
not fit the usual request/response model. For example, if you need to persist
tags across multiple requests, or a request may generate more than one response.
In these cases, the ioctls allow you to decouple the tag allocation (and
release) from individual message send and receive operations.

Both ioctls are passed a pointer to a ``struct mctp_ioc_tag_ctl``:

.. code-block:: C

    struct mctp_ioc_tag_ctl {
        mctp_eid_t      peer_addr;
        __u8                tag;
        __u16           flags;
    };

``SIOCMCTPALLOCTAG`` allocates a tag for a specific peer, which an application
can use in future ``sendmsg()`` calls. The application populates the
``peer_addr`` member with the remote EID. Other fields must be zero.

On return, the ``tag`` member will be populated with the allocated tag value.
The allocated tag will have the following tag bits set:

 - ``MCTP_TAG_OWNER``: it only makes sense to allocate tags if you're the tag
   owner

 - ``MCTP_TAG_PREALLOC``: to indicate to ``sendmsg()`` that this is a
   preallocated tag.

 - ... and the actual tag value, within the least-significant three bits
   (``MCTP_TAG_MASK``). Note that zero is a valid tag value.

The tag value should be used as-is for the ``smctp_tag`` member of ``struct
sockaddr_mctp``.

``SIOCMCTPDROPTAG`` releases a tag that has been previously allocated by a
``SIOCMCTPALLOCTAG`` ioctl. The ``peer_addr`` must be the same as used for the
allocation, and the ``tag`` value must match exactly the tag returned from the
allocation (including the ``MCTP_TAG_OWNER`` and ``MCTP_TAG_PREALLOC`` bits).
The ``flags`` field must be zero.

Kernel packet 흐름과 key reference

263-320

Local 송신 message가 MTU 이하면 `mctp_local_output()`의 route lookup 뒤 `mctp_route_output`과 `dev_queue_xmit()`로 바로 나갑니다. MTU를 넘으면 `mctp_do_fragment_route()`가 packet 크기의 skb를 만들고 각 fragment를 같은 route output 경로로 전송합니다.

Remote에서 local endpoint로 들어온 단일 packet message는 `mctp_pkttype_receive()`에서 route와 `sk_key`를 찾은 뒤 `sock_queue_rcv_skb()`로 socket에 넣습니다. 여러 packet message는 첫 fragment를 `sk_key->reasm_head`에 저장하고 이후 fragment를 기존 reassembly에 이어 붙인 뒤 완성된 skb를 socket에 전달합니다.

Key reference는 route output 중 `skb->cb`에 저장된 skb와 net namespace 및 socket list가 보유합니다. Key가 device와 연결되면 `key->dev`를 통해 device reference를 잡고 `dev->key_count`로 계산하며 여러 key가 같은 device를 참조할 수 있습니다.

MCTP packet paths
Local TX <= MTUsendmsgmctp_local_outputmctp_route_outputdev_queue_xmit
Local TX > MTUmctp_do_fragment_routefragment별 mctp_route_outputdev_queue_xmit
Remote single packetmctp_pkttype_receivemctp_route_inputsk_key lookupsock_queue_rcv_skb
Remote fragmentedsk_key->reasm_headfragment appendsock_queue_rcv_skb

원문의 ASCII 호출 흐름을 구조화했습니다.

Kernel internals
================

There are a few possible packet flows in the MCTP stack:

1. local TX to remote endpoint, message <= MTU::

        sendmsg()
         -> mctp_local_output()
            : route lookup
            -> rt->output() (== mctp_route_output)
               -> dev_queue_xmit()

2. local TX to remote endpoint, message > MTU::

        sendmsg()
        -> mctp_local_output()
            -> mctp_do_fragment_route()
               : creates packet-sized skbs. For each new skb:
               -> rt->output() (== mctp_route_output)
                  -> dev_queue_xmit()

3. remote TX to local endpoint, single-packet message::

        mctp_pkttype_receive()
        : route lookup
        -> rt->output() (== mctp_route_input)
           : sk_key lookup
           -> sock_queue_rcv_skb()

4. remote TX to local endpoint, multiple-packet message::

        mctp_pkttype_receive()
        : route lookup
        -> rt->output() (== mctp_route_input)
           : sk_key lookup
           : stores skb in struct sk_key->reasm_head

        mctp_pkttype_receive()
        : route lookup
        -> rt->output() (== mctp_route_input)
           : sk_key lookup
           : finds existing reassembly in sk_key->reasm_head
           : appends new fragment
           -> sock_queue_rcv_skb()

Key refcounts
-------------

 * keys are refed by:

   - a skb: during route output, stored in ``skb->cb``.

   - netns and sock lists.

 * keys can be associated with a device, in which case they hold a
   reference to the dev (set through ``key->dev``, counted through
   ``dev->key_count``). Multiple keys can reference the device.