InfiniBand / RDMA 심화

InfiniBand 서브넷 아키텍처, RDMA 핵심 개념(QP, CQ, MR), 커널 Verbs API, 사용자 공간 라이브러리(libibverbs, librdmacm), IPoIB, 상위 프로토콜(SRP, iSER, NVMe-oF RDMA), GPUDirect RDMA, 성능 최적화 및 트러블슈팅 종합 가이드. 커널 내부 데이터 경로, 핵심 자료구조/API, 운영 환경 튜닝 포인트와 장애 디버깅 절차까지 실무 관점으로 다룹니다.

전제 조건: PCI/PCIe, DMA 심화, NUMA 문서를 먼저 읽으세요. InfiniBand 성능 문제의 상당수는 프로토콜보다도 PCIe 대역폭, 메모리 핀닝, NUMA 배치에서 먼저 발생하므로 하드웨어 경로를 먼저 고정해야 합니다.
일상 비유: 이 개념은 자동 창고의 전용 컨베이어 + 출입증과 비슷합니다. 버퍼(MR)를 미리 등록해 두고 출입증(rkey)을 받은 상대만 직접 물건을 내려놓을 수 있다는 점이 RDMA Write/Read 모델과 닮아 있습니다.

핵심 요약

  • HCA — RDMA 엔진, DMA, QP/CQ를 가진 InfiniBand NIC입니다.
  • QP — 송신/수신 작업이 실제로 적재되는 하드웨어 큐 쌍입니다.
  • CQ — 완료 이벤트를 회수하는 큐이며 지연과 CPU 사용률을 좌우합니다.
  • MR / rkey — 원격 접근 가능한 메모리와 그 접근 권한입니다.
  • SM / SA — 패브릭에 LID와 경로를 배포하고 파티션 정책을 관리합니다.

단계별 이해

  1. 패브릭 준비
    포트가 Active이고 SM이 살아 있으며 LID/GID/P_Key가 정상 배포됐는지 확인합니다.
  2. 리소스 생성
    프로세스는 PD, MR, CQ, QP를 만들고 버퍼를 등록합니다.
  3. 경로 확정
    QPN/LID/GID/PSN을 교환하거나 librdmacm으로 경로를 해석해 QP를 RTS까지 올립니다.
  4. 데이터 전송
    WR을 post하고 CQ를 poll하여 Send, RDMA Write/Read, Atomic을 실행합니다.
  5. 스케일링
    SRQ/XRC/DC, NUMA 배치, AR/QoS, GPU 메모리 연동으로 대규모 성능을 끌어올립니다.
관련 표준: InfiniBand Architecture Specification, RDMA Consortium — 고속 네트워킹 하드웨어 및 프로토콜 표준입니다. 2025년 7월 31일에는 IBTA가 Volume 1 / Volume 2 Release 2.0을 공개했고, 공개 로드맵은 3.2 Tb/s급 링크까지 확장 방향을 제시하고 있습니다. 종합 목록은 참고자료 — 표준 & 규격 섹션을 참고하세요.

InfiniBand 개요

InfiniBand(IB)는 고성능 컴퓨팅(HPC), 데이터센터, 스토리지 인터커넥트를 위해 설계된 고대역폭·저지연 네트워크 기술입니다. RDMA(Remote Direct Memory Access)를 네이티브로 지원하여 커널 바이패스, 제로카피, 프로토콜 오프로드를 통해 전통적인 TCP/IP 소켓 대비 극적인 성능 향상을 제공합니다.

이 문서는 네이티브 InfiniBand 패브릭을 중심으로 설명합니다. 같은 Verbs API를 쓰더라도 link_layer가 Ethernet이면 RoCE 계열이며, 이 경우 손실 모델, 혼잡 제어, 운영 도구, 장애 지점이 달라집니다. 따라서 실무에서는 먼저 장비가 정말 InfiniBand 포트인지, 아니면 Ethernet 포트에서 RDMA를 수행하는지부터 구분해야 합니다.

InfiniBand vs Ethernet 비교

특성InfiniBandEthernet (RoCE v2)iWARP
RDMA 지원 네이티브 RoCE v1/v2 (컨버전스) TCP 위에 RDMA
전송 계층 IB Transport (신뢰성 내장) UDP/IP (RoCE v2) TCP/IP
최대 대역폭 공개 규격상 XDR 800Gb/s급 이상으로 확장 800GbE급까지 확장 상용 생태계는 제한적
지연시간 ~0.5 μs (HCA-to-HCA) ~1–2 μs ~5–10 μs
손실 처리 신용 기반 흐름 제어 (Lossless) PFC/ECN 필요 (Lossless 구성) TCP 재전송
서브넷 관리 Subnet Manager (opensm) 표준 이더넷 스위칭 표준 이더넷 스위칭
주요 사용처 HPC, AI/ML 클러스터, 스토리지 데이터센터, 클라우드 엔터프라이즈 스토리지

RDMA 전송 기술 비교

기술하위 계층라우팅Lossless 요구특징
IB Native RDMA InfiniBand L2 IB 서브넷 라우팅 내장 (Credit-based) 최저 지연, HPC 표준
RoCE v1 Ethernet L2 L2 전용 PFC 필수 같은 VLAN 내에서만 동작
RoCE v2 UDP/IP IP 라우팅 가능 PFC + ECN 권장 L3 라우팅, 데이터센터 표준
iWARP TCP/IP IP 라우팅 가능 불필요 (TCP 재전송) Lossy 네트워크 호환, 높은 지연
RDMA 핵심 가치: RDMA는 세 가지 핵심 기술을 결합합니다: (1) 커널 바이패스 — 데이터 경로에서 커널 개입 없이 사용자 공간에서 직접 HW 큐에 접근, (2) 제로카피 — 애플리케이션 메모리와 NIC 간 중간 버퍼 복사 없이 직접 DMA 전송, (3) 프로토콜 오프로드 — 전송 프로토콜 처리(세그멘테이션, 신뢰성, 흐름 제어)를 HCA 하드웨어가 수행. 이를 통해 CPU 사용률을 극적으로 낮추면서 높은 처리량과 낮은 지연시간을 동시에 달성합니다.

InfiniBand 서브넷 아키텍처

서브넷 구성 요소

InfiniBand 서브넷은 다음 구성 요소로 이루어집니다:

물리 계층 및 속도

세대lane 신호 속도대표 포트 속도주요 링크 폭비고
SDR2.5 Gbaud4X 기준 8 Gb/s1X / 4X / 12X초기 세대, 8b/10b
DDR5 Gbaud4X 기준 16 Gb/s1X / 4X / 12X8b/10b
QDR10 Gbaud4X 기준 32 Gb/s1X / 4X / 12X오랫동안 HPC 표준
FDR14.0625 Gbaud4X 기준 54.54 Gb/s4X / 10X64b/66b 도입
EDR25 Gbaud4X 기준 100 Gb/s1X / 2X / 4X현대 세대의 출발점
HDR50 GbaudHDR100(2X), HDR200(4X)2X / 4XPAM4
NDR100 GbaudNDR200(2X), NDR400(4X)2X / 4XPAM4
XDR200 GbaudXDR800(4X), 스위치 간 1.6 Tb/s급 링크 지원4X / 8X최신 공개 세대
속도 표 해석: 최신 실배치 패브릭은 대체로 4X 링크를 중심으로 설계되며, HDR/NDR 세대에는 2X 포트(HDR100, NDR200)도 흔합니다. 과거 문헌에 자주 보이는 12X 표기는 주로 구세대 백플레인/스위치 문맥이며, 최신 패브릭 설계에서는 4X와 8X를 우선적으로 보는 편이 실무에 맞습니다.

주소 체계

InfiniBand는 단순히 "빠른 NIC"가 아니라, 패브릭 수준에서 경로와 서비스 클래스를 제어하는 링크 계층을 내장합니다. 애플리케이션은 QP를 만들고 WR을 post하지만, 실제 패킷은 SA가 돌려준 Path Record와 SM이 배포한 SL/VL 정책에 따라 흐릅니다.

