O pacote linux-rdma serve como a implementação de referência para o subsistema InfiniBand no kernel Linux (drivers/infiniband). Ele fornece bibliotecas fundamentais no espaço do usuário, como a libibverbs, que expõe as APIs de Verbs necessárias para operações RDMA (Remote Direct Memory Access) e comunicação de alto desempenho.
Componentes Fundamentais da Arquitetura RDMA
Queue Pair (QP)
O Queue Pair é o endpoint de comunicação no RDMA, análogo aos sockets em redes TCP/IP tradicionais. Cada QP é composto por uma fila de envio (Send Queue) e uma fila de recebimento (Receive Queue). Para que dois nós se comuniquem, seus QPs devem ser configurados e conectados, geralmente com o auxílio de um Gerenciador de Comunicação (CM) para a troca inicial de metadados.
/**
* Protótipo para criação de um Queue Pair
*/
struct ibv_qp *create_rdma_queue_pair(struct ibv_pd *protection_domain,
struct ibv_qp_init_attr *init_attributes);
Completion Queue (CQ)
A Completino Queue funciona como um mecanismo de notificação. Quando uma solicitação de trabalho (Work Request - WR) é finalizada pelo hardware, um elemento de conclusão (CQE) é inserido na CQ. Isso permite que a aplicação verifique o status da operação (sucesso ou erro), o tamanho dos dados transferidos e a origem.
/**
* Exemplo de criação de uma Fila de Conclusão (CQ)
*/
struct ibv_cq *setup_completion_queue(struct ibv_context *verbs_ctx,
int minimum_entries,
void *user_ctx,
struct ibv_comp_channel *evt_channel,
int comp_vector);
Registro de Memória (Memory Registration - MR)
Diferente de sockets padrão, o hardware RDMA precisa acessar a memória RAM diretamente via DMA sem intervenção da CPU. O registro de memória permite mapear áreas de memória virtual ou física para o adaptador de rede.
struct memory_region_info {
struct ibv_context *ctx;
struct ibv_pd *pd_ptr;
void *buffer_addr;
size_t buffer_len;
uint32_t local_key; // lkey
uint32_t remote_key; // rkey
};
- lkey (Local Key): Utilizada pelo adaptador local para acessar a memória durante operações de recebimento ou envio.
- rkey (Remote Key): Enviada ao nó remoto para permitir que ele acesse a memória local via RDMA Read ou Write.
Protection Domain (PD)
O Domínio de Proteção atua como um container lógico de segurança. Ele garante que recursos como QPs e MRs só possam interagir se pertencerem ao mesmo domínio, prevenindo acessos não autorizados entre diferentes processos ou contextos de rede.
/* Alocação de um novo domínio de proteção */
struct ibv_pd *domain = ibv_alloc_pd(verbs_ctx);
Fluxo de Implementação com libibverbs
Para construir uma aplicação RDMA funcional utilizando a API de Verbs, o desenvolvedor deve seguir este fluxo lógico:
1. Localização do Hardware
O primeiro passo é listar os dispositivos InfiniBand/RoCE disponíveis no host através da função ibv_get_device_list(). Cada dispositivo possui um GUID exclusivo e um nome de sistema (ex: mlx5_0).
2. Abertura do Contexto
Após selecionar o dispositivo, abre-se um contexto de execução (ibv_open_device), que servirá de base para todas as operações subsequentes.
3. Configuração de Recursos de Memória e Proteção
Aloca-se o Protection Domain (PD) e, em seguida, registra-se o buffer de memória (MR) que será usado para o tráfego de dados. É neste momento que as permissões (leitura local, escrita remota, etc.) são definidas.
4. Preparação das Filas
Cria-se a Completion Queue (CQ) para monitorar o status das tarefas e o Queue Pair (QP) para gerenciar o tráfego de entrada e saída.
5. Transição de Estados do QP
Um QP recém-criado não pode transmitir dados imediatamente. Ele deve passar por uma máquina de estados controlada por ibv_modify_qp:
- RESET: Estado inicial.
- INIT: Informações básicas configuradas; pronto para receber posts na fila de recebimento.
- RTR (Ready to Receive): Pronto para receber pacotes do nó remoto.
- RTS (Ready to Send): Pronto para enviar dados; parâmetros de timeout e retransmissão ativos.
6. Execução e Sincronização
A aplicação posta Work Requests (WR) e utiliza ibv_poll_cq para verificar quando o hardware concluiu o processamento.
7. Finalização
A destruição dos objetos deve ocorrer na ordem inversa à criação para evitar vazamentos de recursos ou referências órfãs (QP > CQ > MR > PD > Contexto).
Exemplo de Verificação de Conectividade
Ferramentas como o ibv_rc_pingpong são úteis para validar se a pilha RDMA e a configuração do Driver (como o Soft-RoCE rxe) estão operacionais.
Comando no Servidor:
# ibv_rc_pingpong -d rxe0 -g 0 -s 1024 -n 5
Comando no Cliente:
# ibv_rc_pingpong -d rxe0 -g 0 192.168.1.10 -s 1024 -n 5
Este teste estabelcee uma conexão Reliable Connected (RC) e mede a latência e o throughput entre os nós, permitindo analisar o comportamento dos pacotes através de ferramentas de captura de rede, onde se observa o fluxo de pacotes RC Send Only e os respectivos ACKs de hardware.