요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
====================
Userspace MAD access
====================
Device files
============
Each port of each InfiniBand device has a "umad" device and an
"issm" device attached. For example, a two-port HCA will have two
umad devices and two issm devices, while a switch will have one
device of each type (for switch port 0).
Creating MAD agents
===================
A MAD agent can be created by filling in a struct ib_user_mad_reg_req
and then calling the IB_USER_MAD_REGISTER_AGENT ioctl on a file
descriptor for the appropriate device file. If the registration
request succeeds, a 32-bit id will be returned in the structure.
For example::
struct ib_user_mad_reg_req req = { /* ... */ };
ret = ioctl(fd, IB_USER_MAD_REGISTER_AGENT, (char *) &req);
if (!ret)
my_agent = req.id;
else
perror("agent register");
Agents can be unregistered with the IB_USER_MAD_UNREGISTER_AGENT
ioctl. Also, all agents registered through a file descriptor will
be unregistered when the descriptor is closed.
2014
a new registration ioctl is now provided which allows additional
fields to be provided during registration.
Users of this registration call are implicitly setting the use of
pkey_index (see below).
Receiving MADs
==============
MADs are received using read(). The receive side now supports
RMPP. The buffer passed to read() must be at least one
struct ib_user_mad + 256 bytes. For example:
If the buffer passed is not large enough to hold the received
MAD (RMPP), the errno is set to ENOSPC and the length of the
buffer needed is set in mad.length.
Example for normal MAD (non RMPP) reads::
struct ib_user_mad *mad;
mad = malloc(sizeof *mad + 256);
ret = read(fd, mad, sizeof *mad + 256);
if (ret != sizeof mad + 256) {
perror("read");
free(mad);
}
Example for RMPP reads::
struct ib_user_mad *mad;
mad = malloc(sizeof *mad + 256);
ret = read(fd, mad, sizeof *mad + 256);
if (ret == -ENOSPC)) {
length = mad.length;
free(mad);
mad = malloc(sizeof *mad + length);
ret = read(fd, mad, sizeof *mad + length);
}
if (ret < 0) {
perror("read");
free(mad);
}
In addition to the actual MAD contents, the other struct ib_user_mad
fields will be filled in with information on the received MAD. For
example, the remote LID will be in mad.lid.
If a send times out, a receive will be generated with mad.status set
to ETIMEDOUT. Otherwise when a MAD has been successfully received,
mad.status will be 0.
poll()/select() may be used to wait until a MAD can be read.
Sending MADs
============
MADs are sent using write(). The agent ID for sending should be
filled into the id field of the MAD, the destination LID should be
filled into the lid field, and so on. The send side does support
RMPP so arbitrary length MAD can be sent. For example::
struct ib_user_mad *mad;
mad = malloc(sizeof *mad + mad_length);
/* fill in mad->data */
mad->hdr.id = my_agent; /* req.id from agent registration */
mad->hdr.lid = my_dest; /* in network byte order... */
/* etc. */
ret = write(fd, &mad, sizeof *mad + mad_length);
if (ret != sizeof *mad + mad_length)
perror("write");
Transaction IDs
===============
Users of the umad devices can use the lower 32 bits of the
transaction ID field (that is, the least significant half of the
field in network byte order) in MADs being sent to match
request/response pairs. The upper 32 bits are reserved for use by
the kernel and will be overwritten before a MAD is sent.
P_Key Index Handling
====================
The old ib_umad interface did not allow setting the P_Key index for
MADs that are sent and did not provide a way for obtaining the P_Key
index of received MADs. A new layout for struct ib_user_mad_hdr
with a pkey_index member has been defined; however, to preserve binary
compatibility with older applications, this new layout will not be used
unless one of IB_USER_MAD_ENABLE_PKEY or IB_USER_MAD_REGISTER_AGENT2 ioctl's
are called before a file descriptor is used for anything else.
In September 2008, the IB_USER_MAD_ABI_VERSION will be incremented
to 6, the new layout of struct ib_user_mad_hdr will be used by
default, and the IB_USER_MAD_ENABLE_PKEY ioctl will be removed.
Setting IsSM Capability Bit
===========================
To set the IsSM capability bit for a port, simply open the
corresponding issm device file. If the IsSM bit is already set,
then the open call will block until the bit is cleared (or return
immediately with errno set to EAGAIN if the O_NONBLOCK flag is
passed to open()). The IsSM bit will be cleared when the issm file
is closed. No read, write or other operations can be performed on
the issm file.
/dev files
==========
To create the appropriate character device files automatically with
udev, a rule like::
KERNEL=="umad*", NAME="infiniband/%k"
KERNEL=="issm*", NAME="infiniband/%k"
can be used. This will create device nodes named::
/dev/infiniband/umad0
/dev/infiniband/issm0
for the first port, and so on. The InfiniBand device and port
associated with these devices can be determined from the files::
/sys/class/infiniband_mad/umad0/ibdev
/sys/class/infiniband_mad/umad0/port
and::
/sys/class/infiniband_mad/issm0/ibdev
/sys/class/infiniband_mad/issm0/port
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
UMAD·ISSM 장치와 MAD 에이전트 등록
1-38각 InfiniBand 장치의 포트에는 `umad` 장치와 `issm` 장치가 하나씩 연결됩니다. 2포트 HCA에는 각각 두 개가 생기고, 스위치는 스위치 포트 0에 대해 각 유형 하나씩을 갖습니다.
MAD 에이전트를 만들려면 `struct ib_user_mad_reg_req`를 채운 뒤 적절한 장치 파일 디스크립터에 `IB_USER_MAD_REGISTER_AGENT` ioctl을 호출합니다. 등록이 성공하면 구조체에 32비트 에이전트 ID가 반환됩니다.
struct ib_user_mad_reg_req req = { /* ... */ };
ret = ioctl(fd, IB_USER_MAD_REGISTER_AGENT, (char *) &req);
if (!ret)
my_agent = req.id;
else
perror("agent register");
에이전트는 `IB_USER_MAD_UNREGISTER_AGENT` ioctl로 등록 해제할 수 있습니다. 파일 디스크립터를 닫으면 그 디스크립터를 통해 등록한 모든 에이전트도 자동으로 등록 해제됩니다.
2014년에 추가된 새 등록 ioctl은 등록 시 부가 필드를 전달할 수 있게 했습니다. 이 등록 호출을 사용하는 사용자는 아래에서 설명하는 `pkey_index` 사용도 암묵적으로 활성화합니다.
장치 유형과 생성 단위, 기본 용도를 구분합니다.
등록 요청부터 자동 정리까지의 흐름입니다.
====================
Userspace MAD access
====================
Device files
============
Each port of each InfiniBand device has a "umad" device and an
"issm" device attached. For example, a two-port HCA will have two
umad devices and two issm devices, while a switch will have one
device of each type (for switch port 0).
Creating MAD agents
===================
A MAD agent can be created by filling in a struct ib_user_mad_reg_req
and then calling the IB_USER_MAD_REGISTER_AGENT ioctl on a file
descriptor for the appropriate device file. If the registration
request succeeds, a 32-bit id will be returned in the structure.
For example::
struct ib_user_mad_reg_req req = { /* ... */ };
ret = ioctl(fd, IB_USER_MAD_REGISTER_AGENT, (char *) &req);
if (!ret)
my_agent = req.id;
else
perror("agent register");
Agents can be unregistered with the IB_USER_MAD_UNREGISTER_AGENT
ioctl. Also, all agents registered through a file descriptor will
be unregistered when the descriptor is closed.
2014
a new registration ioctl is now provided which allows additional
fields to be provided during registration.
Users of this registration call are implicitly setting the use of
pkey_index (see below).
MAD 수신, RMPP 재할당과 상태 처리
39-85MAD는 `read()`로 수신하며 수신 측은 RMPP를 지원합니다. `read()`에 넘기는 버퍼는 최소한 `struct ib_user_mad + 256`바이트여야 합니다.
받은 RMPP MAD가 버퍼보다 크면 오류 번호가 `ENOSPC`로 설정되고 필요한 버퍼 길이가 `mad.length`에 기록됩니다. 호출자는 이 길이에 맞춰 버퍼를 다시 할당한 뒤 `read()`를 재시도합니다.
mad = malloc(sizeof *mad + 256);
ret = read(fd, mad, sizeof *mad + 256);
if (ret == -ENOSPC) {
length = mad.length;
free(mad);
mad = malloc(sizeof *mad + length);
ret = read(fd, mad, sizeof *mad + length);
}
실제 MAD 내용과 함께 `struct ib_user_mad`의 나머지 필드에도 수신 정보가 채워집니다. 예를 들어 원격 LID는 `mad.lid`에서 얻습니다.
송신 타임아웃이 발생하면 `mad.status=ETIMEDOUT`인 수신 이벤트가 생성됩니다. MAD를 정상적으로 받으면 `mad.status`는 0입니다. 읽을 MAD가 생길 때까지 `poll()` 또는 `select()`로 기다릴 수 있습니다.
버퍼 크기와 전송 상태에 따라 확인할 필드를 정리합니다.
작은 초기 버퍼로 길이를 알아낸 뒤 정확한 크기로 다시 읽는 절차입니다.
Receiving MADs
==============
MADs are received using read(). The receive side now supports
RMPP. The buffer passed to read() must be at least one
struct ib_user_mad + 256 bytes. For example:
If the buffer passed is not large enough to hold the received
MAD (RMPP), the errno is set to ENOSPC and the length of the
buffer needed is set in mad.length.
Example for normal MAD (non RMPP) reads::
struct ib_user_mad *mad;
mad = malloc(sizeof *mad + 256);
ret = read(fd, mad, sizeof *mad + 256);
if (ret != sizeof mad + 256) {
perror("read");
free(mad);
}
Example for RMPP reads::
struct ib_user_mad *mad;
mad = malloc(sizeof *mad + 256);
ret = read(fd, mad, sizeof *mad + 256);
if (ret == -ENOSPC)) {
length = mad.length;
free(mad);
mad = malloc(sizeof *mad + length);
ret = read(fd, mad, sizeof *mad + length);
}
if (ret < 0) {
perror("read");
free(mad);
}
In addition to the actual MAD contents, the other struct ib_user_mad
fields will be filled in with information on the received MAD. For
example, the remote LID will be in mad.lid.
If a send times out, a receive will be generated with mad.status set
to ETIMEDOUT. Otherwise when a MAD has been successfully received,
mad.status will be 0.
poll()/select() may be used to wait until a MAD can be read.
MAD 송신과 Transaction ID 소유 범위
86-116MAD는 `write()`로 보냅니다. 송신 에이전트 ID는 MAD의 `id` 필드에, 목적지 LID는 `lid` 필드에 넣고 다른 주소 정보도 대응 필드에 채웁니다. 송신 측도 RMPP를 지원하므로 임의 길이의 MAD를 보낼 수 있습니다.
mad = malloc(sizeof *mad + mad_length);
mad->hdr.id = my_agent;
mad->hdr.lid = my_dest;
ret = write(fd, &mad, sizeof *mad + mad_length);
`umad` 장치 사용자는 송신 MAD의 transaction ID 하위 32비트, 즉 네트워크 바이트 순서에서 덜 중요한 절반을 요청과 응답의 짝을 맞추는 데 사용할 수 있습니다. 상위 32비트는 커널용으로 예약되어 있으며 MAD를 보내기 전에 커널이 덮어씁니다.
사용자가 채우는 값과 커널이 예약한 transaction ID 범위를 구분합니다.
에이전트와 목적지를 지정하고 길이 전체를 기록하는 순서입니다.
Sending MADs
============
MADs are sent using write(). The agent ID for sending should be
filled into the id field of the MAD, the destination LID should be
filled into the lid field, and so on. The send side does support
RMPP so arbitrary length MAD can be sent. For example::
struct ib_user_mad *mad;
mad = malloc(sizeof *mad + mad_length);
/* fill in mad->data */
mad->hdr.id = my_agent; /* req.id from agent registration */
mad->hdr.lid = my_dest; /* in network byte order... */
/* etc. */
ret = write(fd, &mad, sizeof *mad + mad_length);
if (ret != sizeof *mad + mad_length)
perror("write");
Transaction IDs
===============
Users of the umad devices can use the lower 32 bits of the
transaction ID field (that is, the least significant half of the
field in network byte order) in MADs being sent to match
request/response pairs. The upper 32 bits are reserved for use by
the kernel and will be overwritten before a MAD is sent.
P_Key 인덱스 ABI와 IsSM capability bit
117-142이전 `ib_umad` 인터페이스는 송신 MAD의 P_Key 인덱스를 설정할 수 없었고 수신 MAD의 P_Key 인덱스를 알아낼 방법도 없었습니다. 이를 위해 `pkey_index` 멤버가 있는 새 `struct ib_user_mad_hdr` 배치가 정의되었습니다.
기존 애플리케이션과의 바이너리 호환성을 지키기 위해, 파일 디스크립터를 다른 용도로 사용하기 전에 `IB_USER_MAD_ENABLE_PKEY` 또는 `IB_USER_MAD_REGISTER_AGENT2` ioctl 가운데 하나를 호출해야 새 헤더 배치가 사용됩니다.
문서에 기록된 전환 계획에 따르면 2008년 9월 `IB_USER_MAD_ABI_VERSION`을 6으로 올리고 새 `ib_user_mad_hdr` 배치를 기본값으로 사용하며 `IB_USER_MAD_ENABLE_PKEY` ioctl을 제거합니다.
포트의 IsSM capability bit를 설정하려면 대응 `issm` 장치 파일을 열기만 하면 됩니다. 비트가 이미 설정되어 있으면 비트가 지워질 때까지 `open()`이 블록됩니다. `O_NONBLOCK`을 사용하면 즉시 실패하고 `errno=EAGAIN`이 됩니다.
`issm` 파일을 닫으면 IsSM 비트가 지워집니다. 이 파일에서는 read, write 또는 다른 연산을 수행할 수 없습니다.
이전 ABI와 새 헤더 배치의 선택 조건입니다.
블로킹 모드, 비블로킹 모드, 닫기 동작을 구분합니다.
`issm` 파일 디스크립터의 열림 상태가 capability bit 소유를 표현합니다.
P_Key Index Handling
====================
The old ib_umad interface did not allow setting the P_Key index for
MADs that are sent and did not provide a way for obtaining the P_Key
index of received MADs. A new layout for struct ib_user_mad_hdr
with a pkey_index member has been defined; however, to preserve binary
compatibility with older applications, this new layout will not be used
unless one of IB_USER_MAD_ENABLE_PKEY or IB_USER_MAD_REGISTER_AGENT2 ioctl's
are called before a file descriptor is used for anything else.
In September 2008, the IB_USER_MAD_ABI_VERSION will be incremented
to 6, the new layout of struct ib_user_mad_hdr will be used by
default, and the IB_USER_MAD_ENABLE_PKEY ioctl will be removed.
Setting IsSM Capability Bit
===========================
To set the IsSM capability bit for a port, simply open the
corresponding issm device file. If the IsSM bit is already set,
then the open call will block until the bit is cleared (or return
immediately with errno set to EAGAIN if the O_NONBLOCK flag is
passed to open()). The IsSM bit will be cleared when the issm file
is closed. No read, write or other operations can be performed on
the issm file.
udev 장치 노드와 포트 매핑 sysfs
143-166적절한 문자 장치 파일을 udev로 자동 생성하려면 `umad*`와 `issm*` 커널 장치 이름을 `infiniband/%k`로 배치하는 규칙을 사용할 수 있습니다.
KERNEL=="umad*", NAME="infiniband/%k"
KERNEL=="issm*", NAME="infiniband/%k"
첫 포트에는 `/dev/infiniband/umad0`과 `/dev/infiniband/issm0` 장치 노드가 생성되고 이후 포트도 같은 방식으로 번호가 증가합니다.
각 장치가 연결된 InfiniBand 장치와 포트는 `/sys/class/infiniband_mad/<device>/ibdev` 및 `port` 파일에서 확인합니다. `umad0`과 `issm0` 모두 같은 형식의 매핑 파일을 제공합니다.
첫 포트의 장치 노드 및 연결 정보를 찾는 sysfs 파일입니다.
udev가 만든 노드를 실제 InfiniBand 장치와 포트에 대응시키는 절차입니다.
/dev files
==========
To create the appropriate character device files automatically with
udev, a rule like::
KERNEL=="umad*", NAME="infiniband/%k"
KERNEL=="issm*", NAME="infiniband/%k"
can be used. This will create device nodes named::
/dev/infiniband/umad0
/dev/infiniband/issm0
for the first port, and so on. The InfiniBand device and port
associated with these devices can be determined from the files::
/sys/class/infiniband_mad/umad0/ibdev
/sys/class/infiniband_mad/umad0/port
and::
/sys/class/infiniband_mad/issm0/ibdev
/sys/class/infiniband_mad/issm0/port
요약·해설
user_mad.rst:1-166Userspace MAD 인터페이스는 포트별 `umad`·`issm` 장치, ioctl 기반 에이전트 등록, RMPP를 포함한 read/write 데이터 경로를 제공합니다. 하위 transaction ID는 사용자가 소유하고 상위 절반은 커널이 예약하며, P_Key 헤더 배치는 호환 ioctl로 선택하고 IsSM bit는 `issm` 파일의 열림 수명으로 관리합니다.
원문 분량과 핵심 적용 대상을 요약합니다.
문서의 주요 동작 순서를 압축해 보여 줍니다.