실무 포인트: 네트워크 성능이 이상할 때 ibv_post_send() 호출부만 보지 말고, 해당 연결의 Path MTU, SL, P_Key, LID 경로, AR 설정까지 함께 봐야 합니다. InfiniBand의 병목은 소켓 버퍼보다도 경로 정책과 패브릭 큐 배치에서 자주 발생합니다.

관리 평면: SM, SA, MAD, CM

InfiniBand의 관리 평면은 데이터 평면과 분리되어 있습니다. 패브릭이 처음 올라올 때는 SM(Subnet Manager)이 토폴로지를 스캔하고, 각 포트에 LID를 부여하고, 스위치의 포워딩 테이블을 채웁니다. 이후 애플리케이션과 ULP는 SA(Subnet Administration)에 Path Record, 멀티캐스트 그룹, 파티션 정보를 질의합니다.

제어 평면과 데이터 평면 분리 Host A Application / MPI / Storage libibverbs + librdmacm Local HCA QP0/QP1 + RC/UD QP uverbs / umad / rdma_cm opensm / SA LID 할당, Path Record, P_Key, 라우팅 IB Switch / Fabric LFT, SL→VL, Credit-based FC Adaptive Routing / Partition 정책 Host B Application / MPI / Storage libibverbs + librdmacm Remote HCA QP0/QP1 + RC/UD QP CQ / MR / Doorbell SA 조회 / rdma_resolve_route / 파티션 정보 SMP / VL 기반 정책 배포 실제 데이터 경로: RC / UD / XRC / DC QP InfiniBand Subnet Host A HCA (Port 1) QP / CQ / MR Host B HCA (Port 1) QP / CQ / MR IB Switch LID-based Forwarding Subnet Manager opensm / Switch SM LID 할당 / 경로 계산 IB Router GID-based L3 Routing SMP (관리)

핵심 자료구조 및 개념

Queue Pair (QP)

QP는 RDMA 통신의 기본 단위로, Send Queue (SQ)Receive Queue (RQ) 한 쌍으로 구성됩니다. 각 QP는 고유한 QP Number (QPN)를 가지며, 원격 QP와 1:1(RC), 1:N(UD) 등의 연결 관계를 맺습니다.

Completion Queue (CQ)

CQ는 WR의 완료 이벤트(Work Completion, WC)를 수신하는 큐입니다. 하나의 CQ를 여러 QP의 SQ/RQ에 공유할 수 있습니다. 완료 확인 방식으로 polling(busy-wait)과 completion channel(이벤트 기반) 두 가지를 지원합니다.

Memory Region (MR)

RDMA 동작에 사용할 메모리 영역을 HCA에 등록하는 객체입니다. 등록 시 물리 페이지가 핀(pin)되고, HCA가 DMA로 직접 접근할 수 있는 가상→물리 주소 변환 테이블이 생성됩니다.

고급 메모리 등록: ODP, MW, dma-buf

실무에서는 단순한 ibv_reg_mr()만으로는 부족한 경우가 많습니다. 대용량 메모리, GPU 메모리, 고빈도 권한 부여/회수 패턴을 처리하려면 메모리 등록 전략 자체를 따로 설계해야 합니다.

보안 관점: rkey는 사실상 "원격 DMA 접근 토큰"입니다. 데이터 버퍼 주소와 rkey를 애플리케이션 프로토콜에 평문으로 흘려보내면 그 자체가 capability 누출이 되므로, 제어 채널과 데이터 채널을 분리하고 무효화 시점을 설계해야 합니다.

Protection Domain (PD) / Address Handle (AH)

Work Request (WR) / Work Completion (WC)

QP 상태 머신

QP는 엄격한 상태 전이 순서를 따라야 합니다:

RESET INIT RTR RTS SQD ERROR ibv_modify_qp P_Key, Port Remote QPN Drain SQ Resume 에러 발생 시 Reset 데이터 전송 가능 수신 가능
QP 상태 전이 순서 엄수: QP 상태는 반드시 RESET → INIT → RTR → RTS 순서로 전이해야 합니다. INIT 단계에서 P_Key, 포트 번호, 접근 플래그를 설정하고, RTR(Ready to Receive)에서 원격 QPN, LID/GID, PSN 등 수신 파라미터를 설정하며, RTS(Ready to Send)에서 타임아웃, 재시도 횟수 등 송신 파라미터를 설정합니다. 순서를 건너뛰면 ibv_modify_qp()-EINVAL을 반환합니다.
MR 등록 비용과 ODP: ibv_reg_mr()는 물리 페이지를 핀(pin)하므로 대용량 메모리 등록 시 상당한 시간이 소요됩니다. Mellanox/NVIDIA ConnectX HCA는 ODP (On-Demand Paging)을 지원하여 실제 접근 시점에 페이지를 핀하는 지연 등록을 제공합니다. ibv_reg_mr()IBV_ACCESS_ON_DEMAND 플래그를 지정하면 ODP가 활성화됩니다. ODP는 등록 시간을 단축하지만, 첫 접근 시 페이지 폴트 오버헤드가 발생할 수 있습니다.

RDMA 동작 (Operations)

Send / Receive

양측 관여(two-sided) 동작입니다. 송신 측이 IBV_WR_SEND WR을 SQ에 post하면, 수신 측은 미리 RQ에 게시한 Receive WR의 버퍼로 데이터를 수신합니다. 수신 측 CPU가 반드시 관여해야 하므로 RDMA Write/Read 대비 오버헤드가 높지만, 메시지 도착을 수신 측이 즉시 인지할 수 있는 장점이 있습니다.

RDMA Write / RDMA Write with Immediate

단측 관여(one-sided) 동작입니다. 송신 측이 원격 MR의 주소(rkey + remote addr)를 지정하여 데이터를 직접 씁니다. 수신 측 CPU는 전혀 관여하지 않습니다 (커널 바이패스 + 제로카피). RDMA Write with Immediate는 32비트 즉시값(imm_data)을 함께 전달하며, 수신 측 RQ에서 완료 이벤트가 생성되어 데이터 도착을 알릴 수 있습니다.

RDMA Read

단측 관여 동작입니다. 로컬 측이 원격 MR에서 데이터를 읽어옵니다. 원격 MR의 rkey와 주소를 알아야 하며, 원격 측 CPU 개입 없이 HCA가 직접 처리합니다. 원격 MR에 IBV_ACCESS_REMOTE_READ 접근 권한이 설정되어 있어야 합니다.

Atomic 연산 (CAS, FAA)

Atomic 연산은 RC QP에서만 지원되며, 원격 MR에 IBV_ACCESS_REMOTE_ATOMIC 권한이 필요합니다.

연결 모드 — RC, UC, UD, XRC

QP 타입연결 방식신뢰성지원 동작MTU사용 사례
RC 연결 지향 (1:1) 신뢰 (ACK/재전송) Send, RDMA Write/Read, Atomic 최대 4KB 스토리지, 범용 RDMA
UC 연결 지향 (1:1) 비신뢰 (무 ACK) Send, RDMA Write 최대 4KB 벌크 전송 (손실 허용)
UD 비연결 (1:N) 비신뢰 Send 전용 최대 MTU (4KB) 멀티캐스트, 관리 트래픽
XRC 연결 지향 (N:1 SRQ) 신뢰 Send, RDMA Write/Read, Atomic 최대 4KB 다수 프로세스 간 효율적 통신

스케일링 모델: SRQ, XRC, DC, Tag Matching

작은 클러스터에서는 RC QP를 peer 수만큼 만드는 단순 모델도 충분하지만, 대규모 MPI/AI/스토리지 환경에서는 QP와 RQ 상태가 급격히 늘어납니다. 그래서 RDMA 스택은 다음과 같은 스케일링 기법을 함께 사용합니다.

