Implementing basic data structure handling...
[vlendec/samba-autobuild/.git] / ctdb / ib / ibwrapper.c
1 /*
2  * Unix SMB/CIFS implementation.
3  * Wrap Infiniband calls.
4  *
5  * Copyright (C) Sven Oehme <oehmes@de.ibm.com> 2006
6  *
7  * Major code contributions by Peter Somogyi <psomogyi@gamax.hu>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23
24 #include "ibwrapper.h"
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdio.h>
29 #include <errno.h>
30 #include <sys/types.h>
31 #include <netinet/in.h>
32 #include <sys/socket.h>
33 #include <netdb.h>
34 #include <arpa/inet.h>
35
36 #include <rdma/rdma_cma.h>
37 #include "lib/events/events.h"
38
39 #include "ibwrapper_internal.h"
40
41
42 #define IBW_LASTERR_BUFSIZE 512
43 static char ibw_lasterr[IBW_LASTERR_BUFSIZE];
44
45 static ibw_mr *ibw_alloc_mr(ibw_ctx_priv *pctx)
46 {
47 }
48
49 static int ibw_ctx_priv_destruct(void *ptr)
50 {
51         ibw_ctx *pctx = talloc_get_type(ctx->internal, ibw_ctx_priv);
52         assert(pctx!=NULL);
53
54         if (pctx->cm_id) {
55                 rdma_destroy_id(pctx->cm_id);
56                 pctx->cm_id = NULL;
57         }
58         if (pctx->cm_channel) {
59                 rdma_destroy_event_channel(pctx->cm_channel);
60                 pctx->cm_channel = NULL;
61         }
62
63         /* free memory regions */
64 }
65
66 static int ibw_ctx_destruct(void *ptr)
67 {
68         ibw_ctx *ctx = talloc_get_type(ptr, ibw_ctx);
69         assert(ctx!=NULL);
70
71         if (pconn->cm_id) {
72                 rdma_destroy_id(pconn->cm_id);
73                 pconn->cm_id = NULL;
74         }
75
76         /* free memory regions */
77
78         return 0;
79 }
80
81 static int ibw_conn_priv_destruct(void *ptr)
82 {
83         ibw_conn *pconn = talloc_get_type(ptr, ibw_conn_priv);
84         assert(pconn!=NULL);
85 }
86
87 static int ibw_conn_destruct(void *ptr)
88 {
89         ibw_conn *conn = talloc_get_type(ptr, ibw_conn);
90         ibw_ctx *ctx;
91
92         assert(conn!=NULL);
93         ctx = ibw_conn->ctx;
94         assert(ctx!=NULL);
95
96         /* unhook conn from ctx's linked list */
97         assert(ctx->first_conn!=NULL);
98         assert(ctx->last_conn!=NULL);
99
100         if (conn->prev==NULL) {
101                 assert(ctx->first_conn==conn);
102                 ctx->first_conn = conn->next;
103         } else {
104                 conn->prev->next = conn->next;
105         }
106
107         if (conn->next==NULL) {
108                 assert(ctx->last_conn==conn);
109                 ctx->last_conn = conn->prev;
110         } else {
111                 conn->next->prev = conn->prev;
112         }
113         return 0;
114 }
115
116 static ibw_conn *ibw_new_conn(ibw_ctx *ctx)
117 {
118         ibw_conn *conn;
119         ibw_conn_priv *pconn;
120
121         conn = talloc_zero(ctx, ibw_conn);
122         assert(conn!=NULL);
123         talloc_set_destructor(conn, ibw_conn_destruct);
124
125         pconn = talloc_zero(ctx, ibw_conn_priv);
126         assert(pconn!=NULL);
127         talloc_set_destructor(pconn, ibw_conn_priv_destruct);
128
129         conn->ctx = ctx;
130
131         /* append conn to the end of ctx's linked list */
132         conn->prev = ctx->last_conn;
133         conn->next = NULL;
134         if (ctx->first_conn) {
135                 assert(ctx->last_conn!=NULL);
136                 conn->prev->next = conn;
137         } else {
138                 ctx->first_conn = ctx->last_conn = conn;
139         }
140
141         return conn;
142 }
143
144 static void ibw_process_cm_event(struct event_context *ev,
145         struct fd_event *fde, uint16_t flags, void *private_data)
146 {
147         int     rc;
148         ibw_ctx *ctx = talloc_get_type(private_data, ibw_ctx);
149         ibw_ctx *pctx = talloc_get_type(ctx->internal, ibw_ctx_priv);
150         struct rdma_cm_id *id;
151         struct rdma_cm_event event;
152
153         assert(ctx!=NULL);
154
155         rc = rdma_get_cm_event(cb->cm_channel, &event);
156         if (rc) {
157                 ctx->state = IBWS_ERROR;
158                 sprintf(ibw_lasterr, "rdma_get_cm_event error %d\n", rc);
159                 DEBUG(0, ibw_lasterr);
160                 return;
161         }
162         id = &event.id;
163
164         /* find whose cma_id we have */
165
166 //      DEBUG(10, "cma_event type %d cma_id %p (%s)\n", event->event, cma_id,
167 //                (cma_id == cb->cm_id) ? "parent" : "child");
168
169         switch (event->event) {
170         case RDMA_CM_EVENT_ADDR_RESOLVED:
171                 assert(pctx->state==IWINT_INIT);
172                 pctx->state = IWINT_ADDR_RESOLVED;
173                 ret = rdma_resolve_route(cma_id, 2000);
174                 if (ret) {
175                         cb->state = ERROR;
176                         fprintf(stderr, "rdma_resolve_route error %d\n", ret);
177                         sem_post(&cb->sem);
178                 }
179                 break;
180
181         case RDMA_CM_EVENT_ROUTE_RESOLVED:
182                 assert(pctx->state==IWINT_ADDR_RESOLVED);
183                 pctx->state = IWINT_ROUTE_RESOLVED;
184                 sem_post(&cb->sem);
185                 break;
186
187         case RDMA_CM_EVENT_CONNECT_REQUEST:
188                 cb->state = CONNECT_REQUEST;
189                 cb->child_cm_id = cma_id;
190                 DEBUG_LOG("child cma %p\n", cb->child_cm_id);
191                 sem_post(&cb->sem);
192                 break;
193
194         case RDMA_CM_EVENT_ESTABLISHED:
195                 DEBUG_LOG("ESTABLISHED\n");
196
197                 /*
198                  * Server will wake up when first RECV completes.
199                  */
200                 if (!cb->server) {
201                         cb->state = CONNECTED;
202                 }
203                 sem_post(&cb->sem);
204                 break;
205
206         case RDMA_CM_EVENT_ADDR_ERROR:
207         case RDMA_CM_EVENT_ROUTE_ERROR:
208         case RDMA_CM_EVENT_CONNECT_ERROR:
209         case RDMA_CM_EVENT_UNREACHABLE:
210         case RDMA_CM_EVENT_REJECTED:
211                 fprintf(stderr, "cma event %d, error %d\n", event->event,
212                        event->status);
213                 sem_post(&cb->sem);
214                 ret = -1;
215                 break;
216
217         case RDMA_CM_EVENT_DISCONNECTED:
218                 fprintf(stderr, "%s DISCONNECT EVENT...\n", cb->server ? "server" : "client");
219                 sem_post(&cb->sem);
220                 break;
221
222         case RDMA_CM_EVENT_DEVICE_REMOVAL:
223                 fprintf(stderr, "cma detected device removal!!!!\n");
224                 ret = -1;
225                 break;
226
227         default:
228                 fprintf(stderr, "oof bad type!\n");
229                 sem_post(&cb->sem);
230                 ret = -1;
231                 break;
232         }
233
234         rdma_ack_cm_event(event);
235 }
236
237 static int ibw_process_init_attrs(ibw_initattr *attr, int nattr, ibw_opts *opts)
238 {
239         int     i;
240         char *name, *value;
241         
242         for(i=0; i<nattr; i++) {
243                 name = attr[i].name;
244                 value = attr[i].value;
245
246                 assert(name!=NULL && value!=NULL);
247                 if (strcmp(name, "dev_name")==0)
248                         opts->opts.dev_name = talloc_strdup(ctx, value);
249                 else if (strcmp(name, "rx_depth")==0)
250                         opts->rx_depth = atoi(value);
251                 else if (strcmp(name, "mtu")==0)
252                         opts->mtu = atoi(value);
253                 else {
254                         sprintf(ibw_lasterr, "ibw_init: unknown name %s\n", name);
255                         return -1;
256                 }
257         }
258         return 0;
259 }
260
261 ibw_ctx *ibw_init(ibw_initattr *attr, int nattr,
262         void *ctx_userdata,
263         ibw_connstate_fn_t ibw_connstate,
264         ibw_receive_fn_t ibw_receive)
265 {
266         ibw_ctx *ctx = talloc_zero(NULL, ibw_ctx);
267         ibw_ctx_priv *pctx;
268         int     rc;
269
270         /* initialize basic data structures */
271         memset(ibw_lasterr, 0, IBW_LASTERR_BUFSIZE);
272
273         assert(ctx!=NULL);
274         ibw_lasterr[0] = '\0';
275         talloc_set_destructor(ctx, ibw_ctx_destruct);
276         ctx->userdata = userdata;
277
278         pctx = talloc_zero(ctx, ibw_ctx_priv);
279         talloc_set_destructor(pctx, ibw_ctx_priv_destruct);
280         ctx->internal = (void *)pctx;
281         assert(pctx!=NULL);
282
283         pctx->connstate_func = ibw_connstate;
284         pctx->receive_func = ibw_receive;
285
286         assert((pctx->ectx = event_context_init(ctx))!=NULL);
287
288         /* process attributes */
289         if (ibw_process_init_attrs(attr, nattr, pctx->opts))
290                 goto cleanup;
291
292         /* initialize CM stuff */
293         pctx->cm_channel = rdma_create_event_channel();
294         if (!pctx->cm_channel) {
295                 ret = errno;
296                 sprintf(ibw_lasterr, "rdma_create_event_channel error %d\n", ret);
297                 goto cleanup;
298         }
299
300         pctx->cm_channel_event = event_add_fd(pctx->ectx, pctx,
301                 pctx->cm_channel->fd, EVENT_FD_READ, ibw_process_cm_event, ctx);
302
303         rc = rdma_create_id(pctx->cm_channel, &pctx->cm_id, cb, RDMA_PS_TCP);
304         if (rc) {
305                 rc = errno;
306                 sprintf(ibw_lasterr, "rdma_create_id error %d\n", rc);
307                 goto cleanup;
308         }
309         DEBUG(10, "created cm_id %p\n", pctx->cm_id);
310
311         /* allocate ib memory regions */
312
313         return ctx;
314
315 cleanup:
316         if (ctx)
317                 talloc_free(ctx);
318
319         return NULL;
320 }
321
322 int ibw_stop(ibw_ctx *ctx)
323 {
324         ibw_ctx_priv *pctx = (ibw_ctx_priv *)ctx->internal;
325
326 }
327
328 int ibw_bind(ibw_ctx *ctx, struct sockaddr_in *my_addr)
329 {
330         ibw_ctx_priv *pctx = (ibw_ctx_priv *)ctx->internal;
331         int     rc;
332
333         rc = rdma_bind_addr(cb->cm_id, (struct sockaddr *) &my_addr);
334         if (rc) {
335                 sprintf(ibw_lasterr, "rdma_bind_addr error %d\n", rc);
336                 return rc;
337         }
338
339         return 0;
340 }
341
342 int ibw_listen(ibw_ctx *ctx, int backlog)
343 {
344         ibw_ctx_priv *pctx = (ibw_ctx_priv *)ctx->internal;
345         
346         return 0;
347 }
348
349 int ibw_accept(ibw_ctx *ctx, void *conn_userdata)
350 {
351         ibw_ctx_priv *pctx = (ibw_ctx_priv *)ctx->internal;
352         
353         return 0;
354 }
355
356 int ibw_connect(ibw_ctx *ctx, struct sockaddr_in *serv_addr, void *conn_userdata)
357 {
358         ibw_ctx_priv *pctx = (ibw_ctx_priv *)ctx->internal;
359                 
360         return 0;
361 }
362
363 void ibw_disconnect(ibw_conn *conn)
364 {
365         ibw_ctx_priv *pctx = (ibw_ctx_priv *)ctx->internal;
366         
367         return 0;
368 }
369
370 int ibw_alloc_send_buf(ibw_conn *conn, void **buf, void **key, int n)
371 {
372         ibw_conn_priv *pconn = (ibw_ctx_priv *)ctx->internal;
373
374         return 0;
375 }
376
377 int ibw_send(ibw_conn *conn, void *buf, void *key, int n)
378 {
379         ibw_conn_priv *pconn = (ibw_ctx_priv *)ctx->internal;
380         return 0;
381 }
382
383 const char *ibw_getLastError()
384 {
385         return ibw_lasterr;
386 }