]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/include/spdk_internal/sock.h
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / spdk / include / spdk_internal / sock.h
1 /*-
2 * BSD LICENSE
3 *
4 * Copyright (c) Intel Corporation. All rights reserved.
5 * Copyright (c) 2020 Mellanox Technologies LTD. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /** \file
35 * TCP network implementation abstraction layer
36 */
37
38 #ifndef SPDK_INTERNAL_SOCK_H
39 #define SPDK_INTERNAL_SOCK_H
40
41 #include "spdk/stdinc.h"
42 #include "spdk/sock.h"
43 #include "spdk/queue.h"
44
45 #ifdef __cplusplus
46 extern "C" {
47 #endif
48
49 #define MAX_EVENTS_PER_POLL 32
50 #define DEFAULT_SOCK_PRIORITY 0
51 #define MIN_SOCK_PIPE_SIZE 1024
52
53 struct spdk_sock {
54 struct spdk_net_impl *net_impl;
55 struct spdk_sock_opts opts;
56 int cb_cnt;
57 spdk_sock_cb cb_fn;
58 void *cb_arg;
59 struct spdk_sock_group_impl *group_impl;
60 TAILQ_ENTRY(spdk_sock) link;
61
62 int max_iovcnt;
63 TAILQ_HEAD(, spdk_sock_request) queued_reqs;
64 TAILQ_HEAD(, spdk_sock_request) pending_reqs;
65 int queued_iovcnt;
66
67 struct {
68 uint8_t closed : 1;
69 uint8_t reserved : 7;
70 } flags;
71 };
72
73 struct spdk_sock_group {
74 STAILQ_HEAD(, spdk_sock_group_impl) group_impls;
75 void *ctx;
76 };
77
78 struct spdk_sock_group_impl {
79 struct spdk_net_impl *net_impl;
80 TAILQ_HEAD(, spdk_sock) socks;
81 STAILQ_ENTRY(spdk_sock_group_impl) link;
82 /* List of removed sockets. refreshed each time we poll the sock group. */
83 int num_removed_socks;
84 /* Unfortunately, we can't just keep a tailq of the sockets in case they are freed
85 * or added to another poll group later.
86 */
87 uintptr_t removed_socks[MAX_EVENTS_PER_POLL];
88 };
89
90 struct spdk_net_impl {
91 const char *name;
92 int priority;
93
94 int (*getaddr)(struct spdk_sock *sock, char *saddr, int slen, uint16_t *sport, char *caddr,
95 int clen, uint16_t *cport);
96 struct spdk_sock *(*connect)(const char *ip, int port, struct spdk_sock_opts *opts);
97 struct spdk_sock *(*listen)(const char *ip, int port, struct spdk_sock_opts *opts);
98 struct spdk_sock *(*accept)(struct spdk_sock *sock);
99 int (*close)(struct spdk_sock *sock);
100 ssize_t (*recv)(struct spdk_sock *sock, void *buf, size_t len);
101 ssize_t (*readv)(struct spdk_sock *sock, struct iovec *iov, int iovcnt);
102 ssize_t (*writev)(struct spdk_sock *sock, struct iovec *iov, int iovcnt);
103
104 void (*writev_async)(struct spdk_sock *sock, struct spdk_sock_request *req);
105 int (*flush)(struct spdk_sock *sock);
106
107 int (*set_recvlowat)(struct spdk_sock *sock, int nbytes);
108 int (*set_recvbuf)(struct spdk_sock *sock, int sz);
109 int (*set_sendbuf)(struct spdk_sock *sock, int sz);
110
111 bool (*is_ipv6)(struct spdk_sock *sock);
112 bool (*is_ipv4)(struct spdk_sock *sock);
113 bool (*is_connected)(struct spdk_sock *sock);
114
115 int (*get_placement_id)(struct spdk_sock *sock, int *placement_id);
116 struct spdk_sock_group_impl *(*group_impl_create)(void);
117 int (*group_impl_add_sock)(struct spdk_sock_group_impl *group, struct spdk_sock *sock);
118 int (*group_impl_remove_sock)(struct spdk_sock_group_impl *group, struct spdk_sock *sock);
119 int (*group_impl_poll)(struct spdk_sock_group_impl *group, int max_events,
120 struct spdk_sock **socks);
121 int (*group_impl_close)(struct spdk_sock_group_impl *group);
122
123 int (*get_opts)(struct spdk_sock_impl_opts *opts, size_t *len);
124 int (*set_opts)(const struct spdk_sock_impl_opts *opts, size_t len);
125
126 STAILQ_ENTRY(spdk_net_impl) link;
127 };
128
129 void spdk_net_impl_register(struct spdk_net_impl *impl, int priority);
130
131 #define SPDK_NET_IMPL_REGISTER(name, impl, priority) \
132 static void __attribute__((constructor)) net_impl_register_##name(void) \
133 { \
134 spdk_net_impl_register(impl, priority); \
135 }
136
137 static inline void
138 spdk_sock_request_queue(struct spdk_sock *sock, struct spdk_sock_request *req)
139 {
140 TAILQ_INSERT_TAIL(&sock->queued_reqs, req, internal.link);
141 sock->queued_iovcnt += req->iovcnt;
142 }
143
144 static inline void
145 spdk_sock_request_pend(struct spdk_sock *sock, struct spdk_sock_request *req)
146 {
147 TAILQ_REMOVE(&sock->queued_reqs, req, internal.link);
148 assert(sock->queued_iovcnt >= req->iovcnt);
149 sock->queued_iovcnt -= req->iovcnt;
150 TAILQ_INSERT_TAIL(&sock->pending_reqs, req, internal.link);
151 }
152
153 static inline int
154 spdk_sock_request_put(struct spdk_sock *sock, struct spdk_sock_request *req, int err)
155 {
156 bool closed;
157 int rc = 0;
158
159 TAILQ_REMOVE(&sock->pending_reqs, req, internal.link);
160
161 req->internal.offset = 0;
162
163 closed = sock->flags.closed;
164 sock->cb_cnt++;
165 req->cb_fn(req->cb_arg, err);
166 assert(sock->cb_cnt > 0);
167 sock->cb_cnt--;
168
169 if (sock->cb_cnt == 0 && !closed && sock->flags.closed) {
170 /* The user closed the socket in response to a callback above. */
171 rc = -1;
172 spdk_sock_close(&sock);
173 }
174
175 return rc;
176 }
177
178 static inline int
179 spdk_sock_abort_requests(struct spdk_sock *sock)
180 {
181 struct spdk_sock_request *req;
182 bool closed;
183 int rc = 0;
184
185 closed = sock->flags.closed;
186 sock->cb_cnt++;
187
188 req = TAILQ_FIRST(&sock->pending_reqs);
189 while (req) {
190 TAILQ_REMOVE(&sock->pending_reqs, req, internal.link);
191
192 req->cb_fn(req->cb_arg, -ECANCELED);
193
194 req = TAILQ_FIRST(&sock->pending_reqs);
195 }
196
197 req = TAILQ_FIRST(&sock->queued_reqs);
198 while (req) {
199 TAILQ_REMOVE(&sock->queued_reqs, req, internal.link);
200
201 assert(sock->queued_iovcnt >= req->iovcnt);
202 sock->queued_iovcnt -= req->iovcnt;
203
204 req->cb_fn(req->cb_arg, -ECANCELED);
205
206 req = TAILQ_FIRST(&sock->queued_reqs);
207 }
208 assert(sock->cb_cnt > 0);
209 sock->cb_cnt--;
210
211 assert(TAILQ_EMPTY(&sock->queued_reqs));
212 assert(TAILQ_EMPTY(&sock->pending_reqs));
213
214 if (sock->cb_cnt == 0 && !closed && sock->flags.closed) {
215 /* The user closed the socket in response to a callback above. */
216 rc = -1;
217 spdk_sock_close(&sock);
218 }
219
220 return rc;
221 }
222
223 #ifdef __cplusplus
224 }
225 #endif
226
227 #endif /* SPDK_INTERNAL_SOCK_H */