이식성 주의: SRQ, XRC는 비교적 표준적인 축에 속하지만, DC(DCT/DCI), UMR, CQE compression, DevX 같은 기능은 주로 mlx5 provider 확장에 걸쳐 있습니다. 성능은 좋아도 애플리케이션 이식성은 낮아질 수 있습니다.
Host A Application Buffer (MR) SQ RQ CQ HCA (RDMA Engine) IB Fabric (Switch / Router) Credit-based Flow Control Host B Application Buffer (MR) SQ RQ CQ HCA (RDMA Engine) RDMA Write (Zero-Copy) DMA Read DMA Write RDMA Read (reverse direction)
RDMA Write vs Send 선택 기준: RDMA Write는 수신 측 CPU 개입이 없어 처리량이 높고 지연이 낮지만, 수신 측에 데이터 도착을 알리려면 별도 메커니즘(polling, RDMA Write with Immediate)이 필요합니다. Send/Recv는 수신 측이 데이터 도착을 즉시 인지할 수 있어 제어 메시지, 작은 RPC에 적합합니다. 대용량 데이터 전송에는 RDMA Write, 제어/시그널링에는 Send를 사용하는 하이브리드 패턴이 일반적입니다.

RDMA 동작 비교

동작방향관여 측수신 WR 필요원격 rkey 필요CQ 완료 위치
Send송신→수신양측 (two-sided)아니오송신 + 수신 CQ
RDMA Write로컬→원격송신측만 (one-sided)아니오송신 CQ만
RDMA Write+Imm로컬→원격양측예 (imm 수신용)송신 + 수신 CQ
RDMA Read원격→로컬로컬만 (one-sided)아니오로컬 CQ만
Atomic CAS원격 in-place로컬만아니오로컬 CQ만
Atomic FAA원격 in-place로컬만아니오로컬 CQ만

리눅스 커널 InfiniBand 서브시스템

drivers/infiniband/ 소스 구조

drivers/infiniband/ 구조 drivers/infiniband/ core/ (ib_core) device.c, verbs.c, cq.c, mr_pool.c uverbs_main/cmd, umad_main sa_query.c, cm.c, mad.c addr.c, multicast.c, rdma_core.c Verbs API, uverbs, MAD/CM 공통 계층 hw/ (HCA 벤더 드라이버) mlx4/, mlx5/, hfi1/ bnxt_re/, irdma/ rxe/, siw/ (software RDMA) 실제 NIC/HCA 하드웨어 연동 ulp/ (Upper Layer Protocol) ipoib/, srp/, iser/, isert/ rtrs/ 등 RDMA 기반 상위 프로토콜 네트워크/스토리지 사용자 기능 제공 데이터/제어 흐름 1) 벤더 드라이버(hw/)가 `ib_register_device()`로 디바이스 등록 2) core/가 Verbs 객체(QP/CQ/MR)와 uverbs/umad 인터페이스 제공 3) 사용자 공간(libibverbs, opensm)은 `/dev/infiniband/*`를 통해 접근 4) ulp/가 IPoIB, iSER 등 기능을 조합해 서비스 제공 5) 공통 추상화 덕분에 IB/RoCE/iWARP를 동일한 Verbs 모델로 다룸

ib_core 모듈

ib_core는 InfiniBand 서브시스템의 핵심 프레임워크입니다. HCA 드라이버가 ib_register_device()로 디바이스를 등록하면, ib_core가 sysfs 항목 생성, 이벤트 알림, Verbs API 디스패치 등을 처리합니다. 모든 RDMA 디바이스(IB, RoCE, iWARP)가 동일한 Verbs 추상화를 통해 접근됩니다.

ib_uverbs / ib_umad

대표 모듈과 Kconfig

배포판 커널에서는 대부분 RDMA 기능이 모듈 형태로 제공됩니다. 현재 리눅스 메인라인 Kconfig와 rdma-core README를 기준으로, 실무에서 자주 만나는 항목만 추려 보면 다음과 같습니다.

역할대표 모듈Kconfig / 소스 기준비고
RDMA 미들레이어 ib_core menuconfig INFINIBAND Verbs 공통 프레임워크와 장치 등록 기반
사용자 공간 Verbs ib_uverbs INFINIBAND_USER_ACCESS, INFINIBAND_USER_MEM 계열 /dev/infiniband/uverbsN 제공
주소 해석 계층 ib_addr 계열 INFINIBAND_ADDR_TRANS GID, netdev 연동, 경로 해석 보조
IPoIB ib_ipoib INFINIBAND_IPOIB ib0 같은 netdev 제공
Mellanox / NVIDIA HCA mlx5_ib MLX5_INFINIBAND ConnectX 계열의 핵심 RDMA provider
Intel Omni-Path 계열 hfi1 INFINIBAND_HFI1 대규모 HPC 설치에서 자주 보임
소프트웨어 RoCE rdma_rxe RDMA_RXE Ethernet 기반 개발/랩 환경에 유용
소프트웨어 iWARP siw RDMA_SIW TCP/IP 기반 RDMA 기능 검증용

주요 커널 구조체

/* include/rdma/ib_verbs.h - 핵심 구조체 (간략화) */

struct ib_device {
    const char             *name;           /* 디바이스 이름 (mlx5_0 등) */
    struct ib_device_ops    ops;             /* Verbs 콜백 함수 테이블 */
    struct device           dev;             /* sysfs 디바이스 */
    u32                     phys_port_cnt;   /* 물리 포트 수 */
    struct ib_device_attr   attrs;           /* 디바이스 능력 (속성) */
    struct list_head        event_handler_list;
    enum rdma_transport_type (*get_transport)(struct ib_device *, u32);
};

struct ib_qp {
    struct ib_device       *device;
    struct ib_pd           *pd;             /* Protection Domain */
    struct ib_cq           *send_cq;        /* 송신 Completion Queue */
    struct ib_cq           *recv_cq;        /* 수신 Completion Queue */
    struct ib_srq          *srq;            /* Shared Receive Queue (선택) */
    u32                     qp_num;          /* QP Number */
    enum ib_qp_type        qp_type;         /* RC, UC, UD, XRC 등 */
    void                    (*event_handler)(struct ib_event *, void *);
};

struct ib_cq {
    struct ib_device       *device;
    int                     cqe;             /* CQ 엔트리 수 */
    struct ib_uobject      *uobject;
    ib_comp_handler         comp_handler;    /* 완료 콜백 */
    void                   *cq_context;
    int                     comp_vector;     /* IRQ 벡터 */
    enum ib_poll_context   poll_ctx;        /* 폴링 컨텍스트 */
};

struct ib_mr {
    struct ib_device       *device;
    struct ib_pd           *pd;
    u32                     lkey;            /* Local Key */
    u32                     rkey;            /* Remote Key */
    u64                     iova;            /* I/O Virtual Address */
    u64                     length;          /* 등록된 메모리 길이 */
    enum ib_mr_type       type;            /* MEM_REG, DMA, USER 등 */
};

커널 Verbs API

카테고리API 함수설명
디바이스ib_register_device()HCA 드라이버가 디바이스 등록
ib_query_device()디바이스 속성(포트 수, 최대 QP 수 등) 조회
PDib_alloc_pd()Protection Domain 생성
ib_dealloc_pd()PD 해제
QPib_create_qp()QP 생성 (타입, CQ, SRQ 지정)
ib_modify_qp()QP 상태 전이 (RESET→INIT→RTR→RTS)
ib_destroy_qp()QP 파괴
CQib_alloc_cq() / ib_create_cq()CQ 생성
ib_poll_cq()CQ에서 완료 이벤트 폴링
MRib_reg_user_mr()사용자 공간 메모리 등록
ib_dereg_mr()MR 해제
데이터 전송ib_post_send()SQ에 Work Request 게시
ib_post_recv()RQ에 Receive WR 게시

커널 내부에서 QP를 생성하고 데이터를 전송하는 기본 흐름:

/* 커널 Verbs API 사용 예제 (간략화) */
struct ib_pd *pd;
struct ib_cq *cq;
struct ib_qp *qp;

/* 1. Protection Domain 생성 */
pd = ib_alloc_pd(ib_dev, 0);

/* 2. Completion Queue 생성 */
cq = ib_alloc_cq(ib_dev, NULL, 256, 0, IB_POLL_SOFTIRQ);

/* 3. Queue Pair 생성 */
struct ib_qp_init_attr qp_attr = {
    .event_handler = my_qp_event,
    .send_cq = cq,
    .recv_cq = cq,
    .cap = {
        .max_send_wr  = 128,
        .max_recv_wr  = 128,
        .max_send_sge = 1,
        .max_recv_sge = 1,
    },
    .qp_type = IB_QPT_RC,
};
qp = ib_create_qp(pd, &qp_attr);

