Commit 2f87f784 authored by Titouan Soulard's avatar Titouan Soulard

Initial handshake: allow exchanging RDMA parameters

Before starting a RDMA communication between two nodes, local
informations must be exchanged. The proposed example uses UDP
for that purpose.
parents
HEADERS = udp.h
CFLAGS = -Wall -O3
udp_send: udp_send.c
gcc $(CFLAGS) -o $@ $?
udp_recv: udp_recv.c
gcc $(CFLAGS) -o $@ $?
all: udp_send udp_recv
# RDMA minimal working example
Minimal working example for RDMA with multiple slaves: one machine serves a portion of memory and the others can read it.
struct udp_query_parameters {
uint8_t requested;
};
#define REQ_LID 0x1
#define REQ_QPN 0x2
#define REQ_ADDR 0x4
#define REQ_SIZE 0x8
#define REQ_KEY 0x10
struct udp_rdma_parameters {
uint16_t lid;
uint32_t qpn;
void *addr;
size_t size;
uint32_t key;
};
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "udp_rdma.h"
int main(void) {
struct addrinfo server_hints;
struct addrinfo *server_infos;
struct sockaddr client_addr;
struct udp_query_parameters *rdma_req_params;
struct udp_rdma_parameters rdma_params;
socklen_t client_addr_size = sizeof(struct sockaddr_storage);
const size_t buffer_length = sizeof(struct udp_query_parameters);
int result, server_socket;
char receive_buffer[buffer_length];
// Set up bind address
memset(&server_hints, 0, sizeof(struct addrinfo));
server_hints.ai_family = AF_INET;
server_hints.ai_socktype = SOCK_DGRAM;
server_hints.ai_flags = AI_PASSIVE;
result = getaddrinfo(NULL, "7362", &server_hints, &server_infos);
if(result != 0) {
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(result));
return 1;
}
// Create a socket an bind
// XXX: assumes first address in linked list is 0.0.0.0
server_socket = socket(server_infos->ai_family, server_infos->ai_socktype, server_infos->ai_protocol);
if(server_socket == -1) {
perror("socket error");
return 1;
}
result = bind(server_socket, server_infos->ai_addr, server_infos->ai_addrlen);
if(result == -1) {
perror("bind error");
return 1;
}
// Address info can be freed as soon as the socket in bound
freeaddrinfo(server_infos);
result = recvfrom(server_socket, receive_buffer, buffer_length, 0, &client_addr, &client_addr_size);
if(result == -1) {
perror("recvfrom error");
return 1;
}
rdma_req_params = (struct udp_query_parameters *) receive_buffer;
printf("Client requested: %d", rdma_req_params->requested);
// XXX: stop using dummy data and take account of capabilities
rdma_params.lid = 0x1234;
rdma_params.qpn = 0x12345678;
rdma_params.addr = (void *) receive_buffer;
rdma_params.size = buffer_length;
rdma_params.key = 0x87654321;
result = sendto(server_socket, (void *) &rdma_params, sizeof(struct udp_rdma_parameters), MSG_CONFIRM, &client_addr, client_addr_size);
if(result == -1) {
perror("sendto error");
return 1;
}
close(server_socket);
return 0;
}
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "udp_rdma.h"
int main(void) {
struct addrinfo server_hints;
struct addrinfo *server_infos;
struct udp_query_parameters rdma_req_params;
struct udp_rdma_parameters *rdma_params;
const size_t buffer_length = sizeof(struct udp_rdma_parameters);
int result, server_socket;
char receive_buffer[buffer_length];
// Set up remote address
memset(&server_hints, 0, sizeof(struct addrinfo));
server_hints.ai_family = AF_INET;
server_hints.ai_socktype = SOCK_DGRAM;
result = getaddrinfo("192.168.16.10", "7362", &server_hints, &server_infos);
if(result != 0) {
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(result));
return 1;
}
// Create a socket
// XXX: assumes first address in linked list is 0.0.0.0
server_socket = socket(server_infos->ai_family, server_infos->ai_socktype, server_infos->ai_protocol);
if(server_socket == -1) {
perror("socket error");
return 1;
}
// Create and send a query with full capabilities
rdma_req_params.requested = REQ_LID | REQ_QPN | REQ_ADDR | REQ_SIZE | REQ_KEY;
result = sendto(server_socket, (void *) &rdma_req_params, sizeof(struct udp_query_parameters), 0, server_infos->ai_addr, server_infos->ai_addrlen);
if(result == -1) {
perror("sendto error");
return 1;
}
// Wait for informations from the server
result = recvfrom(server_socket, receive_buffer, buffer_length, 0, server_infos->ai_addr, &server_infos->ai_addrlen);
if(result == -1) {
perror("recvfrom error");
return 1;
}
rdma_params = (struct udp_rdma_parameters *) receive_buffer;
printf("Client LID: %d", rdma_params->lid);
close(server_socket);
freeaddrinfo(server_infos);
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment