2 * Copyright (c) 2011 Intel Corporation. All rights reserved.
4 * This software is available to you under the OpenIB.org BSD license
7 * Redistribution and use in source and binary forms, with or
8 * without modification, are permitted provided that the following
11 * - Redistributions of source code must retain the above
12 * copyright notice, this list of conditions and the following
15 * - Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials
18 * provided with the distribution.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV
23 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
24 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
25 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36 #include <arpa/inet.h>
38 #include <sys/types.h>
39 #include <sys/socket.h>
46 #include <rdma/rsocket.h>
48 union rsocket_address {
50 struct sockaddr_in sin;
51 struct sockaddr_in6 sin6;
52 struct sockaddr_storage storage;
55 static const char *port = "7427";
56 static char *dst_addr;
57 static char *dst_file;
58 static char *src_file;
59 static struct timeval start, end;
60 //static void buf[1024 * 1024];
61 static uint64_t bytes;
63 static void *file_addr;
73 /* TODO: handle byte swapping */
92 static void show_perf(void)
96 usec = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec);
98 printf("%lld bytes in %.2f seconds = %.2f Gb/sec\n",
99 (long long) bytes, usec / 1000000., (bytes * 8) / (1000. * usec));
102 static char *_ntop(union rsocket_address *rsa)
104 static char addr[32];
106 switch (rsa->sa.sa_family) {
108 inet_ntop(AF_INET, &rsa->sin.sin_addr, addr, sizeof addr);
111 inet_ntop(AF_INET6, &rsa->sin6.sin6_addr, addr, sizeof addr);
121 static size_t _recv(int rs, char *msg, size_t len)
125 for (offset = 0; offset < len; offset += ret) {
126 ret = rrecv(rs, msg + offset, len - offset, 0);
134 static int msg_recv_hdr(int rs, struct msg_hdr *hdr)
138 ret = _recv(rs, (char *) hdr, sizeof *hdr);
139 if (ret != sizeof *hdr)
142 if (hdr->version || hdr->len < sizeof *hdr) {
143 printf("invalid version %d or length %d\n",
144 hdr->version, hdr->len);
151 static int msg_get_resp(int rs, struct msg_hdr *msg, uint8_t cmd)
155 ret = msg_recv_hdr(rs, msg);
156 if (ret != sizeof *msg)
159 if ((msg->len != sizeof *msg) || (msg->command != (cmd | CMD_RESP))) {
160 printf("invalid length %d or bad command response %x:%x\n",
161 msg->len, msg->command, cmd | CMD_RESP);
168 static void msg_send_resp(int rs, struct msg_hdr *msg, uint32_t status)
173 resp.command = msg->command | CMD_RESP;
174 resp.len = sizeof resp;
177 rsend(rs, (char *) &resp, sizeof resp, 0);
180 static int server_listen(void)
182 struct addrinfo hints, *res;
185 memset(&hints, 0, sizeof hints);
186 hints.ai_flags = RAI_PASSIVE;
187 ret = getaddrinfo(NULL, port, &hints, &res);
189 printf("getaddrinfo failed: %s\n", gai_strerror(ret));
193 rs = rsocket(res->ai_family, res->ai_socktype, res->ai_protocol);
195 perror("rsocket failed\n");
201 ret = rsetsockopt(rs, SOL_SOCKET, SO_REUSEADDR, &ret, sizeof ret);
203 perror("rsetsockopt failed");
207 ret = rbind(rs, res->ai_addr, res->ai_addrlen);
209 perror("rbind failed");
213 ret = rlisten(rs, 1);
215 perror("rlisten failed");
229 static int server_open(int rs, struct msg_hdr *msg)
236 if (file_addr || fd > 0) {
237 printf("cannot open another file\n");
242 len = msg->len - sizeof *msg;
245 printf("cannot allocate path name\n");
250 ret = _recv(rs, path, len);
252 printf("error receiving path\n");
256 printf("%s, ", path);
258 fd = open(path, O_RDWR | O_CREAT | O_TRUNC, msg->data);
260 printf("unable to open destination file\n");
269 msg_send_resp(rs, msg, ret);
273 static void server_close(int rs, struct msg_hdr *msg)
275 printf("closing...");
277 msg_send_resp(rs, msg, 0);
280 munmap(file_addr, bytes);
291 static int server_write(int rs, struct msg_hdr *msg)
296 printf("transferring");
299 printf("...file not opened\n");
304 if (msg->len != sizeof(struct msg_write)) {
305 printf("...invalid message length %d\n", msg->len);
310 ret = _recv(rs, (char *) &bytes, sizeof bytes);
311 if (ret != sizeof bytes)
314 ret = ftruncate(fd, bytes);
318 file_addr = mmap(NULL, bytes, PROT_WRITE, MAP_SHARED, fd, 0);
319 if (file_addr == (void *) -1) {
320 printf("...error mapping file\n");
325 printf("...%lld bytes...", (long long) bytes);
327 len = _recv(rs, file_addr, bytes);
329 printf("...error receiving data\n");
333 msg_send_resp(rs, msg, ret);
337 static void server_process(int rs)
343 ret = msg_recv_hdr(rs, &msg);
344 if (ret != sizeof msg)
347 switch (msg.command) {
349 ret = server_open(rs, &msg);
352 server_close(rs, &msg);
356 ret = server_write(rs, &msg);
359 msg_send_resp(rs, &msg, EINVAL);
367 static int server_run(void)
370 union rsocket_address rsa;
373 lrs = server_listen();
379 printf("waiting for connection...");
381 rs = raccept(lrs, &rsa.sa, &len);
383 printf("client: %s\n", _ntop(&rsa));
386 rshutdown(rs, SHUT_RDWR);
392 static int client_connect(void)
394 struct addrinfo *res;
397 ret = getaddrinfo(dst_addr, port, NULL, &res);
399 printf("getaddrinfo failed: %s\n", gai_strerror(ret));
403 rs = rsocket(res->ai_family, res->ai_socktype, res->ai_protocol);
405 perror("rsocket failed\n");
409 ret = rconnect(rs, res->ai_addr, res->ai_addrlen);
411 perror("rconnect failed\n");
421 static int client_open(int rs)
423 struct msg_open *msg;
428 printf("opening...");
430 fd = open(src_file, O_RDONLY);
434 ret = fstat(fd, &stats);
438 bytes = (uint64_t) stats.st_size;
439 file_addr = mmap(NULL, bytes, PROT_READ, MAP_SHARED, fd, 0);
440 if (file_addr == (void *) -1) {
445 len = (((uint32_t) strlen(dst_file)) + 8) & 0xFFFFFFF8;
446 msg = calloc(1, sizeof(*msg) + len);
452 msg->hdr.command = CMD_OPEN;
453 msg->hdr.len = sizeof(*msg) + len;
454 msg->hdr.data = (uint32_t) stats.st_mode;
455 strcpy(msg->path, dst_file);
456 ret = rsend(rs, msg, msg->hdr.len, 0);
457 if (ret != msg->hdr.len)
460 ret = msg_get_resp(rs, &msg->hdr, CMD_OPEN);
469 munmap(file_addr, bytes);
475 static int client_start_write(int rs)
477 struct msg_write msg;
480 printf("transferring");
482 memset(&msg, 0, sizeof msg);
483 msg.hdr.command = CMD_WRITE;
484 msg.hdr.len = sizeof(msg);
487 ret = rsend(rs, &msg, sizeof msg, 0);
488 if (ret != msg.hdr.len)
494 static int client_close(int rs)
499 printf("closing...");
501 memset(&msg, 0, sizeof msg);
502 msg.command = CMD_CLOSE;
503 msg.len = sizeof msg;
504 ret = rsend(rs, (char *) &msg, msg.len, 0);
508 ret = msg_get_resp(rs, &msg, CMD_CLOSE);
514 munmap(file_addr, bytes);
519 static int client_run(void)
525 rs = client_connect();
529 ret = client_open(rs);
533 ret = client_start_write(rs);
539 gettimeofday(&start, NULL);
540 len = rsend(rs, file_addr, bytes, 0);
542 ret = msg_get_resp(rs, &ack, CMD_WRITE);
546 gettimeofday(&end, NULL);
551 rshutdown(rs, SHUT_RDWR);
558 static void show_usage(char *program)
560 printf("usage 1: %s [options]\n", program);
561 printf("\t starts the server application\n");
562 printf("\t[-p port_number]\n");
563 printf("usage 2: %s source server[:destination] [options]\n", program);
564 printf("\t source - file name and path\n");
565 printf("\t server - name or address\n");
566 printf("\t destination - file name and path\n");
567 printf("\t[-p port_number]\n");
571 static void server_opts(int argc, char **argv)
575 while ((op = getopt(argc, argv, "p:")) != -1) {
586 static void client_opts(int argc, char **argv)
595 dst_file = strchr(dst_addr, ':');
603 while ((op = getopt(argc, argv, "p:")) != -1) {
615 int main(int argc, char **argv)
619 if (argc == 1 || argv[1][0] == '-') {
620 server_opts(argc, argv);
623 client_opts(argc, argv);