/* 4. QP 상태 전이: RESET → INIT → RTR → RTS */
struct ib_qp_attr attr;
memset(&attr, 0, sizeof(attr));
attr.qp_state        = IB_QPS_INIT;
attr.pkey_index      = 0;
attr.port_num        = 1;
attr.qp_access_flags = IB_ACCESS_REMOTE_WRITE | IB_ACCESS_REMOTE_READ;
ib_modify_qp(qp, &attr, IB_QP_STATE | IB_QP_PKEY_INDEX |
             IB_QP_PORT | IB_QP_ACCESS_FLAGS);
/* RTR, RTS 전이도 유사하게 진행 ... */

/* 5. Work Request 게시 (RDMA Write) */
struct ib_sge sge = {
    .addr   = dma_addr,
    .length = len,
    .lkey   = mr->lkey,
};
struct ib_send_wr wr = {
    .opcode     = IB_WR_RDMA_WRITE,
    .send_flags = IB_SEND_SIGNALED,
    .sg_list    = &sge,
    .num_sge    = 1,
    .wr.rdma    = {
        .remote_addr = remote_addr,
        .rkey        = remote_rkey,
    },
};
const struct ib_send_wr *bad_wr;
ib_post_send(qp, &wr, &bad_wr);

/* 6. 완료 폴링 */
struct ib_wc wc;
while (ib_poll_cq(cq, 1, &wc) == 0)
    /* busy wait */;
if (wc.status != IB_WC_SUCCESS)
    pr_err("WC error: %d\\n", wc.status);

사용자 공간 라이브러리

libibverbs (ibv_* API)

libibverbs는 RDMA Verbs API의 사용자 공간 구현체입니다. /dev/infiniband/uverbsN을 통해 커널의 ib_uverbs와 통신하며, 데이터 경로(post_send, poll_cq 등)는 메모리 매핑된 Doorbell/CQ를 통해 커널 바이패스로 동작합니다.

주요 API 함수:

librdmacm (rdma_* API)

librdmacm은 RDMA Connection Manager 라이브러리로, TCP 소켓과 유사한 연결 설정/해제 인터페이스를 제공합니다. QP 상태 전이를 자동으로 처리하므로 개발이 훨씬 간편합니다.

rdma-core 패키지

rdma-core는 libibverbs, librdmacm, 벤더 플러그인(libmlx5, libirdma 등), 관리 도구를 통합한 오픈소스 패키지입니다. 대부분의 Linux 배포판에서 rdma-core 패키지로 설치할 수 있습니다.

# rdma-core 설치 (Ubuntu/Debian)
sudo apt install rdma-core libibverbs-dev librdmacm-dev

# rdma-core 설치 (RHEL/CentOS)
sudo dnf install rdma-core libibverbs-devel librdmacm-devel
사용자 공간 진입점 정리:
  • /dev/infiniband/uverbsX — libibverbs가 PD/CQ/QP/MR 등 Verbs 객체를 생성하는 기본 경로
  • /dev/infiniband/rdma_cm — librdmacm이 주소 해석, 경로 해석, 연결 이벤트를 처리하는 경로
  • /dev/infiniband/umadX — opensm, saquery, 진단 도구가 MAD를 직접 보내는 경로
  • /dev/infiniband/issmX — 특정 포트를 SM 후보로 다룰 때 IsSM capability bit를 제어하는 경로

Provider 확장 API: mlx5dv, DevX, CQE 최적화

표준 Verbs는 공통 기능을 제공하지만, 최고 성능 튜닝은 provider 확장에 들어 있는 경우가 많습니다. 특히 mlx5 계열은 mlx5dv_*와 DevX를 통해 표준 계층이 아직 추상화하지 못한 하드웨어 기능을 직접 노출합니다.

확장 경로대표 기능언제 쓰는가주의점
mlx5dv_create_qp() DCT / DCI, 고급 QP 속성 대규모 희소 통신, MPI/AI collective 최적화 mlx5 전용, 타 provider 이식성 낮음
mlx5dv_create_cq() CQE compression, mini-CQE 포맷 대량 완료 이벤트에서 PCIe/메모리 대역폭 절감 디코딩 경로가 복잡해지고 관측성도 낮아질 수 있음
DevX 펌웨어 객체 직접 생성/수정 표준 Verbs보다 더 낮은 수준의 HW 기능 제어 펌웨어 의존성이 높고 코드 유지보수 비용이 큼

상위 통신 스택: UCX, Open MPI, libfabric

실제 HPC/AI 애플리케이션은 보통 ibv_post_send()를 직접 호출하지 않습니다. 대부분은 MPI, PGAS, RPC, collective 라이브러리가 UCX 또는 libfabric(OFI) 같은 중간 계층을 통해 Verbs와 provider 확장을 선택합니다.

애플리케이션이 실제로 타는 사용자 공간 스택 Application MPI / NCCL / RPC / Storage Collective / Tag matching Open MPI / MPICH UCX PML / MTL / Collective 계층 UCX UCP / UCT / multi-rail / GPU memory libfabric / OFI rc_x / dc / ud_x UCX transport alias verbs;ofi_rxm RDM endpoint layering Verbs mlx5dv
계층역할InfiniBand 문맥에서 중요한 점
UCX 전송 선택, 프로토콜 분할, multi-rail, GPU 메모리 연동 UCX_TLSrc, dc, cuda, rocm 조합을 제어하며, UCX_LOG_LEVEL=info로 실제 transport 선택을 볼 수 있습니다.
Open MPI MPI point-to-point, collective, RMA Open MPI v6.1.x 문서는 InfiniBand/RoCE를 UCX PML 경로로 지원하고, 과거 openib BTL은 더 이상 포함하지 않는다고 명시합니다.
libfabric / OFI provider 기반 통신 추상화 verbs provider는 libibverbs, librdmacm 위에 올라가며 FI_EP_RDM은 보통 verbs;ofi_rxm 형태로 layering 됩니다.
# UCX가 실제로 어떤 transport를 선택했는지 확인
ucx_info -d
UCX_LOG_LEVEL=info mpirun -x UCX_TLS=rc -x UCX_NET_DEVICES=mlx5_0:1 ./app

# Adaptive Routing이 켜진 SL을 UCX가 고르도록 시도
mpirun -x UCX_IB_AR_ENABLE=yes -x UCX_IB_SL=1 ./app

# Open MPI에서 UCX 경로를 명시
mpirun --mca pml ucx -x UCX_NET_DEVICES=mlx5_0:1 ./app

개발용 소프트웨어 RDMA 랩

네이티브 InfiniBand 장비가 없어도 RDMA 프로그래밍 모델 자체는 연습할 수 있습니다. rdma-core README는 rdma_rxesiw를 사용해 기존 NIC 위에 소프트웨어 RDMA 장치를 추가하는 방식을 안내합니다.

# Soft-RoCE (RXE) 예시
modprobe rdma_rxe
rdma link add rxe0 type rxe netdev eth0

# 소프트웨어 iWARP (SIW) 예시
modprobe siw
rdma link add siw0 type siw netdev eth0

# 장치 확인
rdma link
ibv_devices
중요: rxesiw는 Verbs 실험과 기능 검증에는 좋지만, 네이티브 InfiniBand 패브릭의 지연·혼잡·SM/SA·credit-based flow control 특성을 재현하지는 못합니다. 이들은 API/상태머신 학습용으로 이해하는 편이 정확합니다.

코드 예제 — RDMA RC Send/Recv

/* libibverbs RC Send/Recv 전체 흐름 (간략화) */
#include <infiniband/verbs.h>

