]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | /* | |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2016 XSKY <haomai@xsky.com> | |
7 | * | |
8 | * Author: Haomai Wang <haomaiwang@gmail.com> | |
9 | * | |
10 | * This is free software; you can redistribute it and/or | |
11 | * modify it under the terms of the GNU Lesser General Public | |
12 | * License version 2.1, as published by the Free Software | |
13 | * Foundation. See file COPYING. | |
14 | * | |
15 | */ | |
16 | ||
17 | #include "RDMAStack.h" | |
18 | #include "Device.h" | |
19 | #include "RDMAConnTCP.h" | |
20 | ||
21 | #define dout_subsys ceph_subsys_ms | |
22 | #undef dout_prefix | |
23 | #define dout_prefix *_dout << " RDMAConnTCP " | |
24 | ||
25 | static const uint32_t TCP_MSG_LEN = sizeof("0000:00000000:00000000:00000000:00000000000000000000000000000000"); | |
26 | ||
27 | // 1 means no valid buffer read, 0 means got enough buffer | |
28 | // else return < 0 means error | |
29 | int RDMAConnTCP::recv_msg(CephContext *cct, int sd, IBSYNMsg& im) | |
30 | { | |
31 | char msg[TCP_MSG_LEN]; | |
32 | char gid[33]; | |
33 | ssize_t r = ::read(sd, &msg, sizeof(msg)); | |
34 | // Drop incoming qpt | |
35 | if (cct->_conf->ms_inject_socket_failures && sd >= 0) { | |
36 | if (rand() % cct->_conf->ms_inject_socket_failures == 0) { | |
37 | ldout(cct, 0) << __func__ << " injecting socket failure" << dendl; | |
38 | return -EINVAL; | |
39 | } | |
40 | } | |
41 | if (r < 0) { | |
42 | r = -errno; | |
43 | lderr(cct) << __func__ << " got error " << r << ": " | |
44 | << cpp_strerror(r) << dendl; | |
45 | } else if (r == 0) { // valid disconnect message of length 0 | |
46 | ldout(cct, 10) << __func__ << " got disconnect message " << dendl; | |
47 | } else if ((size_t)r != sizeof(msg)) { // invalid message | |
48 | ldout(cct, 1) << __func__ << " got bad length (" << r << ") " << dendl; | |
49 | r = -EINVAL; | |
50 | } else { // valid message | |
51 | sscanf(msg, "%hu:%x:%x:%x:%s", &(im.lid), &(im.qpn), &(im.psn), &(im.peer_qpn),gid); | |
52 | wire_gid_to_gid(gid, &(im.gid)); | |
53 | ldout(cct, 5) << __func__ << " recevd: " << im.lid << ", " << im.qpn << ", " << im.psn << ", " << im.peer_qpn << ", " << gid << dendl; | |
54 | } | |
55 | return r; | |
56 | } | |
57 | ||
58 | int RDMAConnTCP::send_msg(CephContext *cct, int sd, IBSYNMsg& im) | |
59 | { | |
60 | int retry = 0; | |
61 | ssize_t r; | |
62 | ||
63 | char msg[TCP_MSG_LEN]; | |
64 | char gid[33]; | |
65 | retry: | |
66 | gid_to_wire_gid(&(im.gid), gid); | |
67 | sprintf(msg, "%04x:%08x:%08x:%08x:%s", im.lid, im.qpn, im.psn, im.peer_qpn, gid); | |
68 | ldout(cct, 10) << __func__ << " sending: " << im.lid << ", " << im.qpn << ", " << im.psn | |
69 | << ", " << im.peer_qpn << ", " << gid << dendl; | |
70 | r = ::write(sd, msg, sizeof(msg)); | |
71 | // Drop incoming qpt | |
72 | if (cct->_conf->ms_inject_socket_failures && sd >= 0) { | |
73 | if (rand() % cct->_conf->ms_inject_socket_failures == 0) { | |
74 | ldout(cct, 0) << __func__ << " injecting socket failure" << dendl; | |
75 | return -EINVAL; | |
76 | } | |
77 | } | |
78 | ||
79 | if ((size_t)r != sizeof(msg)) { | |
80 | // FIXME need to handle EAGAIN instead of retry | |
81 | if (r < 0 && (errno == EINTR || errno == EAGAIN) && retry < 3) { | |
82 | retry++; | |
83 | goto retry; | |
84 | } | |
85 | if (r < 0) | |
86 | lderr(cct) << __func__ << " send returned error " << errno << ": " | |
87 | << cpp_strerror(errno) << dendl; | |
88 | else | |
89 | lderr(cct) << __func__ << " send got bad length (" << r << ") " << cpp_strerror(errno) << dendl; | |
90 | return -errno; | |
91 | } | |
92 | return 0; | |
93 | } | |
94 | ||
95 | void RDMAConnTCP::wire_gid_to_gid(const char *wgid, union ibv_gid *gid) | |
96 | { | |
97 | char tmp[9]; | |
98 | uint32_t v32; | |
99 | int i; | |
100 | ||
101 | for (tmp[8] = 0, i = 0; i < 4; ++i) { | |
102 | memcpy(tmp, wgid + i * 8, 8); | |
103 | sscanf(tmp, "%x", &v32); | |
104 | *(uint32_t *)(&gid->raw[i * 4]) = ntohl(v32); | |
105 | } | |
106 | } | |
107 | ||
108 | void RDMAConnTCP::gid_to_wire_gid(const union ibv_gid *gid, char wgid[]) | |
109 | { | |
110 | for (int i = 0; i < 4; ++i) | |
111 | sprintf(&wgid[i * 8], "%08x", htonl(*(uint32_t *)(gid->raw + i * 4))); | |
112 | } | |
113 | ||
114 | ostream &RDMAConnTCP::print(ostream &out) const | |
115 | { | |
116 | return out << "TCP {tcp_fd: " << tcp_fd << "}"; | |
117 | } |