int main(void)
{
    struct ibv_device **dev_list;
    struct ibv_context *ctx;
    struct ibv_pd *pd;
    struct ibv_mr *mr;
    struct ibv_cq *cq;
    struct ibv_qp *qp;
    char buf[4096];

    /* 1. 디바이스 열기 */
    dev_list = ibv_get_device_list(NULL);
    ctx = ibv_open_device(dev_list[0]);

    /* 2. PD, MR, CQ 생성 */
    pd = ibv_alloc_pd(ctx);
    mr = ibv_reg_mr(pd, buf, sizeof(buf),
                    IBV_ACCESS_LOCAL_WRITE |
                    IBV_ACCESS_REMOTE_WRITE |
                    IBV_ACCESS_REMOTE_READ);
    cq = ibv_create_cq(ctx, 16, NULL, NULL, 0);

    /* 3. QP 생성 */
    struct ibv_qp_init_attr qp_init = {
        .send_cq = cq,
        .recv_cq = cq,
        .cap = { .max_send_wr = 16, .max_recv_wr = 16,
                 .max_send_sge = 1, .max_recv_sge = 1 },
        .qp_type = IBV_QPT_RC,
    };
    qp = ibv_create_qp(pd, &qp_init);

    /* 4. QP 상태 전이: RESET → INIT → RTR → RTS */
    struct ibv_qp_attr attr;
    memset(&attr, 0, sizeof(attr));

    /* INIT */
    attr.qp_state        = IBV_QPS_INIT;
    attr.pkey_index      = 0;
    attr.port_num        = 1;
    attr.qp_access_flags = IBV_ACCESS_REMOTE_WRITE | IBV_ACCESS_REMOTE_READ;
    ibv_modify_qp(qp, &attr,
        IBV_QP_STATE | IBV_QP_PKEY_INDEX | IBV_QP_PORT | IBV_QP_ACCESS_FLAGS);

    /* RTR — 원격 QPN, LID, GID, PSN 필요 (out-of-band 교환) */
    attr.qp_state              = IBV_QPS_RTR;
    attr.path_mtu              = IBV_MTU_4096;
    attr.dest_qp_num           = remote_qpn;   /* 상대방 QPN */
    attr.rq_psn                = 0;
    attr.max_dest_rd_atomic    = 1;
    attr.min_rnr_timer         = 12;
    attr.ah_attr.dlid          = remote_lid;
    attr.ah_attr.port_num      = 1;
    ibv_modify_qp(qp, &attr,
        IBV_QP_STATE | IBV_QP_AV | IBV_QP_PATH_MTU |
        IBV_QP_DEST_QPN | IBV_QP_RQ_PSN |
        IBV_QP_MAX_DEST_RD_ATOMIC | IBV_QP_MIN_RNR_TIMER);

    /* RTS */
    attr.qp_state      = IBV_QPS_RTS;
    attr.sq_psn         = 0;
    attr.timeout        = 14;
    attr.retry_cnt      = 7;
    attr.rnr_retry      = 7;
    attr.max_rd_atomic  = 1;
    ibv_modify_qp(qp, &attr,
        IBV_QP_STATE | IBV_QP_SQ_PSN | IBV_QP_TIMEOUT |
        IBV_QP_RETRY_CNT | IBV_QP_RNR_RETRY | IBV_QP_MAX_QP_RD_ATOMIC);

    /* 5. Receive WR 게시 (수신 측) */
    struct ibv_sge recv_sge = { .addr = (uintptr_t)buf,
                                .length = sizeof(buf), .lkey = mr->lkey };
    struct ibv_recv_wr recv_wr = { .sg_list = &recv_sge, .num_sge = 1 };
    struct ibv_recv_wr *bad_recv;
    ibv_post_recv(qp, &recv_wr, &bad_recv);

    /* 6. Send WR 게시 (송신 측) */
    memcpy(buf, "Hello RDMA", 10);
    struct ibv_sge send_sge = { .addr = (uintptr_t)buf,
                                .length = 10, .lkey = mr->lkey };
    struct ibv_send_wr send_wr = {
        .opcode     = IBV_WR_SEND,
        .send_flags = IBV_SEND_SIGNALED,
        .sg_list    = &send_sge,
        .num_sge    = 1,
    };
    struct ibv_send_wr *bad_send;
    ibv_post_send(qp, &send_wr, &bad_send);

    /* 7. 완료 폴링 */
    struct ibv_wc wc;
    while (ibv_poll_cq(cq, 1, &wc) == 0)
        ;  /* busy-wait */

    /* 8. 정리 */
    ibv_destroy_qp(qp);
    ibv_destroy_cq(cq);
    ibv_dereg_mr(mr);
    ibv_dealloc_pd(pd);
    ibv_close_device(ctx);
    ibv_free_device_list(dev_list);
    return 0;
}

코드 예제 — RDMA Write with librdmacm

/* librdmacm RDMA Write 예제 (클라이언트 측, 간략화) */
#include <rdma/rdma_cma.h>
#include <infiniband/verbs.h>

int main(void)
{
    struct rdma_cm_id *id;
    struct rdma_event_channel *ec;
    struct rdma_conn_param conn_param = {};
    struct ibv_pd *pd;
    struct ibv_mr *mr;
    struct ibv_cq *cq;
    char buf[4096];

    /* 1. RDMA CM ID 생성 및 주소 해석 */
    ec = rdma_create_event_channel();
    rdma_create_id(ec, &id, NULL, RDMA_PS_TCP);

    struct sockaddr_in addr = {
        .sin_family = AF_INET,
        .sin_port   = htons(20000),
    };
    inet_pton(AF_INET, "192.168.1.100", &addr.sin_addr);
    rdma_resolve_addr(id, NULL, (struct sockaddr *)&addr, 2000);
    /* ... rdma_resolve_route() ... */

    /* 2. 리소스 생성 (rdmacm이 QP 상태 전이 자동 처리) */
    pd = ibv_alloc_pd(id->verbs);
    cq = ibv_create_cq(id->verbs, 16, NULL, NULL, 0);
    mr = ibv_reg_mr(pd, buf, sizeof(buf),
                    IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_WRITE);

    struct ibv_qp_init_attr qp_attr = {
        .send_cq = cq, .recv_cq = cq,
        .cap = { .max_send_wr = 16, .max_recv_wr = 16,
                 .max_send_sge = 1, .max_recv_sge = 1 },
        .qp_type = IBV_QPT_RC,
    };
    rdma_create_qp(id, pd, &qp_attr);

    /* 3. 연결 (QP 자동으로 RTS 전이) */
    rdma_connect(id, &conn_param);

    /* 4. RDMA Write (원격 rkey/addr은 out-of-band로 수신) */
    memcpy(buf, "RDMA Write Data", 15);
    struct ibv_sge sge = {
        .addr = (uintptr_t)buf, .length = 15, .lkey = mr->lkey
    };
    struct ibv_send_wr wr = {
        .opcode     = IBV_WR_RDMA_WRITE,
        .send_flags = IBV_SEND_SIGNALED,
        .sg_list    = &sge,
        .num_sge    = 1,
        .wr.rdma    = { .remote_addr = remote_addr, .rkey = remote_rkey },
    };
    struct ibv_send_wr *bad;
    ibv_post_send(id->qp, &wr, &bad);

    /* 5. 완료 대기 및 정리 */
    struct ibv_wc wc;
    while (ibv_poll_cq(cq, 1, &wc) == 0);

    rdma_disconnect(id);
    rdma_destroy_qp(id);
    ibv_dereg_mr(mr);
    ibv_destroy_cq(cq);
    ibv_dealloc_pd(pd);
    rdma_destroy_id(id);
rdma_destroy_event_channel(ec);
    return 0;
}

sysfs / 디바이스 노드 / ABI

성능 분석이나 장애 대응을 할 때는 Verbs 호출만 보지 말고, 커널이 노출하는 관측 경로를 함께 붙잡아야 합니다. Linux RDMA 스택은 사용자 API뿐 아니라 /sys/class/infiniband*, /dev/infiniband/*를 통해 상태, 포트 속성, 카운터, ABI 매핑, 관리 디바이스 정보를 꽤 풍부하게 노출합니다.

사용자 공간, 문자 디바이스, sysfs의 연결 Applications MPI / Storage / RPC perf tools / opensm /dev/infiniband/uverbs0 PD / CQ / QP / MR 생성 /dev/infiniband/rdma_cm 주소/경로 해석, 연결 이벤트 /dev/infiniband/umad0 MAD / SM / SA / 진단 도구 /sys/class/infiniband node_guid, fw_ver ports/*/state, lid, rate /sys/class/infiniband_mad umadN ↔ ibdev/port 매핑 /sys/class/infiniband_verbs uverbsN ↔ ABI / ibdev 매핑 HCA mlx5_0 Port 1
경로의미언제 보는가
/sys/class/infiniband/<dev>/node_type
/sys/class/infiniband/<dev>/node_guid
/sys/class/infiniband/<dev>/fw_ver
장치 종류, GUID, 펌웨어 버전 벤더 이슈 분리, 펌웨어 호환성 점검
/sys/class/infiniband/<dev>/ports/<port>/{state,phys_state,link_layer,lid,rate,sm_lid,sm_sl} 포트 활성 상태, 링크 계층, LID, 속도, 연결된 SM 정보 포트가 왜 INIT/ACTIVE에 머무는지, InfiniBand와 RoCE를 구분할 때
/sys/class/infiniband/<dev>/ports/<port>/counters/* 링크/패킷/에러 카운터 재시도, 링크 에러, 혼잡 징후 확인
/sys/class/infiniband/<dev>/ports/<port>/gid_attrs/types/*
/sys/class/infiniband/<dev>/ports/<port>/gid_attrs/ndevs/*
GID 타입과 연동 netdev 매핑 RoCE GID 해석, IPoIB / Ethernet 연동 확인
/sys/class/infiniband_mad/umadN/{ibdev,port} umad 문자 디바이스가 어느 HCA/포트와 연결되는지 표시 opensm, saquery, ibdiagnet가 어떤 포트를 쓰는지 추적
/sys/class/infiniband_verbs/uverbsN/{ibdev,abi_version} uverbs 장치와 커널 ABI 버전 매핑 사용자 공간/커널 ABI mismatch 의심 시
# 기본 장치/포트 상태 관찰
cat /sys/class/infiniband/mlx5_0/node_guid
cat /sys/class/infiniband/mlx5_0/fw_ver
cat /sys/class/infiniband/mlx5_0/ports/1/link_layer
cat /sys/class/infiniband/mlx5_0/ports/1/state
cat /sys/class/infiniband/mlx5_0/ports/1/rate

# uverbs / umad가 어느 장치에 매핑되는지 확인
cat /sys/class/infiniband_verbs/uverbs0/ibdev
cat /sys/class/infiniband_mad/umad0/ibdev
cat /sys/class/infiniband_mad/umad0/port
최신 커널 방향: 2026년 3월 5일자 최신 커널 문서(next 계열)에는 사용자 capability(UCAP) 문서가 추가되어, 일부 펌웨어 기능을 세분화된 문자 디바이스 권한으로 위임하는 방향이 설명됩니다. 아직 모든 배포판에서 일반화된 기능은 아니지만, DevX 같은 저수준 접근을 더 안전하게 노출하려는 흐름으로 이해하면 됩니다.

IPoIB (IP over InfiniBand)

IPoIB는 InfiniBand 패브릭 위에서 기존 IP/TCP/UDP 프로토콜을 투명하게 사용할 수 있게 합니다. 커널의 drivers/infiniband/ulp/ipoib/에 구현되어 있으며, ib0, ib1 등의 네트워크 인터페이스로 나타납니다.

Connected Mode vs Datagram Mode

MTU 설정 및 커널 구성

# IPoIB Connected Mode 활성화
echo connected > /sys/class/net/ib0/mode

# Connected Mode MTU 설정 (최대 65520)
ip link set ib0 mtu 65520

# IPoIB 인터페이스에 IP 주소 할당
ip addr add 10.0.0.1/24 dev ib0
ip link set ib0 up

# 커널 구성 옵션
CONFIG_INFINIBAND_IPOIB=m
CONFIG_INFINIBAND_IPOIB_CM=y       # Connected Mode 지원
CONFIG_INFINIBAND_IPOIB_DEBUG=y    # 디버그 메시지 (선택)
IPoIB Connected Mode MTU: Connected Mode에서 MTU를 65520으로 설정하면 IP 계층 프래그먼테이션 없이 대용량 전송이 가능하여 TCP/IP 성능이 크게 향상됩니다. 다만, ARP/DHCP 등 브로드캐스트가 필요한 프로토콜은 여전히 UD(Datagram) QP를 사용합니다. 현재 모드는 cat /sys/class/net/ib0/mode로 직접 확인하는 편이 가장 확실합니다.

파티션, child interface, Enhanced IPoIB

IPoIB 인터페이스는 기본적으로 포트의 P_Key index 0을 사용합니다. 같은 물리 포트라도 다른 파티션에 참여해야 한다면 P_Key별 child interface를 만들어 별도의 IP 인터페이스처럼 운용할 수 있습니다.

# P_Key 0x8001 파티션용 child interface 생성
echo 0x8001 > /sys/class/net/ib0/create_child

# 생성된 인터페이스 확인 및 활성화
ip link show ib0.8001
ip link set ib0.8001 up
cat /sys/class/net/ib0.8001/pkey

# child interface 삭제
echo 0x8001 > /sys/class/net/ib0/delete_child
운영 팁: 일부 mlx5 스택은 UD 기반의 Enhanced IPoIB를 제공해 RSS/TSS, multi-queue, interrupt moderation, stateless offload를 결합합니다. 따라서 "항상 connected mode가 더 빠르다"라고 단정하면 안 되며, 작은 패킷 다중 흐름에서는 강화된 datagram 모드가 더 좋은 균형을 줄 수 있습니다.

상위 프로토콜 (ULP)

ULP프로토콜 계층용도커널 모듈특징
SRP SCSI over RDMA 블록 스토리지 ib_srp / ib_srpt SCSI 명령 + 데이터를 RDMA로 전송, iSCSI 대비 저지연
iSER iSCSI Extensions for RDMA 블록 스토리지 ib_iser / ib_isert 기존 iSCSI 프로토콜을 RDMA로 가속, iSCSI 호환
NVMe-oF/RDMA NVMe over Fabrics NVMe 스토리지 nvme-rdma / nvmet-rdma NVMe 큐 모델을 RDMA에 직접 매핑, 초저지연 스토리지
NFS/RDMA NFS over RDMA (RPCRDMA) 파일 시스템 xprtrdma / svcrdma RPC 데이터를 RDMA Write/Read로 전송

NVMe-oF/RDMA 설정 예제

### NVMe-oF/RDMA Target 설정 ###

# 커널 모듈 로드
modprobe nvmet
modprobe nvmet-rdma

# NVMe-oF 서브시스템 생성
mkdir -p /sys/kernel/config/nvmet/subsystems/nqn.2024-01.io.example:nvme-rdma
cd /sys/kernel/config/nvmet/subsystems/nqn.2024-01.io.example:nvme-rdma
echo 1 > attr_allow_any_host

# 네임스페이스에 NVMe 디바이스 연결
mkdir namespaces/1
echo /dev/nvme0n1 > namespaces/1/device_path
echo 1 > namespaces/1/enable

# RDMA 포트 생성 및 서브시스템 바인드
mkdir -p /sys/kernel/config/nvmet/ports/1
echo rdma > /sys/kernel/config/nvmet/ports/1/addr_trtype
echo 10.0.0.1 > /sys/kernel/config/nvmet/ports/1/addr_traddr
echo 4420 > /sys/kernel/config/nvmet/ports/1/addr_trsvcid
echo ipv4 > /sys/kernel/config/nvmet/ports/1/addr_adrfam
ln -s /sys/kernel/config/nvmet/subsystems/nqn.2024-01.io.example:nvme-rdma \
      /sys/kernel/config/nvmet/ports/1/subsystems/

### NVMe-oF/RDMA Initiator (클라이언트) 설정 ###

# 커널 모듈 로드
modprobe nvme-rdma

# Target 디스커버리
nvme discover -t rdma -a 10.0.0.1 -s 4420

# Target 연결
nvme connect -t rdma -n nqn.2024-01.io.example:nvme-rdma \
             -a 10.0.0.1 -s 4420

# 연결된 NVMe 디바이스 확인
nvme list
lsblk
NVMe-oF/RDMA 성능: NVMe-oF/RDMA는 NVMe의 멀티큐 모델을 RDMA Send/RDMA Write에 직접 매핑하여 원격 NVMe SSD에 로컬과 유사한 지연시간(~10μs 추가)으로 접근할 수 있습니다. iSCSI 대비 CPU 사용률이 크게 낮고, 4KB random read에서 수백만 IOPS를 달성할 수 있습니다. Block I/O 서브시스템 페이지의 blk-mq 섹션도 참고하세요.

관리 및 진단 도구

opensm (Subnet Manager)

opensm은 Linux에서 가장 많이 사용되는 오픈소스 Subnet Manager입니다. 서브넷 토폴로지를 탐색하고 LID를 할당하며, 라우팅 테이블을 계산하여 스위치에 배포합니다. 실제로는 SA 기능도 함께 제공하므로, Path Record 질의와 파티션 정책 배포까지 운영의 중심에 놓입니다.

# opensm 시작 (기본 설정)
opensm

# 포그라운드 + 디버그 레벨 지정
opensm -F -D 0x02

# 특정 포트 GUID로 SM 바인딩
opensm -g 0x0002c90300000001

# 라우팅 알고리즘 지정 (minhop, updn, ftree, dor 등)
opensm --routing_engine ftree
운영 감각: 포트가 LinkUp인데도 State: Init에 머무르면, 케이블 문제보다 먼저 SM 부재, SM 충돌, 잘못된 GUID 바인딩, IsSM capability bit 충돌을 의심하는 편이 빠릅니다.

진단 도구

# HCA 상태 확인
ibstat
## 출력 예시:
## CA 'mlx5_0'
##   CA type: MT4123
##   Number of ports: 1
##   Port 1:
##     State: Active
##     Physical state: LinkUp
##     Rate: 100 (EDR)
##     Base lid: 1
##     SM lid: 1

# 디바이스 상세 정보
ibv_devinfo

# 디바이스 속성 (최대 QP 수, MR 크기 등)
ibv_devinfo -v

# SM / SA 상태
sminfo
saquery -s

# 파티션 / 멀티캐스트 / 경로 조회
saquery -p
saquery -m

# 서브넷 노드 목록
ibnetdiscover

# 링크 상태와 포트 정보 요약
iblinkinfo

# 스위치 라우팅 및 경로 추적
ibroute <switch_lid>
# 특정 노드 경로 추적
ibtracert <src_lid> <dst_lid>

# 포트 카운터 확인
perfquery

# fabric 전반 오류 요약
ibqueryerrors

# 포트 에러 카운터 초기화
perfquery -x -r <lid> <port>

# fabric 감사: 토폴로지/라우팅/카운터/케이블 검증
ibdiagnet

# 핑 (GRH 없이 LID 기반)
ibping -S   # 서버 모드
ibping <lid>   # 클라이언트

ibdiagnet는 단순 카운터 조회를 넘어, 토폴로지 검증, 라우팅 검증, 케이블/BER 확인, 혼잡 제어 설정 점검까지 수행하는 fabric audit 도구입니다. 대규모 클러스터에서는 ibnetdiscover보다 먼저 실행되는 경우도 많습니다.

성능 도구

# RDMA Write 대역폭 측정
ib_write_bw -d mlx5_0      # 서버
ib_write_bw -d mlx5_0 <server_ip>  # 클라이언트

# RDMA Write 지연시간 측정
ib_write_lat -d mlx5_0      # 서버
ib_write_lat -d mlx5_0 <server_ip>  # 클라이언트

# Send/Recv 대역폭/지연
ib_send_bw, ib_send_lat

# RDMA Read 대역폭/지연
ib_read_bw, ib_read_lat

# Atomic 연산 지연
ib_atomic_lat -d mlx5_0 <server_ip>

rdma (iproute2 rdma tool)

# RDMA 디바이스 목록
rdma dev

# RDMA 링크 상태
rdma link

# RDMA 통계 (상세)
rdma statistic show

# RDMA 리소스 (QP, CQ, MR 등) 목록
rdma resource show

# 특정 디바이스의 QP 목록
rdma resource show qp -d mlx5_0

# 포트별 GID / 링크 계층 / netdev 매핑 확인
rdma link show mlx5_0/1

# netns에서 RDMA 디바이스 사용 설정
rdma system set netns shared

성능 최적화

Adaptive Routing / SR-IOV

메모리 핀닝/등록 최적화

Completion Channel vs Polling

QP / CQ 튜닝

GPUDirect RDMA

NVIDIA GPUDirect RDMA는 GPU 메모리를 RDMA MR로 직접 등록하여, CPU 메모리를 거치지 않고 GPU ↔ HCA 간 직접 P2P DMA 전송을 수행합니다. AI/ML 분산 학습에서 GPU 간 gradient 교환 성능을 극적으로 향상시킵니다.

DMA 심화 페이지의 P2P DMA / GPUDirect 섹션도 참고하세요.

메모리 핀닝 주의사항: RDMA MR 등록은 물리 페이지를 핀하여 스왑 아웃을 방지합니다. 대량의 MR을 등록하면 시스템 가용 메모리가 급격히 줄어들어 OOM이 발생할 수 있습니다. ulimit -l로 프로세스별 메모리 잠금 제한을 확인하고, /etc/security/limits.conf에서 RDMA 사용자의 memlock 값을 적절히 설정해야 합니다. 컨테이너 환경에서는 cgroups의 memory.max도 함께 고려해야 합니다.

격리와 멀티테넌시

InfiniBand는 본질적으로 강한 성능 지향 기술이지만, 클라우드·공유 HPC·AI 플랫폼에서는 누가 어느 HCA 자원을 얼마나 쓰는지, 어느 파티션까지 접근 가능한지를 함께 설계해야 합니다. 단순히 디바이스 파일 권한만 나눠 주는 것으로는 충분하지 않습니다.

패브릭 격리: P_Key, SL, SR-IOV

RDMA cgroup controller

현재 커널 문서는 RDMA controller가 프로세스 집합별로 RDMA/IB 자원 사용량을 제한한다고 설명합니다. 인터페이스는 rdma.max, rdma.current 파일을 통해 노출되며, 장치별로 hca_handle, hca_object 한도를 설정합니다.

제어 항목의미실무 해석
hca_handle RDMA 장치 핸들 수 제한 프로세스군이 열 수 있는 HCA 컨텍스트 수를 제한합니다.
hca_object RDMA 객체 수 제한 QP, CQ, MR, AH 등 하드웨어/커널 객체 총량을 묶어서 제어합니다.
# cgroup v2 예시: mlx5_0의 RDMA 자원 제한
mkdir -p /sys/fs/cgroup/tenant-a
echo '+rdma' > /sys/fs/cgroup/cgroup.subtree_control
echo 'mlx5_0 hca_handle=4 hca_object=2000' > /sys/fs/cgroup/tenant-a/rdma.max

# 현재 사용량 확인
cat /sys/fs/cgroup/tenant-a/rdma.current
cat /sys/fs/cgroup/tenant-a/rdma.max
컨테이너 함정: 컨테이너에 /dev/infiniband/uverbs0만 넘겨도, memlock, cgroup RDMA 제한, IOMMU 정책, VF/PF 매핑, GPU dma-buf 권한이 맞지 않으면 성능과 안정성이 바로 깨집니다. RDMA 자원 격리는 반드시 디바이스 파일 + cgroup + 패브릭 파티션을 같이 봐야 합니다.

네임스페이스와 capability 위임

트러블슈팅 및 주의사항

가장 먼저 확인할 것: 이 연결이 정말 네이티브 InfiniBand인지, 아니면 Ethernet 포트의 RoCE인지 구분하세요. 같은 Verbs API를 써도 문제를 보는 순서가 완전히 다릅니다.
  • InfiniBand: SM/SA, LID, P_Key, SL/VL, credit-based flow control, Path Record를 먼저 확인
  • RoCE: PFC, ECN/DCQCN, VLAN/DSCP, lossless 큐, GID/IP 라우팅을 먼저 확인
ibv_devinfordma link에서 link_layer가 무엇인지부터 보세요.

일반적인 트러블슈팅 순서:

  1. ibstat, ibv_devinfo, rdma link으로 포트 상태와 link_layer를 확인합니다.
  2. sminfo, saquery -s, ibnetdiscover로 SM/SA와 fabric discovery가 정상인지 확인합니다.
  3. saquery -p, ibroute, ibtracert로 P_Key와 실제 경로를 점검합니다.
  4. perfquery, ibqueryerrors, ibdiagnet로 포트 카운터와 fabric 오류를 수집합니다.
  5. rdma resource show, dmesg | grep -i rdma로 QP/CQ/MR과 커널 로그를 확인합니다.
  6. ib_write_bw, ib_send_bw, 필요하면 GPU 옵션이 붙은 perftest로 재현 가능한 성능 기준선을 만듭니다.
증상먼저 볼 것흔한 원인
포트가 INIT에서 올라오지 않음 ibstat, sminfo, opensm 로그 SM 부재, 잘못된 GUID 바인딩, 케이블/모듈 문제, 포트 speed negotiation 실패
QP가 RTR/RTS로 전이되지 않음 QPN, LID/GID, PSN, MTU, P_Key out-of-band 교환 값 오류, 경로 해석 실패, 파티션 불일치
IB_WC_REM_ACCESS_ERR, REM_INV_REQ_ERR MR access flags, rkey, remote_addr 잘못된 rkey 전달, 원격 버퍼 길이 초과, MW/MR 무효화 이후 접근
RNR retry exceeded RQ depth, SRQ, 수신 버퍼 게시 타이밍 수신 측이 Receive WR을 충분히 post하지 않음, CQ poller 지연
대역폭이 선형으로 안 나옴 NUMA 배치, CQE 수, signaled 비율, MTU, multi-rail HCA와 메모리의 NUMA 불일치, 너무 잦은 completion, 작은 큐 깊이, 혼잡/경로 편중
IPoIB child interface에 트래픽이 없음 /sys/class/net/*/pkey, SA 파티션 정보 파티션 membership 누락, 잘못된 P_Key index, connected/datagram mode 혼선

자주 보는 Work Completion 상태

실패한 WR은 결국 CQ의 ibv_wc.status로 드러납니다. rdma-core의 enum ibv_wc_status를 기준으로, 현장에서 가장 자주 보는 상태는 다음 정도입니다.

ibv_wc_status의미우선 확인할 것
IBV_WC_SUCCESS 정상 완료 지연/처리량 문제면 큐 깊이, polling, NUMA, MTU 쪽으로 이동
IBV_WC_LOC_LEN_ERR 로컬 SGE 길이/버퍼 범위 오류 SGE length, MR 길이, receive buffer 크기
IBV_WC_LOC_PROT_ERR 로컬 보호 오류 lkey, access flag, 잘못된 MR 재사용 여부
IBV_WC_WR_FLUSH_ERR QP가 error 상태로 가며 미완료 WR이 flush됨 그 전에 발생한 최초 에러, QP 이벤트 핸들러 로그
IBV_WC_REM_ACCESS_ERR 원격 접근 권한 오류 원격 MR access flag, rkey, remote_addr 범위
IBV_WC_RETRY_EXC_ERR 재시도 횟수 초과 상대 QP 상태, 경로 단절, PSN/MTU 불일치, 혼잡/링크 오류
IBV_WC_RNR_RETRY_EXC_ERR RNR 재시도 초과 수신 측 Receive WR 게시 누락, SRQ 고갈, poller 지연
디버깅 요령: IBV_WC_WR_FLUSH_ERR는 대개 2차 증상입니다. flush가 보이면 그 직전에 발생한 RETRY_EXC, REM_ACCESS, 링크 down 이벤트를 먼저 찾는 편이 훨씬 빠릅니다.

커널 모듈 관련 이슈는 네트워크 스택 페이지를, PCIe/SR-IOV 관련 문제는 PCI/PCIe 서브시스템 페이지를 참고하세요.

프로덕션 배포 체크리스트

InfiniBand는 단일 설정값 하나로 안정화되는 기술이 아닙니다. 하드웨어, 패브릭, 메모리, 애플리케이션이 모두 같은 방향으로 맞아야 하므로 배포 전 체크 순서를 명확히 고정하는 것이 중요합니다.

  1. PCIe / 펌웨어 정합성
    HCA가 기대한 링크 폭/속도로 올라왔는지, 펌웨어와 드라이버 조합이 지원 매트릭스 안에 있는지 확인합니다.
  2. 패브릭 활성화
    ibstatActive, sminfo가 정상, LID와 P_Key가 의도한 값으로 배포됐는지 확인합니다.
  3. 단일 흐름 기준선
    ib_write_bw, ib_write_lat, ib_send_bw로 단일 QP/단일 코어 기준선을 먼저 만듭니다.
  4. NUMA / IRQ / poller 배치
    HCA와 같은 NUMA 노드에 메모리와 스레드를 묶고 CQ completion vector, IRQ affinity를 정렬합니다.
  5. 애플리케이션 모델 선택
    제어 메시지는 Send/Recv, 대용량 데이터는 RDMA Write/Read, 대규모 fan-in은 SRQ/XRC/DC로 분리 설계합니다.
  6. 상위 프로토콜 검증
    IPoIB, NFS/RDMA, NVMe-oF/RDMA, GPU 메모리 경로를 각각 별도 기준선으로 확인합니다. 기본 RDMA가 빠르다고 ULP도 자동으로 빠른 것은 아닙니다.
  7. 지속 관측 체계
    perfquery, ibqueryerrors, ibdiagnet, rdma statistic show를 정기 수집에 포함합니다.
  8. 장애 시 격리 순서
    애플리케이션 → Verbs → QP/CQ/MR → 포트 상태 → SM/SA → 스위치 경로 → PCIe/IOMMU 순으로 아래로 내려가며 원인을 좁힙니다.
운영 원칙: 처음부터 multi-rail, SR-IOV, GPU direct, 컨테이너 RDMA, 스토리지 ULP를 한 번에 붙이지 마세요. 반드시 네이티브 RC QP 단일 노드 쌍 기준선을 먼저 확보한 뒤 기능을 하나씩 쌓아야, 성능 회귀와 장애 원인을 추적할 수 있습니다.

2노드 Bring-up 시나리오

새 장비를 랙에 넣었을 때 가장 안전한 방식은, 복잡한 스토리지나 MPI 스택을 바로 올리지 말고 두 노드만 연결한 최소 구성에서 패브릭, Verbs, IPoIB, 성능 기준선을 순서대로 확인하는 것입니다.

  1. 드라이버와 관리 도구 로드
    mlx5_ib, ib_umad, 필요하면 ib_ipoib가 올라왔는지 확인합니다.
  2. SM 확보
    스위치 내장 SM이 없다면 한 노드에서 opensm을 띄우고 다른 노드 포트가 INIT → ACTIVE로 전이되는지 봅니다.
  3. 기본 관측
    ibstat, ibv_devinfo, sminfo, saquery -s로 포트 상태와 SM/SA를 점검합니다.
  4. Verbs 기준선
    ib_write_bw, ib_write_lat, ib_send_bw만으로 HCA-to-HCA 경로를 먼저 검증합니다.
  5. IP 계층 확인
    필요하면 IPoIB를 올리고 ip addr, ping, 애플리케이션 포트 바인딩을 점검합니다.
  6. 애플리케이션 계층 확장
    그 다음에야 UCX/Open MPI, NVMe-oF, NFS/RDMA, GPU direct를 하나씩 붙입니다.
# 노드 A: SM이 필요하면 시작
modprobe mlx5_ib ib_umad
opensm -F

# 양 노드: 포트 상태 확인
ibstat
ibv_devinfo
sminfo

# 양 노드: Verbs 기준선 측정
# 노드 A (server)
ib_write_bw -d mlx5_0

# 노드 B (client)
ib_write_bw -d mlx5_0 <server_name_or_ip>

# 필요 시 IPoIB 확인
modprobe ib_ipoib
ip link set ib0 up
ip addr add 10.10.10.1/24 dev ib0
기준선 해석: 이 단계에서 원하는 대역폭이 나오지 않으면, 원인을 상위 스택에서 찾지 말고 포트 속도, Path MTU, NUMA 배치, CQ signaled 비율, PCIe 링크 폭, 케이블 품질 쪽으로 먼저 내려가야 합니다.

이 주제와 관련된 다른 문서를 더 깊이 이해하고 싶다면 다음을 참고하세요.