ibacm: Remove umask(0)
[~shefty/ibacm.git] / src / acm.c
1 /*
2  * Copyright (c) 2009-2012 Intel Corporation. All rights reserved.
3  *
4  * This software is available to you under the OpenIB.org BSD license
5  * below:
6  *
7  *     Redistribution and use in source and binary forms, with or
8  *     without modification, are permitted provided that the following
9  *     conditions are met:
10  *
11  *      - Redistributions of source code must retain the above
12  *        copyright notice, this list of conditions and the following
13  *        disclaimer.
14  *
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.
19  *
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
27  * SOFTWARE.
28  */
29
30 #if HAVE_CONFIG_H
31 #  include <config.h>
32 #endif /* HAVE_CONFIG_H */
33
34 #include <stdio.h>
35 #include <stdarg.h>
36 #include <string.h>
37 #include <osd.h>
38 #include <arpa/inet.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <sys/time.h>
42 #include <fcntl.h>
43 #include <infiniband/acm.h>
44 #include <infiniband/umad.h>
45 #include <infiniband/verbs.h>
46 #include <dlist.h>
47 #include <search.h>
48 #include "acm_mad.h"
49
50 #define src_out     data[0]
51
52 #define MAX_EP_ADDR 4
53 #define MAX_EP_MC   2
54
55 enum acm_state {
56         ACM_INIT,
57         ACM_QUERY_ADDR,
58         ACM_ADDR_RESOLVED,
59         ACM_QUERY_ROUTE,
60         ACM_READY
61 };
62
63 enum acm_addr_prot {
64         ACM_ADDR_PROT_ACM
65 };
66
67 enum acm_route_prot {
68         ACM_ROUTE_PROT_ACM,
69         ACM_ROUTE_PROT_SA
70 };
71
72 enum acm_loopback_prot {
73         ACM_LOOPBACK_PROT_NONE,
74         ACM_LOOPBACK_PROT_LOCAL
75 };
76
77 /*
78  * Nested locking order: dest -> ep, dest -> port
79  */
80 struct acm_dest {
81         uint8_t                address[ACM_MAX_ADDRESS]; /* keep first */
82         char                   name[ACM_MAX_ADDRESS];
83         struct ibv_ah          *ah;
84         struct ibv_ah_attr     av;
85         struct ibv_path_record path;
86         union ibv_gid          mgid;
87         uint64_t               req_id;
88         DLIST_ENTRY            req_queue;
89         uint32_t               remote_qpn;
90         lock_t                 lock;
91         enum acm_state         state;
92         atomic_t               refcnt;
93         uint64_t               addr_timeout;
94         uint64_t               route_timeout;
95         uint8_t                addr_type;
96 };
97
98 struct acm_port {
99         struct acm_device   *dev;
100         DLIST_ENTRY         ep_list;
101         lock_t              lock;
102         int                 mad_portid;
103         int                 mad_agentid;
104         struct acm_dest     sa_dest;
105         enum ibv_port_state state;
106         enum ibv_mtu        mtu;
107         enum ibv_rate       rate;
108         int                 subnet_timeout;
109         int                 gid_cnt;
110         uint16_t            pkey_cnt;
111         uint16_t            lid;
112         uint16_t            lid_mask;
113         uint8_t             port_num;
114 };
115
116 struct acm_device {
117         struct ibv_context      *verbs;
118         struct ibv_comp_channel *channel;
119         struct ibv_pd           *pd;
120         uint64_t                guid;
121         DLIST_ENTRY             entry;
122         int                     port_cnt;
123         struct acm_port         port[0];
124 };
125
126 /* Maintain separate virtual send queues to avoid deadlock */
127 struct acm_send_queue {
128         int                   credits;
129         DLIST_ENTRY           pending;
130 };
131
132 struct acm_ep {
133         struct acm_port       *port;
134         struct ibv_cq         *cq;
135         struct ibv_qp         *qp;
136         struct ibv_mr         *mr;
137         uint8_t               *recv_bufs;
138         DLIST_ENTRY           entry;
139         union acm_ep_info     addr[MAX_EP_ADDR];
140         char                  name[MAX_EP_ADDR][ACM_MAX_ADDRESS];
141         uint8_t               addr_type[MAX_EP_ADDR];
142         void                  *dest_map[ACM_ADDRESS_RESERVED - 1];
143         struct acm_dest       mc_dest[MAX_EP_MC];
144         int                   mc_cnt;
145         uint16_t              pkey_index;
146         uint16_t              pkey;
147         lock_t                lock;
148         struct acm_send_queue resolve_queue;
149         struct acm_send_queue sa_queue;
150         struct acm_send_queue resp_queue;
151         DLIST_ENTRY           active_queue;
152         DLIST_ENTRY           wait_queue;
153         enum acm_state        state;
154 };
155
156 struct acm_send_msg {
157         DLIST_ENTRY          entry;
158         struct acm_ep        *ep;
159         struct acm_dest      *dest;
160         struct ibv_ah        *ah;
161         void                 *context;
162         void                 (*resp_handler)(struct acm_send_msg *req,
163                                              struct ibv_wc *wc, struct acm_mad *resp);
164         struct acm_send_queue *req_queue;
165         struct ibv_mr        *mr;
166         struct ibv_send_wr   wr;
167         struct ibv_sge       sge;
168         uint64_t             expires;
169         int                  tries;
170         uint8_t              data[ACM_SEND_SIZE];
171 };
172
173 struct acm_client {
174         lock_t   lock;   /* acquire ep lock first */
175         SOCKET   sock;
176         int      index;
177         atomic_t refcnt;
178 };
179
180 struct acm_request {
181         struct acm_client *client;
182         DLIST_ENTRY       entry;
183         struct acm_msg    msg;
184 };
185
186 union socket_addr {
187         struct sockaddr     sa;
188         struct sockaddr_in  sin;
189         struct sockaddr_in6 sin6;
190 };
191
192 static DLIST_ENTRY dev_list;
193
194 static atomic_t tid;
195 static DLIST_ENTRY timeout_list;
196 static event_t timeout_event;
197 static atomic_t wait_cnt;
198
199 static SOCKET listen_socket;
200 static struct acm_client client[FD_SETSIZE - 1];
201
202 static FILE *flog;
203 static lock_t log_lock;
204 PER_THREAD char log_data[ACM_MAX_ADDRESS];
205 static atomic_t counter[ACM_MAX_COUNTER];
206
207 /*
208  * Service options - may be set through acm_opts file.
209  */
210 static char *acme = BINDIR "/ib_acme -A";
211 static char *opts_file = ACM_CONF_DIR "/" ACM_OPTS_FILE;
212 static char *addr_file = ACM_CONF_DIR "/" ACM_ADDR_FILE;
213 static char log_file[128] = "/var/log/ibacm.log";
214 static int log_level = 0;
215 static char lock_file[128] = "/var/run/ibacm.pid";
216 static enum acm_addr_prot addr_prot = ACM_ADDR_PROT_ACM;
217 static int addr_timeout = 1440;
218 static enum acm_route_prot route_prot = ACM_ROUTE_PROT_SA;
219 static int route_timeout = -1;
220 static enum acm_loopback_prot loopback_prot = ACM_LOOPBACK_PROT_LOCAL;
221 static short server_port = 6125;
222 static int timeout = 2000;
223 static int retries = 2;
224 static int resolve_depth = 1;
225 static int sa_depth = 1;
226 static int send_depth = 1;
227 static int recv_depth = 1024;
228 static uint8_t min_mtu = IBV_MTU_2048;
229 static uint8_t min_rate = IBV_RATE_10_GBPS;
230
231 #define acm_log(level, format, ...) \
232         acm_write(level, "%s: "format, __func__, ## __VA_ARGS__)
233
234 static void acm_write(int level, const char *format, ...)
235 {
236         va_list args;
237         struct timeval tv;
238
239         if (level > log_level)
240                 return;
241
242         gettimeofday(&tv, NULL);
243         va_start(args, format);
244         lock_acquire(&log_lock);
245         fprintf(flog, "%u.%03u: ", (unsigned) tv.tv_sec, (unsigned) (tv.tv_usec / 1000));
246         vfprintf(flog, format, args);
247         fflush(flog);
248         lock_release(&log_lock);
249         va_end(args);
250 }
251
252 static void
253 acm_format_name(int level, char *name, size_t name_size,
254                 uint8_t addr_type, uint8_t *addr, size_t addr_size)
255 {
256         struct ibv_path_record *path;
257
258         if (level > log_level)
259                 return;
260
261         switch (addr_type) {
262         case ACM_EP_INFO_NAME:
263                 memcpy(name, addr, addr_size);
264                 break;
265         case ACM_EP_INFO_ADDRESS_IP:
266                 inet_ntop(AF_INET, addr, name, name_size);
267                 break;
268         case ACM_EP_INFO_ADDRESS_IP6:
269         case ACM_ADDRESS_GID:
270                 inet_ntop(AF_INET6, addr, name, name_size);
271                 break;
272         case ACM_EP_INFO_PATH:
273                 path = (struct ibv_path_record *) addr;
274                 if (path->dlid) {
275                         snprintf(name, name_size, "SLID(%u) DLID(%u)",
276                                 ntohs(path->slid), ntohs(path->dlid));
277                 } else {
278                         acm_format_name(level, name, name_size, ACM_ADDRESS_GID,
279                                         path->dgid.raw, sizeof path->dgid);
280                 }
281                 break;
282         case ACM_ADDRESS_LID:
283                 snprintf(name, name_size, "LID(%u)", ntohs(*((uint16_t *) addr)));
284                 break;
285         default:
286                 strcpy(name, "Unknown");
287                 break;
288         }
289 }
290
291 static int ib_any_gid(union ibv_gid *gid)
292 {
293         return ((gid->global.subnet_prefix | gid->global.interface_id) == 0);
294 }
295
296 static int acm_compare_dest(const void *dest1, const void *dest2)
297 {
298         return memcmp(dest1, dest2, ACM_MAX_ADDRESS);
299 }
300
301 static void
302 acm_set_dest_addr(struct acm_dest *dest, uint8_t addr_type, uint8_t *addr, size_t size)
303 {
304         memcpy(dest->address, addr, size);
305         dest->addr_type = addr_type;
306         acm_format_name(0, dest->name, sizeof dest->name, addr_type, addr, size);
307 }
308
309 static void
310 acm_init_dest(struct acm_dest *dest, uint8_t addr_type, uint8_t *addr, size_t size)
311 {
312         DListInit(&dest->req_queue);
313         atomic_init(&dest->refcnt);
314         atomic_set(&dest->refcnt, 1);
315         lock_init(&dest->lock);
316         if (size)
317                 acm_set_dest_addr(dest, addr_type, addr, size);
318 }
319
320 static struct acm_dest *
321 acm_alloc_dest(uint8_t addr_type, uint8_t *addr)
322 {
323         struct acm_dest *dest;
324
325         dest = calloc(1, sizeof *dest);
326         if (!dest) {
327                 acm_log(0, "ERROR - unable to allocate dest\n");
328                 return NULL;
329         }
330
331         acm_init_dest(dest, addr_type, addr, ACM_MAX_ADDRESS);
332         acm_log(1, "%s\n", dest->name);
333         return dest;
334 }
335
336 /* Caller must hold ep lock. */
337 static struct acm_dest *
338 acm_get_dest(struct acm_ep *ep, uint8_t addr_type, uint8_t *addr)
339 {
340         struct acm_dest *dest, **tdest;
341
342         tdest = tfind(addr, &ep->dest_map[addr_type - 1], acm_compare_dest);
343         if (tdest) {
344                 dest = *tdest;
345                 (void) atomic_inc(&dest->refcnt);
346                 acm_log(2, "%s\n", dest->name);
347         } else {
348                 dest = NULL;
349                 acm_format_name(2, log_data, sizeof log_data,
350                                 addr_type, addr, ACM_MAX_ADDRESS);
351                 acm_log(2, "%s not found\n", log_data);
352         }
353         return dest;
354 }
355
356 static void
357 acm_put_dest(struct acm_dest *dest)
358 {
359         acm_log(2, "%s\n", dest->name);
360         if (atomic_dec(&dest->refcnt) == 0) {
361                 free(dest);
362         }
363 }
364
365 static struct acm_dest *
366 acm_acquire_dest(struct acm_ep *ep, uint8_t addr_type, uint8_t *addr)
367 {
368         struct acm_dest *dest;
369
370         acm_format_name(2, log_data, sizeof log_data,
371                         addr_type, addr, ACM_MAX_ADDRESS);
372         acm_log(2, "%s\n", log_data);
373         lock_acquire(&ep->lock);
374         dest = acm_get_dest(ep, addr_type, addr);
375         if (!dest) {
376                 dest = acm_alloc_dest(addr_type, addr);
377                 if (dest) {
378                         tsearch(dest, &ep->dest_map[addr_type - 1], acm_compare_dest);
379                         (void) atomic_inc(&dest->refcnt);
380                 }
381         }
382         lock_release(&ep->lock);
383         return dest;
384 }
385
386 static struct acm_dest *
387 acm_acquire_sa_dest(struct acm_port *port)
388 {
389         struct acm_dest *dest;
390
391         lock_acquire(&port->lock);
392         if (port->state == IBV_PORT_ACTIVE) {
393                 dest = &port->sa_dest;
394                 atomic_inc(&port->sa_dest.refcnt);
395         } else {
396                 dest = NULL;
397         }
398         lock_release(&port->lock);
399         return dest;
400 }
401
402 static void acm_release_sa_dest(struct acm_dest *dest)
403 {
404         atomic_dec(&dest->refcnt);
405 }
406
407 /* Caller must hold ep lock. */
408 //static void
409 //acm_remove_dest(struct acm_ep *ep, struct acm_dest *dest)
410 //{
411 //      acm_log(2, "%s\n", dest->name);
412 //      tdelete(dest->address, &ep->dest_map[dest->addr_type - 1], acm_compare_dest);
413 //      acm_put_dest(dest);
414 //}
415
416 static struct acm_request *
417 acm_alloc_req(struct acm_client *client, struct acm_msg *msg)
418 {
419         struct acm_request *req;
420
421         req = calloc(1, sizeof *req);
422         if (!req) {
423                 acm_log(0, "ERROR - unable to alloc client request\n");
424                 return NULL;
425         }
426
427         (void) atomic_inc(&client->refcnt);
428         req->client = client;
429         memcpy(&req->msg, msg, sizeof(req->msg));
430         acm_log(2, "client %d, req %p\n", client->index, req);
431         return req;
432 }
433
434 static void
435 acm_free_req(struct acm_request *req)
436 {
437         acm_log(2, "%p\n", req);
438         (void) atomic_dec(&client->refcnt);
439         free(req);
440 }
441
442 static struct acm_send_msg *
443 acm_alloc_send(struct acm_ep *ep, struct acm_dest *dest, size_t size)
444 {
445         struct acm_send_msg *msg;
446
447         msg = (struct acm_send_msg *) calloc(1, sizeof *msg);
448         if (!msg) {
449                 acm_log(0, "ERROR - unable to allocate send buffer\n");
450                 return NULL;
451         }
452
453         msg->ep = ep;
454         msg->mr = ibv_reg_mr(ep->port->dev->pd, msg->data, size, 0);
455         if (!msg->mr) {
456                 acm_log(0, "ERROR - failed to register send buffer\n");
457                 goto err1;
458         }
459
460         if (!dest->ah) {
461                 msg->ah = ibv_create_ah(ep->port->dev->pd, &dest->av);
462                 if (!msg->ah) {
463                         acm_log(0, "ERROR - unable to create ah\n");
464                         goto err2;
465                 }
466                 msg->wr.wr.ud.ah = msg->ah;
467         } else {
468                 msg->wr.wr.ud.ah = dest->ah;
469         }
470
471         acm_log(2, "get dest %s\n", dest->name);
472         (void) atomic_inc(&dest->refcnt);
473         msg->dest = dest;
474
475         msg->wr.next = NULL;
476         msg->wr.sg_list = &msg->sge;
477         msg->wr.num_sge = 1;
478         msg->wr.opcode = IBV_WR_SEND;
479         msg->wr.send_flags = IBV_SEND_SIGNALED;
480         msg->wr.wr_id = (uintptr_t) msg;
481         msg->wr.wr.ud.remote_qpn = dest->remote_qpn;
482         msg->wr.wr.ud.remote_qkey = ACM_QKEY;
483
484         msg->sge.length = size;
485         msg->sge.lkey = msg->mr->lkey;
486         msg->sge.addr = (uintptr_t) msg->data;
487         acm_log(2, "%p\n", msg);
488         return msg;
489
490 err2:
491         ibv_dereg_mr(msg->mr);
492 err1:
493         free(msg);
494         return NULL;
495 }
496
497 static void
498 acm_init_send_req(struct acm_send_msg *msg, void *context, 
499         void (*resp_handler)(struct acm_send_msg *req,
500                 struct ibv_wc *wc, struct acm_mad *resp))
501 {
502         acm_log(2, "%p\n", msg);
503         msg->tries = retries + 1;
504         msg->context = context;
505         msg->resp_handler = resp_handler;
506 }
507
508 static void acm_free_send(struct acm_send_msg *msg)
509 {
510         acm_log(2, "%p\n", msg);
511         if (msg->ah)
512                 ibv_destroy_ah(msg->ah);
513         ibv_dereg_mr(msg->mr);
514         acm_put_dest(msg->dest);
515         free(msg);
516 }
517
518 static void acm_post_send(struct acm_send_queue *queue, struct acm_send_msg *msg)
519 {
520         struct acm_ep *ep = msg->ep;
521         struct ibv_send_wr *bad_wr;
522
523         msg->req_queue = queue;
524         lock_acquire(&ep->lock);
525         if (queue->credits) {
526                 acm_log(2, "posting send to QP\n");
527                 queue->credits--;
528                 DListInsertTail(&msg->entry, &ep->active_queue);
529                 ibv_post_send(ep->qp, &msg->wr, &bad_wr);
530         } else {
531                 acm_log(2, "no sends available, queuing message\n");
532                 DListInsertTail(&msg->entry, &queue->pending);
533         }
534         lock_release(&ep->lock);
535 }
536
537 static void acm_post_recv(struct acm_ep *ep, uint64_t address)
538 {
539         struct ibv_recv_wr wr, *bad_wr;
540         struct ibv_sge sge;
541
542         wr.next = NULL;
543         wr.sg_list = &sge;
544         wr.num_sge = 1;
545         wr.wr_id = address;
546
547         sge.length = ACM_RECV_SIZE;
548         sge.lkey = ep->mr->lkey;
549         sge.addr = address;
550
551         ibv_post_recv(ep->qp, &wr, &bad_wr);
552 }
553
554 /* Caller must hold ep lock */
555 static void acm_send_available(struct acm_ep *ep, struct acm_send_queue *queue)
556 {
557         struct acm_send_msg *msg;
558         struct ibv_send_wr *bad_wr;
559         DLIST_ENTRY *entry;
560
561         if (DListEmpty(&queue->pending)) {
562                 queue->credits++;
563         } else {
564                 acm_log(2, "posting queued send message\n");
565                 entry = queue->pending.Next;
566                 DListRemove(entry);
567                 msg = container_of(entry, struct acm_send_msg, entry);
568                 DListInsertTail(&msg->entry, &ep->active_queue);
569                 ibv_post_send(ep->qp, &msg->wr, &bad_wr);
570         }
571 }
572
573 static void acm_complete_send(struct acm_send_msg *msg)
574 {
575         struct acm_ep *ep = msg->ep;
576
577         lock_acquire(&ep->lock);
578         DListRemove(&msg->entry);
579         if (msg->tries) {
580                 acm_log(2, "waiting for response\n");
581                 msg->expires = time_stamp_ms() + ep->port->subnet_timeout + timeout;
582                 DListInsertTail(&msg->entry, &ep->wait_queue);
583                 if (atomic_inc(&wait_cnt) == 1)
584                         event_signal(&timeout_event);
585         } else {
586                 acm_log(2, "freeing\n");
587                 acm_send_available(ep, msg->req_queue);
588                 acm_free_send(msg);
589         }
590         lock_release(&ep->lock);
591 }
592
593 static struct acm_send_msg *acm_get_request(struct acm_ep *ep, uint64_t tid, int *free)
594 {
595         struct acm_send_msg *msg, *req = NULL;
596         struct acm_mad *mad;
597         DLIST_ENTRY *entry, *next;
598
599         acm_log(2, "\n");
600         lock_acquire(&ep->lock);
601         for (entry = ep->wait_queue.Next; entry != &ep->wait_queue; entry = next) {
602                 next = entry->Next;
603                 msg = container_of(entry, struct acm_send_msg, entry);
604                 mad = (struct acm_mad *) msg->data;
605                 if (mad->tid == tid) {
606                         acm_log(2, "match found in wait queue\n");
607                         req = msg;
608                         DListRemove(entry);
609                         (void) atomic_dec(&wait_cnt);
610                         acm_send_available(ep, msg->req_queue);
611                         *free = 1;
612                         goto unlock;
613                 }
614         }
615
616         for (entry = ep->active_queue.Next; entry != &ep->active_queue; entry = entry->Next) {
617                 msg = container_of(entry, struct acm_send_msg, entry);
618                 mad = (struct acm_mad *) msg->data;
619                 if (mad->tid == tid && msg->tries) {
620                         acm_log(2, "match found in active queue\n");
621                         req = msg;
622                         req->tries = 0;
623                         *free = 0;
624                         break;
625                 }
626         }
627 unlock:
628         lock_release(&ep->lock);
629         return req;
630 }
631
632 static uint8_t acm_gid_index(struct acm_port *port, union ibv_gid *gid)
633 {
634         union ibv_gid cmp_gid;
635         uint8_t i;
636
637         for (i = 0; i < port->gid_cnt; i++) {
638                 ibv_query_gid(port->dev->verbs, port->port_num, i, &cmp_gid);
639                 if (!memcmp(&cmp_gid, gid, sizeof cmp_gid))
640                         break;
641         }
642         return i;
643 }
644
645 static int acm_mc_index(struct acm_ep *ep, union ibv_gid *gid)
646 {
647         int i;
648
649         for (i = 0; i < ep->mc_cnt; i++) {
650                 if (!memcmp(&ep->mc_dest[i].address, gid, sizeof(*gid)))
651                         return i;
652         }
653         return -1;
654 }
655
656 /* Multicast groups are ordered lowest to highest preference. */
657 static int acm_best_mc_index(struct acm_ep *ep, struct acm_resolve_rec *rec)
658 {
659         int i, index;
660
661         for (i = min(rec->gid_cnt, ACM_MAX_GID_COUNT) - 1; i >= 0; i--) {
662                 index = acm_mc_index(ep, &rec->gid[i]);
663                 if (index >= 0) {
664                         return index;
665                 }
666         }
667         return -1;
668 }
669
670 static void
671 acm_record_mc_av(struct acm_port *port, struct ib_mc_member_rec *mc_rec,
672         struct acm_dest *dest)
673 {
674         uint32_t sl_flow_hop;
675
676         sl_flow_hop = ntohl(mc_rec->sl_flow_hop);
677
678         dest->av.dlid = ntohs(mc_rec->mlid);
679         dest->av.sl = (uint8_t) (sl_flow_hop >> 28);
680         dest->av.src_path_bits = port->sa_dest.av.src_path_bits;
681         dest->av.static_rate = mc_rec->rate & 0x3F;
682         dest->av.port_num = port->port_num;
683
684         dest->av.is_global = 1;
685         dest->av.grh.dgid = mc_rec->mgid;
686         dest->av.grh.flow_label = (sl_flow_hop >> 8) & 0xFFFFF;
687         dest->av.grh.sgid_index = acm_gid_index(port, &mc_rec->port_gid);
688         dest->av.grh.hop_limit = (uint8_t) sl_flow_hop;
689         dest->av.grh.traffic_class = mc_rec->tclass;
690
691         dest->path.dgid = mc_rec->mgid;
692         dest->path.sgid = mc_rec->port_gid;
693         dest->path.dlid = mc_rec->mlid;
694         dest->path.slid = htons(port->lid) | port->sa_dest.av.src_path_bits;
695         dest->path.flowlabel_hoplimit = htonl(sl_flow_hop & 0xFFFFFFF);
696         dest->path.tclass = mc_rec->tclass;
697         dest->path.reversible_numpath = IBV_PATH_RECORD_REVERSIBLE | 1;
698         dest->path.pkey = mc_rec->pkey;
699         dest->path.qosclass_sl = htons((uint16_t) (sl_flow_hop >> 28));
700         dest->path.mtu = mc_rec->mtu;
701         dest->path.rate = mc_rec->rate;
702         dest->path.packetlifetime = mc_rec->packet_lifetime;
703 }
704
705 /* Always send the GRH to transfer GID data to remote side */
706 static void
707 acm_init_path_av(struct acm_port *port, struct acm_dest *dest)
708 {
709         uint32_t flow_hop;
710
711         dest->av.dlid = ntohs(dest->path.dlid);
712         dest->av.sl = ntohs(dest->path.qosclass_sl) & 0xF;
713         dest->av.src_path_bits = dest->path.slid & 0x7F;
714         dest->av.static_rate = dest->path.rate & 0x3F;
715         dest->av.port_num = port->port_num;
716
717         flow_hop = ntohl(dest->path.flowlabel_hoplimit);
718         dest->av.is_global = 1;
719         dest->av.grh.flow_label = (flow_hop >> 8) & 0xFFFFF;
720         dest->av.grh.sgid_index = acm_gid_index(port, &dest->path.sgid);
721         dest->av.grh.hop_limit = (uint8_t) flow_hop;
722         dest->av.grh.traffic_class = dest->path.tclass;
723 }
724
725 static void acm_process_join_resp(struct acm_ep *ep, struct ib_user_mad *umad)
726 {
727         struct acm_dest *dest;
728         struct ib_mc_member_rec *mc_rec;
729         struct ib_sa_mad *mad;
730         int index, ret;
731
732         mad = (struct ib_sa_mad *) umad->data;
733         acm_log(1, "response status: 0x%x, mad status: 0x%x\n",
734                 umad->status, mad->status);
735         if (umad->status) {
736                 acm_log(0, "ERROR - send join failed 0x%x\n", umad->status);
737                 return;
738         }
739         if (mad->status) {
740                 acm_log(0, "ERROR - join response status 0x%x\n", mad->status);
741                 return;
742         }
743
744         mc_rec = (struct ib_mc_member_rec *) mad->data;
745         lock_acquire(&ep->lock);
746         index = acm_mc_index(ep, &mc_rec->mgid);
747         if (index < 0) {
748                 acm_log(0, "ERROR - MGID in join response not found\n");
749                 goto out;
750         }
751
752         dest = &ep->mc_dest[index];
753         dest->remote_qpn = IB_MC_QPN;
754         dest->mgid = mc_rec->mgid;
755         acm_record_mc_av(ep->port, mc_rec, dest);
756
757         if (index == 0) {
758                 dest->ah = ibv_create_ah(ep->port->dev->pd, &dest->av);
759                 if (!dest->ah) {
760                         acm_log(0, "ERROR - unable to create ah\n");
761                         goto out;
762                 }
763                 ret = ibv_attach_mcast(ep->qp, &mc_rec->mgid, mc_rec->mlid);
764                 if (ret) {
765                         acm_log(0, "ERROR - unable to attach QP to multicast group\n");
766                         goto out;
767                 }
768         }
769
770         atomic_set(&dest->refcnt, 1);
771         dest->state = ACM_READY;
772         acm_log(1, "join successful\n");
773 out:
774         lock_release(&ep->lock);
775 }
776
777 static int acm_addr_index(struct acm_ep *ep, uint8_t *addr, uint8_t addr_type)
778 {
779         int i;
780
781         for (i = 0; i < MAX_EP_ADDR; i++) {
782                 if (ep->addr_type[i] != addr_type)
783                         continue;
784
785                 if ((addr_type == ACM_ADDRESS_NAME &&
786                         !strnicmp((char *) ep->addr[i].name,
787                                 (char *) addr, ACM_MAX_ADDRESS)) ||
788                         !memcmp(ep->addr[i].addr, addr, ACM_MAX_ADDRESS))
789                         return i;
790         }
791         return -1;
792 }
793
794 static uint8_t
795 acm_record_acm_route(struct acm_ep *ep, struct acm_dest *dest)
796 {
797         int i;
798
799         acm_log(2, "\n");
800         for (i = 0; i < MAX_EP_MC; i++) {
801                 if (!memcmp(&dest->mgid, &ep->mc_dest[i].mgid, sizeof dest->mgid))
802                         break;
803         }
804         if (i == MAX_EP_MC) {
805                 acm_log(0, "ERROR - cannot match mgid\n");
806                 return ACM_STATUS_EINVAL;
807         }
808
809         dest->path = ep->mc_dest[i].path;
810         dest->path.dgid = dest->av.grh.dgid;
811         dest->path.dlid = htons(dest->av.dlid);
812         dest->addr_timeout = time_stamp_min() + (unsigned) addr_timeout;
813         dest->route_timeout = time_stamp_min() + (unsigned) route_timeout;
814         dest->state = ACM_READY;
815         return ACM_STATUS_SUCCESS;
816 }
817
818 static void acm_init_path_query(struct ib_sa_mad *mad)
819 {
820         acm_log(2, "\n");
821         mad->base_version = 1;
822         mad->mgmt_class = IB_MGMT_CLASS_SA;
823         mad->class_version = 2;
824         mad->method = IB_METHOD_GET;
825         mad->tid = (uint64_t) atomic_inc(&tid);
826         mad->attr_id = IB_SA_ATTR_PATH_REC;
827 }
828
829 static uint64_t acm_path_comp_mask(struct ibv_path_record *path)
830 {
831         uint32_t fl_hop;
832         uint16_t qos_sl;
833         uint64_t comp_mask = 0;
834
835         acm_log(2, "\n");
836         if (path->service_id)
837                 comp_mask |= IB_COMP_MASK_PR_SERVICE_ID;
838         if (!ib_any_gid(&path->dgid))
839                 comp_mask |= IB_COMP_MASK_PR_DGID;
840         if (!ib_any_gid(&path->sgid))
841                 comp_mask |= IB_COMP_MASK_PR_SGID;
842         if (path->dlid)
843                 comp_mask |= IB_COMP_MASK_PR_DLID;
844         if (path->slid)
845                 comp_mask |= IB_COMP_MASK_PR_SLID;
846
847         fl_hop = ntohl(path->flowlabel_hoplimit);
848         if (fl_hop >> 8)
849                 comp_mask |= IB_COMP_MASK_PR_FLOW_LABEL;
850         if (fl_hop & 0xFF)
851                 comp_mask |= IB_COMP_MASK_PR_HOP_LIMIT;
852
853         if (path->tclass)
854                 comp_mask |= IB_COMP_MASK_PR_TCLASS;
855         if (path->reversible_numpath & 0x80)
856                 comp_mask |= IB_COMP_MASK_PR_REVERSIBLE;
857         if (path->pkey)
858                 comp_mask |= IB_COMP_MASK_PR_PKEY;
859
860         qos_sl = ntohs(path->qosclass_sl);
861         if (qos_sl >> 4)
862                 comp_mask |= IB_COMP_MASK_PR_QOS_CLASS;
863         if (qos_sl & 0xF)
864                 comp_mask |= IB_COMP_MASK_PR_SL;
865
866         if (path->mtu & 0xC0)
867                 comp_mask |= IB_COMP_MASK_PR_MTU_SELECTOR;
868         if (path->mtu & 0x3F)
869                 comp_mask |= IB_COMP_MASK_PR_MTU;
870         if (path->rate & 0xC0)
871                 comp_mask |= IB_COMP_MASK_PR_RATE_SELECTOR;
872         if (path->rate & 0x3F)
873                 comp_mask |= IB_COMP_MASK_PR_RATE;
874         if (path->packetlifetime & 0xC0)
875                 comp_mask |= IB_COMP_MASK_PR_PACKET_LIFETIME_SELECTOR;
876         if (path->packetlifetime & 0x3F)
877                 comp_mask |= IB_COMP_MASK_PR_PACKET_LIFETIME;
878
879         return comp_mask;
880 }
881
882 /* Caller must hold dest lock */
883 static uint8_t acm_resolve_path(struct acm_ep *ep, struct acm_dest *dest,
884         void (*resp_handler)(struct acm_send_msg *req,
885                 struct ibv_wc *wc, struct acm_mad *resp))
886 {
887         struct acm_send_msg *msg;
888         struct ib_sa_mad *mad;
889         uint8_t ret;
890
891         acm_log(2, "%s\n", dest->name);
892         if (!acm_acquire_sa_dest(ep->port)) {
893                 acm_log(1, "cannot acquire SA destination\n");
894                 ret = ACM_STATUS_EINVAL;
895                 goto err;
896         }
897
898         msg = acm_alloc_send(ep, &ep->port->sa_dest, sizeof(*mad));
899         acm_release_sa_dest(&ep->port->sa_dest);
900         if (!msg) {
901                 acm_log(0, "ERROR - cannot allocate send msg\n");
902                 ret = ACM_STATUS_ENOMEM;
903                 goto err;
904         }
905
906         (void) atomic_inc(&dest->refcnt);
907         acm_init_send_req(msg, (void *) dest, resp_handler);
908         mad = (struct ib_sa_mad *) msg->data;
909         acm_init_path_query(mad);
910
911         memcpy(mad->data, &dest->path, sizeof(dest->path));
912         mad->comp_mask = acm_path_comp_mask(&dest->path);
913
914         atomic_inc(&counter[ACM_CNTR_ROUTE_QUERY]);
915         dest->state = ACM_QUERY_ROUTE;
916         acm_post_send(&ep->sa_queue, msg);
917         return ACM_STATUS_SUCCESS;
918 err:
919         dest->state = ACM_INIT;
920         return ret;
921 }
922
923 static uint8_t
924 acm_record_acm_addr(struct acm_ep *ep, struct acm_dest *dest, struct ibv_wc *wc,
925         struct acm_resolve_rec *rec)
926 {
927         int index;
928
929         acm_log(2, "%s\n", dest->name);
930         index = acm_best_mc_index(ep, rec);
931         if (index < 0) {
932                 acm_log(0, "ERROR - no shared multicast groups\n");
933                 dest->state = ACM_INIT;
934                 return ACM_STATUS_ENODATA;
935         }
936
937         acm_log(2, "selecting MC group at index %d\n", index);
938         dest->av = ep->mc_dest[index].av;
939         dest->av.dlid = wc->slid;
940         dest->av.src_path_bits = wc->dlid_path_bits;
941         dest->av.grh.dgid = ((struct ibv_grh *) (uintptr_t) wc->wr_id)->sgid;
942         
943         dest->mgid = ep->mc_dest[index].mgid;
944         dest->path.sgid = ep->mc_dest[index].path.sgid;
945         dest->path.dgid = dest->av.grh.dgid;
946         dest->path.tclass = ep->mc_dest[index].path.tclass;
947         dest->path.pkey = ep->mc_dest[index].path.pkey;
948         dest->remote_qpn = wc->src_qp;
949
950         dest->state = ACM_ADDR_RESOLVED;
951         return ACM_STATUS_SUCCESS;
952 }
953
954 static void
955 acm_record_path_addr(struct acm_ep *ep, struct acm_dest *dest,
956         struct ibv_path_record *path)
957 {
958         acm_log(2, "%s\n", dest->name);
959         dest->path.pkey = htons(ep->pkey);
960         dest->path.dgid = path->dgid;
961         if (path->slid || !ib_any_gid(&path->sgid)) {
962                 dest->path.sgid = path->sgid;
963                 dest->path.slid = path->slid;
964         } else {
965                 dest->path.slid = htons(ep->port->lid);
966         }
967         dest->path.dlid = path->dlid;
968         dest->state = ACM_ADDR_RESOLVED;
969 }
970
971 static uint8_t acm_validate_addr_req(struct acm_mad *mad)
972 {
973         struct acm_resolve_rec *rec;
974
975         if (mad->method != IB_METHOD_GET) {
976                 acm_log(0, "ERROR - invalid method 0x%x\n", mad->method);
977                 return ACM_STATUS_EINVAL;
978         }
979
980         rec = (struct acm_resolve_rec *) mad->data;
981         if (!rec->src_type || rec->src_type >= ACM_ADDRESS_RESERVED) {
982                 acm_log(0, "ERROR - unknown src type 0x%x\n", rec->src_type);
983                 return ACM_STATUS_EINVAL;
984         }
985
986         return ACM_STATUS_SUCCESS;
987 }
988
989 static void
990 acm_send_addr_resp(struct acm_ep *ep, struct acm_dest *dest)
991 {
992         struct acm_resolve_rec *rec;
993         struct acm_send_msg *msg;
994         struct acm_mad *mad;
995
996         acm_log(2, "%s\n", dest->name);
997         msg = acm_alloc_send(ep, dest, sizeof (*mad));
998         if (!msg) {
999                 acm_log(0, "ERROR - failed to allocate message\n");
1000                 return;
1001         }
1002
1003         mad = (struct acm_mad *) msg->data;
1004         rec = (struct acm_resolve_rec *) mad->data;
1005
1006         mad->base_version = 1;
1007         mad->mgmt_class = ACM_MGMT_CLASS;
1008         mad->class_version = 1;
1009         mad->method = IB_METHOD_GET | IB_METHOD_RESP;
1010         mad->status = ACM_STATUS_SUCCESS;
1011         mad->control = ACM_CTRL_RESOLVE;
1012         mad->tid = dest->req_id;
1013         rec->gid_cnt = 1;
1014         memcpy(rec->gid, dest->mgid.raw, sizeof(union ibv_gid));
1015
1016         acm_post_send(&ep->resp_queue, msg);
1017 }
1018
1019 static int
1020 acm_client_resolve_resp(struct acm_client *client, struct acm_msg *req_msg,
1021         struct acm_dest *dest, uint8_t status)
1022 {
1023         struct acm_msg msg;
1024         int ret;
1025
1026         acm_log(2, "client %d, status 0x%x\n", client->index, status);
1027         memset(&msg, 0, sizeof msg);
1028
1029         if (status == ACM_STATUS_ENODATA)
1030                 atomic_inc(&counter[ACM_CNTR_NODATA]);
1031         else if (status)
1032                 atomic_inc(&counter[ACM_CNTR_ERROR]);
1033
1034         lock_acquire(&client->lock);
1035         if (client->sock == INVALID_SOCKET) {
1036                 acm_log(0, "ERROR - connection lost\n");
1037                 ret = ACM_STATUS_ENOTCONN;
1038                 goto release;
1039         }
1040
1041         msg.hdr = req_msg->hdr;
1042         msg.hdr.opcode |= ACM_OP_ACK;
1043         msg.hdr.status = status;
1044         msg.hdr.length = ACM_MSG_HDR_LENGTH;
1045         memset(msg.hdr.data, 0, sizeof(msg.hdr.data));
1046
1047         if (status == ACM_STATUS_SUCCESS) {
1048                 msg.hdr.length += ACM_MSG_EP_LENGTH;
1049                 msg.resolve_data[0].flags = IBV_PATH_FLAG_GMP |
1050                         IBV_PATH_FLAG_PRIMARY | IBV_PATH_FLAG_BIDIRECTIONAL;
1051                 msg.resolve_data[0].type = ACM_EP_INFO_PATH;
1052                 msg.resolve_data[0].info.path = dest->path;
1053
1054                 if (req_msg->hdr.src_out) {
1055                         msg.hdr.length += ACM_MSG_EP_LENGTH;
1056                         memcpy(&msg.resolve_data[1],
1057                                 &req_msg->resolve_data[req_msg->hdr.src_out],
1058                                 ACM_MSG_EP_LENGTH);
1059                 }
1060         }
1061
1062         ret = send(client->sock, (char *) &msg, msg.hdr.length, 0);
1063         if (ret != msg.hdr.length)
1064                 acm_log(0, "ERROR - failed to send response\n");
1065         else
1066                 ret = 0;
1067
1068 release:
1069         lock_release(&client->lock);
1070         return ret;
1071 }
1072
1073 static void
1074 acm_complete_queued_req(struct acm_dest *dest, uint8_t status)
1075 {
1076         struct acm_request *req;
1077         DLIST_ENTRY *entry;
1078
1079         acm_log(2, "status %d\n", status);
1080         lock_acquire(&dest->lock);
1081         while (!DListEmpty(&dest->req_queue)) {
1082                 entry = dest->req_queue.Next;
1083                 DListRemove(entry);
1084                 req = container_of(entry, struct acm_request, entry);
1085                 lock_release(&dest->lock);
1086
1087                 acm_log(2, "completing request, client %d\n", req->client->index);
1088                 acm_client_resolve_resp(req->client, &req->msg, dest, status);
1089                 acm_free_req(req);
1090
1091                 lock_acquire(&dest->lock);
1092         }
1093         lock_release(&dest->lock);
1094 }
1095
1096 static void
1097 acm_dest_sa_resp(struct acm_send_msg *msg, struct ibv_wc *wc, struct acm_mad *mad)
1098 {
1099         struct acm_dest *dest = (struct acm_dest *) msg->context;
1100         struct ib_sa_mad *sa_mad = (struct ib_sa_mad *) mad;
1101         uint8_t status;
1102
1103         if (mad) {
1104                 status = (uint8_t) (ntohs(mad->status) >> 8);
1105         } else {
1106                 status = ACM_STATUS_ETIMEDOUT;
1107         }
1108         acm_log(2, "%s status=0x%x\n", dest->name, status);
1109
1110         lock_acquire(&dest->lock);
1111         if (dest->state != ACM_QUERY_ROUTE) {
1112                 acm_log(1, "notice - discarding SA response\n");
1113                 lock_release(&dest->lock);
1114                 return;
1115         }
1116
1117         if (!status) {
1118                 memcpy(&dest->path, sa_mad->data, sizeof(dest->path));
1119                 acm_init_path_av(msg->ep->port, dest);
1120                 dest->addr_timeout = time_stamp_min() + (unsigned) addr_timeout;
1121                 dest->route_timeout = time_stamp_min() + (unsigned) route_timeout;
1122                 acm_log(2, "timeout addr %llu route %llu\n", dest->addr_timeout, dest->route_timeout);
1123                 dest->state = ACM_READY;
1124         } else {
1125                 dest->state = ACM_INIT;
1126         }
1127         lock_release(&dest->lock);
1128
1129         acm_complete_queued_req(dest, status);
1130 }
1131
1132 static void
1133 acm_resolve_sa_resp(struct acm_send_msg *msg, struct ibv_wc *wc, struct acm_mad *mad)
1134 {
1135         struct acm_dest *dest = (struct acm_dest *) msg->context;
1136         int send_resp;
1137
1138         acm_log(2, "\n");
1139         acm_dest_sa_resp(msg, wc, mad);
1140
1141         lock_acquire(&dest->lock);
1142         send_resp = (dest->state == ACM_READY);
1143         lock_release(&dest->lock);
1144
1145         if (send_resp)
1146                 acm_send_addr_resp(msg->ep, dest);
1147 }
1148
1149 static void
1150 acm_process_addr_req(struct acm_ep *ep, struct ibv_wc *wc, struct acm_mad *mad)
1151 {
1152         struct acm_resolve_rec *rec;
1153         struct acm_dest *dest;
1154         uint8_t status;
1155         int addr_index;
1156
1157         acm_log(2, "\n");
1158         if ((status = acm_validate_addr_req(mad))) {
1159                 acm_log(0, "ERROR - invalid request\n");
1160                 return;
1161         }
1162
1163         rec = (struct acm_resolve_rec *) mad->data;
1164         dest = acm_acquire_dest(ep, rec->src_type, rec->src);
1165         if (!dest) {
1166                 acm_log(0, "ERROR - unable to add source\n");
1167                 return;
1168         }
1169         
1170         addr_index = acm_addr_index(ep, rec->dest, rec->dest_type);
1171         if (addr_index >= 0)
1172                 dest->req_id = mad->tid;
1173
1174         lock_acquire(&dest->lock);
1175         acm_log(2, "dest state %d\n", dest->state);
1176         switch (dest->state) {
1177         case ACM_READY:
1178                 if (dest->remote_qpn == wc->src_qp)
1179                         break;
1180
1181                 acm_log(2, "src service has new qp, resetting\n");
1182                 /* fall through */
1183         case ACM_INIT:
1184         case ACM_QUERY_ADDR:
1185                 status = acm_record_acm_addr(ep, dest, wc, rec);
1186                 if (status)
1187                         break;
1188                 /* fall through */
1189         case ACM_ADDR_RESOLVED:
1190                 if (route_prot == ACM_ROUTE_PROT_ACM) {
1191                         status = acm_record_acm_route(ep, dest);
1192                         break;
1193                 }
1194                 if (addr_index >= 0 || !DListEmpty(&dest->req_queue)) {
1195                         status = acm_resolve_path(ep, dest, acm_resolve_sa_resp);
1196                         if (status)
1197                                 break;
1198                 }
1199                 /* fall through */
1200         default:
1201                 lock_release(&dest->lock);
1202                 acm_put_dest(dest);
1203                 return;
1204         }
1205         lock_release(&dest->lock);
1206         acm_complete_queued_req(dest, status);
1207
1208         if (addr_index >= 0 && !status) {
1209                 acm_send_addr_resp(ep, dest);
1210         }
1211         acm_put_dest(dest);
1212 }
1213
1214 static void
1215 acm_process_addr_resp(struct acm_send_msg *msg, struct ibv_wc *wc, struct acm_mad *mad)
1216 {
1217         struct acm_resolve_rec *resp_rec;
1218         struct acm_dest *dest = (struct acm_dest *) msg->context;
1219         uint8_t status;
1220
1221         if (mad) {
1222                 status = acm_class_status(mad->status);
1223                 resp_rec = (struct acm_resolve_rec *) mad->data;
1224         } else {
1225                 status = ACM_STATUS_ETIMEDOUT;
1226                 resp_rec = NULL;
1227         }
1228         acm_log(2, "resp status 0x%x\n", status);
1229
1230         lock_acquire(&dest->lock);
1231         if (dest->state != ACM_QUERY_ADDR) {
1232                 lock_release(&dest->lock);
1233                 goto put;
1234         }
1235
1236         if (!status) {
1237                 status = acm_record_acm_addr(msg->ep, dest, wc, resp_rec);
1238                 if (!status) {
1239                         if (route_prot == ACM_ROUTE_PROT_ACM) {
1240                                 status = acm_record_acm_route(msg->ep, dest);
1241                         } else {
1242                                 status = acm_resolve_path(msg->ep, dest, acm_dest_sa_resp);
1243                                 if (!status) {
1244                                         lock_release(&dest->lock);
1245                                         goto put;
1246                                 }
1247                         }
1248                 }
1249         } else {
1250                 dest->state = ACM_INIT;
1251         }
1252         lock_release(&dest->lock);
1253
1254         acm_complete_queued_req(dest, status);
1255 put:
1256         acm_put_dest(dest);
1257 }
1258
1259 static void acm_process_acm_recv(struct acm_ep *ep, struct ibv_wc *wc, struct acm_mad *mad)
1260 {
1261         struct acm_send_msg *req;
1262         struct acm_resolve_rec *rec;
1263         int free;
1264
1265         acm_log(2, "\n");
1266         if (mad->base_version != 1 || mad->class_version != 1) {
1267                 acm_log(0, "ERROR - invalid version %d %d\n",
1268                         mad->base_version, mad->class_version);
1269                 return;
1270         }
1271         
1272         if (mad->control != ACM_CTRL_RESOLVE) {
1273                 acm_log(0, "ERROR - invalid control 0x%x\n", mad->control);
1274                 return;
1275         }
1276
1277         rec = (struct acm_resolve_rec *) mad->data;
1278         acm_format_name(2, log_data, sizeof log_data,
1279                         rec->src_type, rec->src, sizeof rec->src);
1280         acm_log(2, "src  %s\n", log_data);
1281         acm_format_name(2, log_data, sizeof log_data,
1282                         rec->dest_type, rec->dest, sizeof rec->dest);
1283         acm_log(2, "dest %s\n", log_data);
1284         if (mad->method & IB_METHOD_RESP) {
1285                 acm_log(2, "received response\n");
1286                 req = acm_get_request(ep, mad->tid, &free);
1287                 if (!req) {
1288                         acm_log(1, "notice - response did not match active request\n");
1289                         return;
1290                 }
1291                 acm_log(2, "found matching request\n");
1292                 req->resp_handler(req, wc, mad);
1293                 if (free)
1294                         acm_free_send(req);
1295         } else {
1296                 acm_log(2, "unsolicited request\n");
1297                 acm_process_addr_req(ep, wc, mad);
1298         }
1299 }
1300
1301 static int
1302 acm_client_query_resp(struct acm_client *client,
1303         struct acm_msg *msg, uint8_t status)
1304 {
1305         int ret;
1306
1307         acm_log(2, "status 0x%x\n", status);
1308         lock_acquire(&client->lock);
1309         if (client->sock == INVALID_SOCKET) {
1310                 acm_log(0, "ERROR - connection lost\n");
1311                 ret = ACM_STATUS_ENOTCONN;
1312                 goto release;
1313         }
1314
1315         msg->hdr.opcode |= ACM_OP_ACK;
1316         msg->hdr.status = status;
1317
1318         ret = send(client->sock, (char *) msg, msg->hdr.length, 0);
1319         if (ret != msg->hdr.length)
1320                 acm_log(0, "ERROR - failed to send response\n");
1321         else
1322                 ret = 0;
1323
1324 release:
1325         lock_release(&client->lock);
1326         return ret;
1327 }
1328
1329 static void
1330 acm_client_sa_resp(struct acm_send_msg *msg, struct ibv_wc *wc, struct acm_mad *mad)
1331 {
1332         struct acm_request *req = (struct acm_request *) msg->context;
1333         struct ib_sa_mad *sa_mad = (struct ib_sa_mad *) mad;
1334         uint8_t status;
1335
1336         if (mad) {
1337                 status = (uint8_t) (ntohs(sa_mad->status) >> 8);
1338                 memcpy(&req->msg.resolve_data[0].info.path, sa_mad->data,
1339                         sizeof(struct ibv_path_record));
1340         } else {
1341                 status = ACM_STATUS_ETIMEDOUT;
1342         }
1343         acm_log(2, "status 0x%x\n", status);
1344
1345         acm_client_query_resp(req->client, &req->msg, status);
1346         acm_free_req(req);
1347 }
1348
1349 static void acm_process_sa_recv(struct acm_ep *ep, struct ibv_wc *wc, struct acm_mad *mad)
1350 {
1351         struct ib_sa_mad *sa_mad = (struct ib_sa_mad *) mad;
1352         struct acm_send_msg *req;
1353         int free;
1354
1355         acm_log(2, "\n");
1356         if (mad->base_version != 1 || mad->class_version != 2 ||
1357             !(mad->method & IB_METHOD_RESP) || sa_mad->attr_id != IB_SA_ATTR_PATH_REC) {
1358                 acm_log(0, "ERROR - unexpected SA MAD %d %d\n",
1359                         mad->base_version, mad->class_version);
1360                 return;
1361         }
1362         
1363         req = acm_get_request(ep, mad->tid, &free);
1364         if (!req) {
1365                 acm_log(1, "notice - response did not match active request\n");
1366                 return;
1367         }
1368         acm_log(2, "found matching request\n");
1369         req->resp_handler(req, wc, mad);
1370         if (free)
1371                 acm_free_send(req);
1372 }
1373
1374 static void acm_process_recv(struct acm_ep *ep, struct ibv_wc *wc)
1375 {
1376         struct acm_mad *mad;
1377
1378         acm_log(2, "base endpoint name %s\n", ep->name[0]);
1379         mad = (struct acm_mad *) (uintptr_t) (wc->wr_id + sizeof(struct ibv_grh));
1380         switch (mad->mgmt_class) {
1381         case IB_MGMT_CLASS_SA:
1382                 acm_process_sa_recv(ep, wc, mad);
1383                 break;
1384         case ACM_MGMT_CLASS:
1385                 acm_process_acm_recv(ep, wc, mad);
1386                 break;
1387         default:
1388                 acm_log(0, "ERROR - invalid mgmt class 0x%x\n", mad->mgmt_class);
1389                 break;
1390         }
1391
1392         acm_post_recv(ep, wc->wr_id);
1393 }
1394
1395 static void acm_process_comp(struct acm_ep *ep, struct ibv_wc *wc)
1396 {
1397         if (wc->status) {
1398                 acm_log(0, "ERROR - work completion error\n"
1399                         "\topcode %d, completion status %d\n",
1400                         wc->opcode, wc->status);
1401                 return;
1402         }
1403
1404         if (wc->opcode & IBV_WC_RECV)
1405                 acm_process_recv(ep, wc);
1406         else
1407                 acm_complete_send((struct acm_send_msg *) (uintptr_t) wc->wr_id);
1408 }
1409
1410 static void CDECL_FUNC acm_comp_handler(void *context)
1411 {
1412         struct acm_device *dev = (struct acm_device *) context;
1413         struct acm_ep *ep;
1414         struct ibv_cq *cq;
1415         struct ibv_wc wc;
1416         int cnt;
1417
1418         acm_log(1, "started\n");
1419         while (1) {
1420                 ibv_get_cq_event(dev->channel, &cq, (void *) &ep);
1421
1422                 cnt = 0;
1423                 while (ibv_poll_cq(cq, 1, &wc) > 0) {
1424                         cnt++;
1425                         acm_process_comp(ep, &wc);
1426                 }
1427
1428                 ibv_req_notify_cq(cq, 0);
1429                 while (ibv_poll_cq(cq, 1, &wc) > 0) {
1430                         cnt++;
1431                         acm_process_comp(ep, &wc);
1432                 }
1433
1434                 ibv_ack_cq_events(cq, cnt);
1435         }
1436 }
1437
1438 static void acm_format_mgid(union ibv_gid *mgid, uint16_t pkey, uint8_t tos,
1439         uint8_t rate, uint8_t mtu)
1440 {
1441         mgid->raw[0] = 0xFF;
1442         mgid->raw[1] = 0x10 | 0x05;
1443         mgid->raw[2] = 0x40;
1444         mgid->raw[3] = 0x01;
1445         mgid->raw[4] = (uint8_t) (pkey >> 8);
1446         mgid->raw[5] = (uint8_t) pkey;
1447         mgid->raw[6] = tos;
1448         mgid->raw[7] = rate;
1449         mgid->raw[8] = mtu;
1450         mgid->raw[9] = 0;
1451         mgid->raw[10] = 0;
1452         mgid->raw[11] = 0;
1453         mgid->raw[12] = 0;
1454         mgid->raw[13] = 0;
1455         mgid->raw[14] = 0;
1456         mgid->raw[15] = 0;
1457 }
1458
1459 static void acm_init_join(struct ib_sa_mad *mad, union ibv_gid *port_gid,
1460         uint16_t pkey, uint8_t tos, uint8_t tclass, uint8_t sl, uint8_t rate, uint8_t mtu)
1461 {
1462         struct ib_mc_member_rec *mc_rec;
1463
1464         acm_log(2, "\n");
1465         mad->base_version = 1;
1466         mad->mgmt_class = IB_MGMT_CLASS_SA;
1467         mad->class_version = 2;
1468         mad->method = IB_METHOD_SET;
1469         mad->tid = (uint64_t) atomic_inc(&tid);
1470         mad->attr_id = IB_SA_ATTR_MC_MEMBER_REC;
1471         mad->comp_mask =
1472                 IB_COMP_MASK_MC_MGID | IB_COMP_MASK_MC_PORT_GID |
1473                 IB_COMP_MASK_MC_QKEY | IB_COMP_MASK_MC_MTU_SEL| IB_COMP_MASK_MC_MTU |
1474                 IB_COMP_MASK_MC_TCLASS | IB_COMP_MASK_MC_PKEY | IB_COMP_MASK_MC_RATE_SEL |
1475                 IB_COMP_MASK_MC_RATE | IB_COMP_MASK_MC_SL | IB_COMP_MASK_MC_FLOW |
1476                 IB_COMP_MASK_MC_SCOPE | IB_COMP_MASK_MC_JOIN_STATE;
1477
1478         mc_rec = (struct ib_mc_member_rec *) mad->data;
1479         acm_format_mgid(&mc_rec->mgid, pkey, tos, rate, mtu);
1480         mc_rec->port_gid = *port_gid;
1481         mc_rec->qkey = ACM_QKEY;
1482         mc_rec->mtu = 0x80 | mtu;
1483         mc_rec->tclass = tclass;
1484         mc_rec->pkey = htons(pkey);
1485         mc_rec->rate = 0x80 | rate;
1486         mc_rec->sl_flow_hop = htonl(((uint32_t) sl) << 28);
1487         mc_rec->scope_state = 0x51;
1488 }
1489
1490 static void acm_join_group(struct acm_ep *ep, union ibv_gid *port_gid,
1491         uint8_t tos, uint8_t tclass, uint8_t sl, uint8_t rate, uint8_t mtu)
1492 {
1493         struct acm_port *port;
1494         struct ib_sa_mad *mad;
1495         struct ib_user_mad *umad;
1496         struct ib_mc_member_rec *mc_rec;
1497         int ret, len;
1498
1499         acm_log(2, "\n");
1500         len = sizeof(*umad) + sizeof(*mad);
1501         umad = (struct ib_user_mad *) calloc(1, len);
1502         if (!umad) {
1503                 acm_log(0, "ERROR - unable to allocate MAD for join\n");
1504                 return;
1505         }
1506
1507         port = ep->port;
1508         umad->addr.qpn = htonl(port->sa_dest.remote_qpn);
1509         umad->addr.qkey = htonl(ACM_QKEY);
1510         umad->addr.pkey_index = ep->pkey_index;
1511         umad->addr.lid = htons(port->sa_dest.av.dlid);
1512         umad->addr.sl = port->sa_dest.av.sl;
1513         umad->addr.path_bits = port->sa_dest.av.src_path_bits;
1514
1515         acm_log(0, "%s %d pkey 0x%x, sl 0x%x, rate 0x%x, mtu 0x%x\n",
1516                 ep->port->dev->verbs->device->name, ep->port->port_num,
1517                 ep->pkey, sl, rate, mtu);
1518         mad = (struct ib_sa_mad *) umad->data;
1519         acm_init_join(mad, port_gid, ep->pkey, tos, tclass, sl, rate, mtu);
1520         mc_rec = (struct ib_mc_member_rec *) mad->data;
1521         acm_set_dest_addr(&ep->mc_dest[ep->mc_cnt++], ACM_ADDRESS_GID,
1522                 mc_rec->mgid.raw, sizeof(mc_rec->mgid));
1523
1524         ret = umad_send(port->mad_portid, port->mad_agentid, (void *) umad,
1525                 sizeof(*mad), timeout, retries);
1526         if (ret) {
1527                 acm_log(0, "ERROR - failed to send multicast join request %d\n", ret);
1528                 goto out;
1529         }
1530
1531         acm_log(1, "waiting for response from SA to join request\n");
1532         ret = umad_recv(port->mad_portid, (void *) umad, &len, -1);
1533         if (ret < 0) {
1534                 acm_log(0, "ERROR - recv error for multicast join response %d\n", ret);
1535                 goto out;
1536         }
1537
1538         acm_process_join_resp(ep, umad);
1539 out:
1540         free(umad);
1541 }
1542
1543 static void acm_port_join(struct acm_port *port)
1544 {
1545         struct acm_device *dev;
1546         struct acm_ep *ep;
1547         union ibv_gid port_gid;
1548         DLIST_ENTRY *ep_entry;
1549         int ret;
1550
1551         dev = port->dev;
1552         acm_log(1, "device %s port %d\n", dev->verbs->device->name,
1553                 port->port_num);
1554
1555         ret = ibv_query_gid(dev->verbs, port->port_num, 0, &port_gid);
1556         if (ret) {
1557                 acm_log(0, "ERROR - ibv_query_gid %d device %s port %d\n",
1558                         ret, dev->verbs->device->name, port->port_num);
1559                 return;
1560         }
1561
1562         for (ep_entry = port->ep_list.Next; ep_entry != &port->ep_list;
1563                  ep_entry = ep_entry->Next) {
1564
1565                 ep = container_of(ep_entry, struct acm_ep, entry);
1566                 ep->mc_cnt = 0;
1567                 acm_join_group(ep, &port_gid, 0, 0, 0, min_rate, min_mtu);
1568
1569                 if ((ep->state = ep->mc_dest[0].state) != ACM_READY)
1570                         continue;
1571
1572                 if ((route_prot == ACM_ROUTE_PROT_ACM) &&
1573                     (port->rate != min_rate || port->mtu != min_mtu))
1574                         acm_join_group(ep, &port_gid, 0, 0, 0, port->rate, port->mtu);
1575         }
1576         acm_log(1, "joins for device %s port %d complete\n", dev->verbs->device->name,
1577                 port->port_num);
1578 }
1579
1580 static void acm_process_timeouts(void)
1581 {
1582         DLIST_ENTRY *entry;
1583         struct acm_send_msg *msg;
1584         struct acm_resolve_rec *rec;
1585         
1586         while (!DListEmpty(&timeout_list)) {
1587                 entry = timeout_list.Next;
1588                 DListRemove(entry);
1589
1590                 msg = container_of(entry, struct acm_send_msg, entry);
1591                 rec = (struct acm_resolve_rec *) ((struct acm_mad *) msg->data)->data;
1592
1593                 acm_format_name(0, log_data, sizeof log_data,
1594                                 rec->dest_type, rec->dest, sizeof rec->dest);
1595                 acm_log(0, "notice - dest %s\n", log_data);
1596                 msg->resp_handler(msg, NULL, NULL);
1597         }
1598 }
1599
1600 static void acm_process_wait_queue(struct acm_ep *ep, uint64_t *next_expire)
1601 {
1602         struct acm_send_msg *msg;
1603         DLIST_ENTRY *entry, *next;
1604         struct ibv_send_wr *bad_wr;
1605
1606         for (entry = ep->wait_queue.Next; entry != &ep->wait_queue; entry = next) {
1607                 next = entry->Next;
1608                 msg = container_of(entry, struct acm_send_msg, entry);
1609                 if (msg->expires < time_stamp_ms()) {
1610                         DListRemove(entry);
1611                         (void) atomic_dec(&wait_cnt);
1612                         if (--msg->tries) {
1613                                 acm_log(1, "notice - retrying request\n");
1614                                 DListInsertTail(&msg->entry, &ep->active_queue);
1615                                 ibv_post_send(ep->qp, &msg->wr, &bad_wr);
1616                         } else {
1617                                 acm_log(0, "notice - failing request\n");
1618                                 acm_send_available(ep, msg->req_queue);
1619                                 DListInsertTail(&msg->entry, &timeout_list);
1620                         }
1621                 } else {
1622                         *next_expire = min(*next_expire, msg->expires);
1623                         break;
1624                 }
1625         }
1626 }
1627
1628 static void CDECL_FUNC acm_retry_handler(void *context)
1629 {
1630         struct acm_device *dev;
1631         struct acm_port *port;
1632         struct acm_ep *ep;
1633         DLIST_ENTRY *dev_entry, *ep_entry;
1634         uint64_t next_expire;
1635         int i, wait;
1636
1637         acm_log(0, "started\n");
1638         while (1) {
1639                 while (!atomic_get(&wait_cnt))
1640                         event_wait(&timeout_event, -1);
1641
1642                 next_expire = -1;
1643                 for (dev_entry = dev_list.Next; dev_entry != &dev_list;
1644                          dev_entry = dev_entry->Next) {
1645
1646                         dev = container_of(dev_entry, struct acm_device, entry);
1647
1648                         for (i = 0; i < dev->port_cnt; i++) {
1649                                 port = &dev->port[i];
1650
1651                                 for (ep_entry = port->ep_list.Next;
1652                                          ep_entry != &port->ep_list;
1653                                          ep_entry = ep_entry->Next) {
1654
1655                                         ep = container_of(ep_entry, struct acm_ep, entry);
1656                                         lock_acquire(&ep->lock);
1657                                         if (!DListEmpty(&ep->wait_queue))
1658                                                 acm_process_wait_queue(ep, &next_expire);
1659                                         lock_release(&ep->lock);
1660                                 }
1661                         }
1662                 }
1663
1664                 acm_process_timeouts();
1665                 wait = (int) (next_expire - time_stamp_ms());
1666                 if (wait > 0 && atomic_get(&wait_cnt))
1667                         event_wait(&timeout_event, wait);
1668         }
1669 }
1670
1671 static void acm_init_server(void)
1672 {
1673         FILE *f;
1674         int i;
1675
1676         for (i = 0; i < FD_SETSIZE - 1; i++) {
1677                 lock_init(&client[i].lock);
1678                 client[i].index = i;
1679                 client[i].sock = INVALID_SOCKET;
1680                 atomic_init(&client[i].refcnt);
1681         }
1682
1683         if (!(f = fopen("/var/run/ibacm.port", "w"))) {
1684                 acm_log(0, "notice - cannot publish ibacm port number\n");
1685                 return;
1686         }
1687         fprintf(f, "%hu\n", server_port);
1688         fclose(f);
1689 }
1690
1691 static int acm_listen(void)
1692 {
1693         struct sockaddr_in addr;
1694         int ret;
1695
1696         acm_log(2, "\n");
1697         listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1698         if (listen_socket == INVALID_SOCKET) {
1699                 acm_log(0, "ERROR - unable to allocate listen socket\n");
1700                 return socket_errno();
1701         }
1702
1703         memset(&addr, 0, sizeof addr);
1704         addr.sin_family = AF_INET;
1705         addr.sin_port = htons(server_port);
1706         ret = bind(listen_socket, (struct sockaddr *) &addr, sizeof addr);
1707         if (ret == SOCKET_ERROR) {
1708                 acm_log(0, "ERROR - unable to bind listen socket\n");
1709                 return socket_errno();
1710         }
1711         
1712         ret = listen(listen_socket, 0);
1713         if (ret == SOCKET_ERROR) {
1714                 acm_log(0, "ERROR - unable to start listen\n");
1715                 return socket_errno();
1716         }
1717
1718         acm_log(2, "listen active\n");
1719         return 0;
1720 }
1721
1722 static void acm_disconnect_client(struct acm_client *client)
1723 {
1724         lock_acquire(&client->lock);
1725         shutdown(client->sock, SHUT_RDWR);
1726         closesocket(client->sock);
1727         client->sock = INVALID_SOCKET;
1728         lock_release(&client->lock);
1729         (void) atomic_dec(&client->refcnt);
1730 }
1731
1732 static void acm_svr_accept(void)
1733 {
1734         SOCKET s;
1735         int i;
1736
1737         acm_log(2, "\n");
1738         s = accept(listen_socket, NULL, NULL);
1739         if (s == INVALID_SOCKET) {
1740                 acm_log(0, "ERROR - failed to accept connection\n");
1741                 return;
1742         }
1743
1744         for (i = 0; i < FD_SETSIZE - 1; i++) {
1745                 if (!atomic_get(&client[i].refcnt))
1746                         break;
1747         }
1748
1749         if (i == FD_SETSIZE - 1) {
1750                 acm_log(0, "ERROR - all connections busy - rejecting\n");
1751                 closesocket(s);
1752                 return;
1753         }
1754
1755         client[i].sock = s;
1756         atomic_set(&client[i].refcnt, 1);
1757         acm_log(2, "assigned client %d\n", i);
1758 }
1759
1760 static int
1761 acm_is_path_from_port(struct acm_port *port, struct ibv_path_record *path)
1762 {
1763         union ibv_gid gid;
1764         uint8_t i;
1765
1766         if (!ib_any_gid(&path->sgid)) {
1767                 return (acm_gid_index(port, &path->sgid) < port->gid_cnt);
1768         }
1769
1770         if (path->slid) {
1771                 return (port->lid == (ntohs(path->slid) & port->lid_mask));
1772         }
1773
1774         if (ib_any_gid(&path->dgid)) {
1775                 return 1;
1776         }
1777
1778         if (acm_gid_index(port, &path->dgid) < port->gid_cnt) {
1779                 return 1;
1780         }
1781
1782         for (i = 0; i < port->gid_cnt; i++) {
1783                 ibv_query_gid(port->dev->verbs, port->port_num, i, &gid);
1784                 if (gid.global.subnet_prefix == path->dgid.global.subnet_prefix) {
1785                         return 1;
1786                 }
1787         }
1788
1789         return 0;
1790 }
1791
1792 static struct acm_ep *
1793 acm_get_port_ep(struct acm_port *port, struct acm_ep_addr_data *data)
1794 {
1795         struct acm_ep *ep;
1796         DLIST_ENTRY *ep_entry;
1797
1798         if (port->state != IBV_PORT_ACTIVE)
1799                 return NULL;
1800
1801         if (data->type == ACM_EP_INFO_PATH &&
1802             !acm_is_path_from_port(port, &data->info.path))
1803                 return NULL;
1804
1805         for (ep_entry = port->ep_list.Next; ep_entry != &port->ep_list;
1806                  ep_entry = ep_entry->Next) {
1807
1808                 ep = container_of(ep_entry, struct acm_ep, entry);
1809                 if (ep->state != ACM_READY)
1810                         continue;
1811
1812                 if ((data->type == ACM_EP_INFO_PATH) &&
1813                     (!data->info.path.pkey || (ntohs(data->info.path.pkey) == ep->pkey)))
1814                         return ep;
1815
1816                 if (acm_addr_index(ep, data->info.addr, (uint8_t) data->type) >= 0)
1817                         return ep;
1818         }
1819
1820         return NULL;
1821 }
1822
1823 static struct acm_ep *
1824 acm_get_ep(struct acm_ep_addr_data *data)
1825 {
1826         struct acm_device *dev;
1827         struct acm_ep *ep;
1828         DLIST_ENTRY *dev_entry;
1829         int i;
1830
1831         acm_format_name(2, log_data, sizeof log_data,
1832                         data->type, data->info.addr, sizeof data->info.addr);
1833         acm_log(2, "%s\n", log_data);
1834         for (dev_entry = dev_list.Next; dev_entry != &dev_list;
1835                  dev_entry = dev_entry->Next) {
1836
1837                 dev = container_of(dev_entry, struct acm_device, entry);
1838                 for (i = 0; i < dev->port_cnt; i++) {
1839                         lock_acquire(&dev->port[i].lock);
1840                         ep = acm_get_port_ep(&dev->port[i], data);
1841                         lock_release(&dev->port[i].lock);
1842                         if (ep)
1843                                 return ep;
1844                 }
1845         }
1846
1847         acm_format_name(0, log_data, sizeof log_data,
1848                         data->type, data->info.addr, sizeof data->info.addr);
1849         acm_log(1, "notice - could not find %s\n", log_data);
1850         return NULL;
1851 }
1852
1853 static int
1854 acm_svr_query_path(struct acm_client *client, struct acm_msg *msg)
1855 {
1856         struct acm_request *req;
1857         struct acm_send_msg *sa_msg;
1858         struct ib_sa_mad *mad;
1859         struct acm_ep *ep;
1860         uint8_t status;
1861
1862         acm_log(2, "client %d\n", client->index);
1863         if (msg->hdr.length != ACM_MSG_HDR_LENGTH + ACM_MSG_EP_LENGTH) {
1864                 acm_log(0, "ERROR - invalid length: 0x%x\n", msg->hdr.length);
1865                 status = ACM_STATUS_EINVAL;
1866                 goto resp;
1867         }
1868
1869         ep = acm_get_ep(&msg->resolve_data[0]);
1870         if (!ep) {
1871                 acm_log(1, "notice - could not find local end point\n");
1872                 status = ACM_STATUS_ESRCADDR;
1873                 goto resp;
1874         }
1875
1876         req = acm_alloc_req(client, msg);
1877         if (!req) {
1878                 status = ACM_STATUS_ENOMEM;
1879                 goto resp;
1880         }
1881
1882         if (!acm_acquire_sa_dest(ep->port)) {
1883                 acm_log(1, "cannot acquire SA destination\n");
1884                 status = ACM_STATUS_EINVAL;
1885                 goto free;
1886         }
1887
1888         sa_msg = acm_alloc_send(ep, &ep->port->sa_dest, sizeof(*mad));
1889         acm_release_sa_dest(&ep->port->sa_dest);
1890         if (!sa_msg) {
1891                 acm_log(0, "ERROR - cannot allocate send msg\n");
1892                 status = ACM_STATUS_ENOMEM;
1893                 goto free;
1894         }
1895
1896         acm_init_send_req(sa_msg, (void *) req, acm_client_sa_resp);
1897         mad = (struct ib_sa_mad *) sa_msg->data;
1898         acm_init_path_query(mad);
1899
1900         memcpy(mad->data, &msg->resolve_data[0].info.path,
1901                 sizeof(struct ibv_path_record));
1902         mad->comp_mask = acm_path_comp_mask(&msg->resolve_data[0].info.path);
1903
1904         atomic_inc(&counter[ACM_CNTR_ROUTE_QUERY]);
1905         acm_post_send(&ep->sa_queue, sa_msg);
1906         return ACM_STATUS_SUCCESS;
1907
1908 free:
1909         acm_free_req(req);
1910 resp:
1911         return acm_client_query_resp(client, msg, status);
1912 }
1913
1914 static uint8_t
1915 acm_send_resolve(struct acm_ep *ep, struct acm_dest *dest,
1916         struct acm_ep_addr_data *saddr)
1917 {
1918         struct acm_send_msg *msg;
1919         struct acm_mad *mad;
1920         struct acm_resolve_rec *rec;
1921         int i;
1922
1923         acm_log(2, "\n");
1924         msg = acm_alloc_send(ep, &ep->mc_dest[0], sizeof(*mad));
1925         if (!msg) {
1926                 acm_log(0, "ERROR - cannot allocate send msg\n");
1927                 return ACM_STATUS_ENOMEM;
1928         }
1929
1930         acm_init_send_req(msg, (void *) dest, acm_process_addr_resp);
1931         (void) atomic_inc(&dest->refcnt);
1932
1933         mad = (struct acm_mad *) msg->data;
1934         mad->base_version = 1;
1935         mad->mgmt_class = ACM_MGMT_CLASS;
1936         mad->class_version = 1;
1937         mad->method = IB_METHOD_GET;
1938         mad->control = ACM_CTRL_RESOLVE;
1939         mad->tid = (uint64_t) atomic_inc(&tid);
1940
1941         rec = (struct acm_resolve_rec *) mad->data;
1942         rec->src_type = (uint8_t) saddr->type;
1943         rec->src_length = ACM_MAX_ADDRESS;
1944         memcpy(rec->src, saddr->info.addr, ACM_MAX_ADDRESS);
1945         rec->dest_type = dest->addr_type;
1946         rec->dest_length = ACM_MAX_ADDRESS;
1947         memcpy(rec->dest, dest->address, ACM_MAX_ADDRESS);
1948
1949         rec->gid_cnt = (uint8_t) ep->mc_cnt;
1950         for (i = 0; i < ep->mc_cnt; i++)
1951                 memcpy(&rec->gid[i], ep->mc_dest[i].address, 16);
1952         
1953         atomic_inc(&counter[ACM_CNTR_ADDR_QUERY]);
1954         acm_post_send(&ep->resolve_queue, msg);
1955         return 0;
1956 }
1957
1958 static int acm_svr_select_src(struct acm_ep_addr_data *src, struct acm_ep_addr_data *dst)
1959 {
1960         union socket_addr addr;
1961         socklen_t len;
1962         int ret;
1963         SOCKET s;
1964
1965         if (src->type)
1966                 return 0;
1967
1968         acm_log(2, "selecting source address\n");
1969         memset(&addr, 0, sizeof addr);
1970         switch (dst->type) {
1971         case ACM_EP_INFO_ADDRESS_IP:
1972                 addr.sin.sin_family = AF_INET;
1973                 memcpy(&addr.sin.sin_addr, dst->info.addr, 4);
1974                 len = sizeof(struct sockaddr_in);
1975                 break;
1976         case ACM_EP_INFO_ADDRESS_IP6:
1977                 addr.sin6.sin6_family = AF_INET6;
1978                 memcpy(&addr.sin6.sin6_addr, dst->info.addr, 16);
1979                 len = sizeof(struct sockaddr_in6);
1980                 break;
1981         default:
1982                 acm_log(1, "notice - bad destination type, cannot lookup source\n");
1983                 return ACM_STATUS_EDESTTYPE;
1984         }
1985
1986         s = socket(addr.sa.sa_family, SOCK_DGRAM, IPPROTO_UDP);
1987         if (s == INVALID_SOCKET) {
1988                 acm_log(0, "ERROR - unable to allocate socket\n");
1989                 return socket_errno();
1990         }
1991
1992         ret = connect(s, &addr.sa, len);
1993         if (ret) {
1994                 acm_log(0, "ERROR - unable to connect socket\n");
1995                 ret = socket_errno();
1996                 goto out;
1997         }
1998
1999         ret = getsockname(s, &addr.sa, &len);
2000         if (ret) {
2001                 acm_log(0, "ERROR - failed to get socket address\n");
2002                 ret = socket_errno();
2003                 goto out;
2004         }
2005
2006         src->type = dst->type;
2007         src->flags = ACM_EP_FLAG_SOURCE;
2008         if (dst->type == ACM_EP_INFO_ADDRESS_IP) {
2009                 memcpy(&src->info.addr, &addr.sin.sin_addr, 4);
2010         } else {
2011                 memcpy(&src->info.addr, &addr.sin6.sin6_addr, 16);
2012         }
2013 out:
2014         close(s);
2015         return ret;
2016 }
2017
2018 /*
2019  * Verify the resolve message from the client and return
2020  * references to the source and destination addresses.
2021  * The message buffer contains extra address data buffers.  If a
2022  * source address is not given, reference an empty address buffer,
2023  * and we'll resolve a source address later.
2024  */
2025 static uint8_t
2026 acm_svr_verify_resolve(struct acm_msg *msg,
2027         struct acm_ep_addr_data **saddr, struct acm_ep_addr_data **daddr)
2028 {
2029         struct acm_ep_addr_data *src = NULL, *dst = NULL;
2030         int i, cnt;
2031
2032         if (msg->hdr.length < ACM_MSG_HDR_LENGTH) {
2033                 acm_log(0, "ERROR - invalid msg hdr length %d\n", msg->hdr.length);
2034                 return ACM_STATUS_EINVAL;
2035         }
2036
2037         cnt = (msg->hdr.length - ACM_MSG_HDR_LENGTH) / ACM_MSG_EP_LENGTH;
2038         for (i = 0; i < cnt; i++) {
2039                 if (msg->resolve_data[i].flags & ACM_EP_FLAG_SOURCE) {
2040                         if (src) {
2041                                 acm_log(0, "ERROR - multiple sources specified\n");
2042                                 return ACM_STATUS_ESRCADDR;
2043                         }
2044                         if (!msg->resolve_data[i].type ||
2045                             (msg->resolve_data[i].type >= ACM_ADDRESS_RESERVED)) {
2046                                 acm_log(0, "ERROR - unsupported source address type\n");
2047                                 return ACM_STATUS_ESRCTYPE;
2048                         }
2049                         src = &msg->resolve_data[i];
2050                 }
2051                 if (msg->resolve_data[i].flags & ACM_EP_FLAG_DEST) {
2052                         if (dst) {
2053                                 acm_log(0, "ERROR - multiple destinations specified\n");
2054                                 return ACM_STATUS_EDESTADDR;
2055                         }
2056                         if (!msg->resolve_data[i].type ||
2057                             (msg->resolve_data[i].type >= ACM_ADDRESS_RESERVED)) {
2058                                 acm_log(0, "ERROR - unsupported destination address type\n");
2059                                 return ACM_STATUS_EDESTTYPE;
2060                         }
2061                         dst = &msg->resolve_data[i];
2062                 }
2063         }
2064
2065         if (!dst) {
2066                 acm_log(0, "ERROR - destination address required\n");
2067                 return ACM_STATUS_EDESTTYPE;
2068         }
2069
2070         if (!src) {
2071                 msg->hdr.src_out = i;
2072                 src = &msg->resolve_data[i];
2073                 memset(src, 0, sizeof *src);
2074         }
2075         *saddr = src;
2076         *daddr = dst;
2077         return ACM_STATUS_SUCCESS;
2078 }
2079
2080 /* Caller must hold dest lock */
2081 static uint8_t
2082 acm_svr_queue_req(struct acm_dest *dest, struct acm_client *client,
2083         struct acm_msg *msg)
2084 {
2085         struct acm_request *req;
2086
2087         acm_log(2, "client %d\n", client->index);
2088         req = acm_alloc_req(client, msg);
2089         if (!req) {
2090                 return ACM_STATUS_ENOMEM;
2091         }
2092
2093         DListInsertTail(&req->entry, &dest->req_queue);
2094         return ACM_STATUS_SUCCESS;
2095 }
2096
2097 static int acm_dest_timeout(struct acm_dest *dest)
2098 {
2099         uint64_t timestamp = time_stamp_min();
2100
2101         if (timestamp > dest->addr_timeout) {
2102                 acm_log(2, "%s address timed out\n", dest->name);
2103                 dest->state = ACM_INIT;
2104                 return 1;
2105         } else if (timestamp > dest->route_timeout) {
2106                 acm_log(2, "%s route timed out\n", dest->name);
2107                 dest->state = ACM_ADDR_RESOLVED;
2108                 return 1;
2109         }
2110         return 0;
2111 }
2112
2113 static int
2114 acm_svr_resolve_dest(struct acm_client *client, struct acm_msg *msg)
2115 {
2116         struct acm_ep *ep;
2117         struct acm_dest *dest;
2118         struct acm_ep_addr_data *saddr, *daddr;
2119         uint8_t status;
2120         int ret;
2121
2122         acm_log(2, "client %d\n", client->index);
2123         status = acm_svr_verify_resolve(msg, &saddr, &daddr);
2124         if (status) {
2125                 acm_log(0, "notice - misformatted or unsupported request\n");
2126                 return acm_client_resolve_resp(client, msg, NULL, status);
2127         }
2128
2129         status = acm_svr_select_src(saddr, daddr);
2130         if (status) {
2131                 acm_log(0, "notice - unable to select suitable source address\n");
2132                 return acm_client_resolve_resp(client, msg, NULL, status);
2133         }
2134
2135         acm_format_name(2, log_data, sizeof log_data,
2136                         saddr->type, saddr->info.addr, sizeof saddr->info.addr);
2137         acm_log(2, "src  %s\n", log_data);
2138         ep = acm_get_ep(saddr);
2139         if (!ep) {
2140                 acm_log(0, "notice - unknown local end point\n");
2141                 return acm_client_resolve_resp(client, msg, NULL, ACM_STATUS_ESRCADDR);
2142         }
2143
2144         acm_format_name(2, log_data, sizeof log_data,
2145                         daddr->type, daddr->info.addr, sizeof daddr->info.addr);
2146         acm_log(2, "dest %s\n", log_data);
2147
2148         dest = acm_acquire_dest(ep, daddr->type, daddr->info.addr);
2149         if (!dest) {
2150                 acm_log(0, "ERROR - unable to allocate destination in client request\n");
2151                 return acm_client_resolve_resp(client, msg, NULL, ACM_STATUS_ENOMEM);
2152         }
2153
2154         lock_acquire(&dest->lock);
2155 test:
2156         switch (dest->state) {
2157         case ACM_READY:
2158                 if (acm_dest_timeout(dest))
2159                         goto test;
2160                 acm_log(2, "request satisfied from local cache\n");
2161                 atomic_inc(&counter[ACM_CNTR_ROUTE_CACHE]);
2162                 status = ACM_STATUS_SUCCESS;
2163                 break;
2164         case ACM_ADDR_RESOLVED:
2165                 acm_log(2, "have address, resolving route\n");
2166                 atomic_inc(&counter[ACM_CNTR_ADDR_CACHE]);
2167                 status = acm_resolve_path(ep, dest, acm_dest_sa_resp);
2168                 if (status) {
2169                         break;
2170                 }
2171                 goto queue;
2172         case ACM_INIT:
2173                 acm_log(2, "sending resolve msg to dest\n");
2174                 status = acm_send_resolve(ep, dest, saddr);
2175                 if (status) {
2176                         break;
2177                 }
2178                 dest->state = ACM_QUERY_ADDR;
2179                 /* fall through */
2180         default:
2181 queue:
2182                 if (daddr->flags & ACM_FLAGS_NODELAY) {
2183                         acm_log(2, "lookup initiated, but client wants no delay\n");
2184                         status = ACM_STATUS_ENODATA;
2185                         break;
2186                 }
2187                 status = acm_svr_queue_req(dest, client, msg);
2188                 if (status) {
2189                         break;
2190                 }
2191                 ret = 0;
2192                 lock_release(&dest->lock);
2193                 goto put;
2194         }
2195         lock_release(&dest->lock);
2196         ret = acm_client_resolve_resp(client, msg, dest, status);
2197 put:
2198         acm_put_dest(dest);
2199         return ret;
2200 }
2201
2202 /*
2203  * The message buffer contains extra address data buffers.  We extract the
2204  * destination address from the path record into an extra buffer, so we can
2205  * lookup the destination by either LID or GID.
2206  */
2207 static int
2208 acm_svr_resolve_path(struct acm_client *client, struct acm_msg *msg)
2209 {
2210         struct acm_ep *ep;
2211         struct acm_dest *dest;
2212         struct ibv_path_record *path;
2213         uint8_t *addr;
2214         uint8_t status;
2215         int ret;
2216
2217         acm_log(2, "client %d\n", client->index);
2218         if (msg->hdr.length < (ACM_MSG_HDR_LENGTH + ACM_MSG_EP_LENGTH)) {
2219                 acm_log(0, "notice - invalid msg hdr length %d\n", msg->hdr.length);
2220                 return acm_client_resolve_resp(client, msg, NULL, ACM_STATUS_EINVAL);
2221         }
2222
2223         path = &msg->resolve_data[0].info.path;
2224         if (!path->dlid && ib_any_gid(&path->dgid)) {
2225                 acm_log(0, "notice - no destination specified\n");
2226                 return acm_client_resolve_resp(client, msg, NULL, ACM_STATUS_EDESTADDR);
2227         }
2228
2229         acm_format_name(2, log_data, sizeof log_data, ACM_EP_INFO_PATH,
2230                 msg->resolve_data[0].info.addr, sizeof *path);
2231         acm_log(2, "path %s\n", log_data);
2232         ep = acm_get_ep(&msg->resolve_data[0]);
2233         if (!ep) {
2234                 acm_log(0, "notice - unknown local end point\n");
2235                 return acm_client_resolve_resp(client, msg, NULL, ACM_STATUS_ESRCADDR);
2236         }
2237
2238         addr = msg->resolve_data[1].info.addr;
2239         memset(addr, 0, ACM_MAX_ADDRESS);
2240         if (path->dlid) {
2241                 * ((uint16_t *) addr) = path->dlid;
2242                 dest = acm_acquire_dest(ep, ACM_ADDRESS_LID, addr);
2243         } else {
2244                 memcpy(addr, &path->dgid, sizeof path->dgid);
2245                 dest = acm_acquire_dest(ep, ACM_ADDRESS_GID, addr);
2246         }
2247         if (!dest) {
2248                 acm_log(0, "ERROR - unable to allocate destination in client request\n");
2249                 return acm_client_resolve_resp(client, msg, NULL, ACM_STATUS_ENOMEM);
2250         }
2251
2252         lock_acquire(&dest->lock);
2253 test:
2254         switch (dest->state) {
2255         case ACM_READY:
2256                 if (acm_dest_timeout(dest))
2257                         goto test;
2258                 acm_log(2, "request satisfied from local cache\n");
2259                 atomic_inc(&counter[ACM_CNTR_ROUTE_CACHE]);
2260                 status = ACM_STATUS_SUCCESS;
2261                 break;
2262         case ACM_INIT:
2263                 acm_log(2, "have path, bypassing address resolution\n");
2264                 acm_record_path_addr(ep, dest, path);
2265                 /* fall through */
2266         case ACM_ADDR_RESOLVED:
2267                 acm_log(2, "have address, resolving route\n");
2268                 status = acm_resolve_path(ep, dest, acm_dest_sa_resp);
2269                 if (status) {
2270                         break;
2271                 }
2272                 /* fall through */
2273         default:
2274                 if (msg->resolve_data[0].flags & ACM_FLAGS_NODELAY) {
2275                         acm_log(2, "lookup initiated, but client wants no delay\n");
2276                         status = ACM_STATUS_ENODATA;
2277                         break;
2278                 }
2279                 status = acm_svr_queue_req(dest, client, msg);
2280                 if (status) {
2281                         break;
2282                 }
2283                 ret = 0;
2284                 lock_release(&dest->lock);
2285                 goto put;
2286         }
2287         lock_release(&dest->lock);
2288         ret = acm_client_resolve_resp(client, msg, dest, status);
2289 put:
2290         acm_put_dest(dest);
2291         return ret;
2292 }
2293
2294 static int acm_svr_resolve(struct acm_client *client, struct acm_msg *msg)
2295 {
2296         if (msg->resolve_data[0].type == ACM_EP_INFO_PATH) {
2297                 if (msg->resolve_data[0].flags & ACM_FLAGS_QUERY_SA) {
2298                         return acm_svr_query_path(client, msg);
2299                 } else {
2300                         return acm_svr_resolve_path(client, msg);
2301                 }
2302         } else {
2303                 return acm_svr_resolve_dest(client, msg);
2304         }
2305 }
2306
2307 static int acm_svr_perf_query(struct acm_client *client, struct acm_msg *msg)
2308 {
2309         int ret, i;
2310         uint16_t len;
2311
2312         acm_log(2, "client %d\n", client->index);
2313         msg->hdr.opcode |= ACM_OP_ACK;
2314         msg->hdr.status = ACM_STATUS_SUCCESS;
2315         msg->hdr.data[0] = ACM_MAX_COUNTER;
2316         msg->hdr.data[1] = 0;
2317         msg->hdr.data[2] = 0;
2318         len = ACM_MSG_HDR_LENGTH + (ACM_MAX_COUNTER * sizeof(uint64_t));
2319         msg->hdr.length = htons(len);
2320
2321         for (i = 0; i < ACM_MAX_COUNTER; i++)
2322                 msg->perf_data[i] = htonll((uint64_t) atomic_get(&counter[i]));
2323
2324         ret = send(client->sock, (char *) msg, len, 0);
2325         if (ret != len)
2326                 acm_log(0, "ERROR - failed to send response\n");
2327         else
2328                 ret = 0;
2329
2330         return ret;
2331 }
2332
2333 static int acm_msg_length(struct acm_msg *msg)
2334 {
2335         return (msg->hdr.opcode == ACM_OP_RESOLVE) ?
2336                 msg->hdr.length : ntohs(msg->hdr.length);
2337 }
2338
2339 static void acm_svr_receive(struct acm_client *client)
2340 {
2341         struct acm_msg msg;
2342         int ret;
2343
2344         acm_log(2, "client %d\n", client->index);
2345         ret = recv(client->sock, (char *) &msg, sizeof msg, 0);
2346         if (ret <= 0 || ret != acm_msg_length(&msg)) {
2347                 acm_log(2, "client disconnected\n");
2348                 ret = ACM_STATUS_ENOTCONN;
2349                 goto out;
2350         }
2351
2352         if (msg.hdr.version != ACM_VERSION) {
2353                 acm_log(0, "ERROR - unsupported version %d\n", msg.hdr.version);
2354                 goto out;
2355         }
2356
2357         switch (msg.hdr.opcode & ACM_OP_MASK) {
2358         case ACM_OP_RESOLVE:
2359                 atomic_inc(&counter[ACM_CNTR_RESOLVE]);
2360                 ret = acm_svr_resolve(client, &msg);
2361                 break;
2362         case ACM_OP_PERF_QUERY:
2363                 ret = acm_svr_perf_query(client, &msg);
2364                 break;
2365         default:
2366                 acm_log(0, "ERROR - unknown opcode 0x%x\n", msg.hdr.opcode);
2367                 break;
2368         }
2369
2370 out:
2371         if (ret)
2372                 acm_disconnect_client(client);
2373 }
2374
2375 static void acm_server(void)
2376 {
2377         fd_set readfds;
2378         int i, n, ret;
2379
2380         acm_log(0, "started\n");
2381         acm_init_server();
2382         ret = acm_listen();
2383         if (ret) {
2384                 acm_log(0, "ERROR - server listen failed\n");
2385                 return;
2386         }
2387
2388         while (1) {
2389                 n = (int) listen_socket;
2390                 FD_ZERO(&readfds);
2391                 FD_SET(listen_socket, &readfds);
2392
2393                 for (i = 0; i < FD_SETSIZE - 1; i++) {
2394                         if (client[i].sock != INVALID_SOCKET) {
2395                                 FD_SET(client[i].sock, &readfds);
2396                                 n = max(n, (int) client[i].sock);
2397                         }
2398                 }
2399
2400                 ret = select(n + 1, &readfds, NULL, NULL, NULL);
2401                 if (ret == SOCKET_ERROR) {
2402                         acm_log(0, "ERROR - server select error\n");
2403                         continue;
2404                 }
2405
2406                 if (FD_ISSET(listen_socket, &readfds))
2407                         acm_svr_accept();
2408
2409                 for (i = 0; i < FD_SETSIZE - 1; i++) {
2410                         if (client[i].sock != INVALID_SOCKET &&
2411                                 FD_ISSET(client[i].sock, &readfds)) {
2412                                 acm_log(2, "receiving from client %d\n", i);
2413                                 acm_svr_receive(&client[i]);
2414                         }
2415                 }
2416         }
2417 }
2418
2419 static enum acm_addr_prot acm_convert_addr_prot(char *param)
2420 {
2421         if (!stricmp("acm", param))
2422                 return ACM_ADDR_PROT_ACM;
2423
2424         return addr_prot;
2425 }
2426
2427 static enum acm_route_prot acm_convert_route_prot(char *param)
2428 {
2429         if (!stricmp("acm", param))
2430                 return ACM_ROUTE_PROT_ACM;
2431         else if (!stricmp("sa", param))
2432                 return ACM_ROUTE_PROT_SA;
2433
2434         return route_prot;
2435 }
2436
2437 static enum acm_loopback_prot acm_convert_loopback_prot(char *param)
2438 {
2439         if (!stricmp("none", param))
2440                 return ACM_LOOPBACK_PROT_NONE;
2441         else if (!stricmp("local", param))
2442                 return ACM_LOOPBACK_PROT_LOCAL;
2443
2444         return loopback_prot;
2445 }
2446
2447 static enum ibv_rate acm_get_rate(uint8_t width, uint8_t speed)
2448 {
2449         switch (width) {
2450         case 1:
2451                 switch (speed) {
2452                 case 1: return IBV_RATE_2_5_GBPS;
2453                 case 2: return IBV_RATE_5_GBPS;
2454                 case 4: return IBV_RATE_10_GBPS;
2455                 default: return IBV_RATE_MAX;
2456                 }
2457         case 2:
2458                 switch (speed) {
2459                 case 1: return IBV_RATE_10_GBPS;
2460                 case 2: return IBV_RATE_20_GBPS;
2461                 case 4: return IBV_RATE_40_GBPS;
2462                 default: return IBV_RATE_MAX;
2463                 }
2464         case 4:
2465                 switch (speed) {
2466                 case 1: return IBV_RATE_20_GBPS;
2467                 case 2: return IBV_RATE_40_GBPS;
2468                 case 4: return IBV_RATE_80_GBPS;
2469                 default: return IBV_RATE_MAX;
2470                 }
2471         case 8:
2472                 switch (speed) {
2473                 case 1: return IBV_RATE_30_GBPS;
2474                 case 2: return IBV_RATE_60_GBPS;
2475                 case 4: return IBV_RATE_120_GBPS;
2476                 default: return IBV_RATE_MAX;
2477                 }
2478         default:
2479                 acm_log(0, "ERROR - unknown link width 0x%x\n", width);
2480                 return IBV_RATE_MAX;
2481         }
2482 }
2483
2484 static enum ibv_mtu acm_convert_mtu(int mtu)
2485 {
2486         switch (mtu) {
2487         case 256:  return IBV_MTU_256;
2488         case 512:  return IBV_MTU_512;
2489         case 1024: return IBV_MTU_1024;
2490         case 2048: return IBV_MTU_2048;
2491         case 4096: return IBV_MTU_4096;
2492         default:   return IBV_MTU_2048;
2493         }
2494 }
2495
2496 static enum ibv_rate acm_convert_rate(int rate)
2497 {
2498         switch (rate) {
2499         case 2:   return IBV_RATE_2_5_GBPS;
2500         case 5:   return IBV_RATE_5_GBPS;
2501         case 10:  return IBV_RATE_10_GBPS;
2502         case 20:  return IBV_RATE_20_GBPS;
2503         case 30:  return IBV_RATE_30_GBPS;
2504         case 40:  return IBV_RATE_40_GBPS;
2505         case 60:  return IBV_RATE_60_GBPS;
2506         case 80:  return IBV_RATE_80_GBPS;
2507         case 120: return IBV_RATE_120_GBPS;
2508         default:  return IBV_RATE_10_GBPS;
2509         }
2510 }
2511
2512 static int acm_post_recvs(struct acm_ep *ep)
2513 {
2514         int i, size;
2515
2516         size = recv_depth * ACM_RECV_SIZE;
2517         ep->recv_bufs = malloc(size);
2518         if (!ep->recv_bufs) {
2519                 acm_log(0, "ERROR - unable to allocate receive buffer\n");
2520                 return ACM_STATUS_ENOMEM;
2521         }
2522
2523         ep->mr = ibv_reg_mr(ep->port->dev->pd, ep->recv_bufs, size,
2524                 IBV_ACCESS_LOCAL_WRITE);
2525         if (!ep->mr) {
2526                 acm_log(0, "ERROR - unable to register receive buffer\n");
2527                 goto err;
2528         }
2529
2530         for (i = 0; i < recv_depth; i++) {
2531                 acm_post_recv(ep, (uintptr_t) (ep->recv_bufs + ACM_RECV_SIZE * i));
2532         }
2533         return 0;
2534
2535 err:
2536         free(ep->recv_bufs);
2537         return -1;
2538 }
2539
2540 static FILE *acm_open_addr_file(void)
2541 {
2542         FILE *f;
2543
2544         if ((f = fopen(addr_file, "r")))
2545                 return f;
2546
2547         acm_log(0, "notice - generating %s file\n", addr_file);
2548         if (!(f = popen(acme, "r"))) {
2549                 acm_log(0, "ERROR - cannot generate %s\n", addr_file);
2550                 return NULL;
2551         }
2552         pclose(f);
2553         return fopen(addr_file, "r");
2554 }
2555
2556 static int acm_assign_ep_names(struct acm_ep *ep)
2557 {
2558         FILE *faddr;
2559         char *dev_name;
2560         char s[120];
2561         char dev[32], addr[32], pkey_str[8];
2562         uint16_t pkey;
2563         uint8_t type;
2564         int port, index = 0;
2565         struct in6_addr ip_addr;
2566
2567         dev_name = ep->port->dev->verbs->device->name;
2568         acm_log(1, "device %s, port %d, pkey 0x%x\n",
2569                 dev_name, ep->port->port_num, ep->pkey);
2570
2571         if (!(faddr = acm_open_addr_file())) {
2572                 acm_log(0, "ERROR - address file not found\n");
2573                 return -1;
2574         }
2575
2576         while (fgets(s, sizeof s, faddr)) {
2577                 if (s[0] == '#')
2578                         continue;
2579
2580                 if (sscanf(s, "%32s%32s%d%8s", addr, dev, &port, pkey_str) != 4)
2581                         continue;
2582
2583                 acm_log(2, "%s", s);
2584                 if (inet_pton(AF_INET, addr, &ip_addr) > 0)
2585                         type = ACM_ADDRESS_IP;
2586                 else if (inet_pton(AF_INET6, addr, &ip_addr) > 0)
2587                         type = ACM_ADDRESS_IP6;
2588                 else
2589                         type = ACM_ADDRESS_NAME;
2590
2591                 if (stricmp(pkey_str, "default")) {
2592                         if (sscanf(pkey_str, "%hx", &pkey) != 1) {
2593                                 acm_log(0, "ERROR - bad pkey format %s\n", pkey_str);
2594                                 continue;
2595                         }
2596                 } else {
2597                         pkey = 0xFFFF;
2598                 }
2599
2600                 if (!stricmp(dev_name, dev) && (ep->port->port_num == (uint8_t) port) &&
2601                         (ep->pkey == pkey)) {
2602
2603                         ep->addr_type[index] = type;
2604                         acm_log(1, "assigning %s\n", addr);
2605                         strncpy(ep->name[index], addr, ACM_MAX_ADDRESS);
2606                         if (type == ACM_ADDRESS_IP)
2607                                 memcpy(ep->addr[index].addr, &ip_addr, 4);
2608                         else if (type == ACM_ADDRESS_IP6)
2609                                 memcpy(ep->addr[index].addr, &ip_addr, sizeof ip_addr);
2610                         else
2611                                 strncpy((char *) ep->addr[index].addr, addr, ACM_MAX_ADDRESS);
2612
2613                         if (++index == MAX_EP_ADDR) {
2614                                 acm_log(1, "maximum number of names assigned to EP\n");
2615                                 break;
2616                         }
2617                 }
2618         }
2619         fclose(faddr);
2620
2621         return !index;
2622 }
2623
2624 static int acm_init_ep_loopback(struct acm_ep *ep)
2625 {
2626         struct acm_dest *dest;
2627         int i;
2628
2629         acm_log(2, "\n");
2630         if (loopback_prot != ACM_LOOPBACK_PROT_LOCAL)
2631                 return 0;
2632
2633         for (i = 0; i < MAX_EP_ADDR && ep->addr_type[i]; i++) {
2634                 dest = acm_acquire_dest(ep, ep->addr_type[i], ep->addr[i].addr);
2635                 if (!dest) {
2636                         acm_format_name(0, log_data, sizeof log_data,
2637                                         ep->addr_type[i], ep->addr[i].addr,
2638                                         sizeof ep->addr[i].addr);
2639                         acm_log(0, "ERROR - unable to create loopback dest %s\n", log_data);
2640                         return -1;
2641                 }
2642
2643                 ibv_query_gid(ep->port->dev->verbs, ep->port->port_num,
2644                               0, &dest->path.sgid);
2645
2646                 dest->path.dgid = dest->path.sgid;
2647                 dest->path.dlid = dest->path.slid = htons(ep->port->lid);
2648                 dest->path.reversible_numpath = IBV_PATH_RECORD_REVERSIBLE;
2649                 dest->path.pkey = htons(ep->pkey);
2650                 dest->path.mtu = (uint8_t) ep->port->mtu;
2651                 dest->path.rate = (uint8_t) ep->port->rate;
2652
2653                 dest->remote_qpn = ep->qp->qp_num;
2654                 dest->addr_timeout = (uint64_t) ~0ULL;
2655                 dest->route_timeout = (uint64_t) ~0ULL;
2656                 dest->state = ACM_READY;
2657                 acm_put_dest(dest);
2658                 acm_log(1, "added loopback dest %s\n", dest->name);
2659         }
2660         return 0;
2661 }
2662
2663 static struct acm_ep *acm_find_ep(struct acm_port *port, uint16_t pkey)
2664 {
2665         struct acm_ep *ep, *res = NULL;
2666         DLIST_ENTRY *entry;
2667
2668         acm_log(2, "pkey 0x%x\n", pkey);
2669
2670         lock_acquire(&port->lock);
2671         for (entry = port->ep_list.Next; entry != &port->ep_list; entry = entry->Next) {
2672                 ep = container_of(entry, struct acm_ep, entry);
2673                 if (ep->pkey == pkey) {
2674                         res = ep;
2675                         break;
2676                 }
2677         }
2678         lock_release(&port->lock);
2679         return res;
2680 }
2681
2682 static struct acm_ep *
2683 acm_alloc_ep(struct acm_port *port, uint16_t pkey, uint16_t pkey_index)
2684 {
2685         struct acm_ep *ep;
2686
2687         acm_log(1, "\n");
2688         ep = calloc(1, sizeof *ep);
2689         if (!ep)
2690                 return NULL;
2691
2692         ep->port = port;
2693         ep->pkey = pkey;
2694         ep->pkey_index = pkey_index;
2695         ep->resolve_queue.credits = resolve_depth;
2696         ep->sa_queue.credits = sa_depth;
2697         ep->resp_queue.credits = send_depth;
2698         DListInit(&ep->resolve_queue.pending);
2699         DListInit(&ep->sa_queue.pending);
2700         DListInit(&ep->resp_queue.pending);
2701         DListInit(&ep->active_queue);
2702         DListInit(&ep->wait_queue);
2703         lock_init(&ep->lock);
2704
2705         return ep;
2706 }
2707
2708 static void acm_ep_up(struct acm_port *port, uint16_t pkey_index)
2709 {
2710         struct acm_ep *ep;
2711         struct ibv_qp_init_attr init_attr;
2712         struct ibv_qp_attr attr;
2713         int ret, sq_size;
2714         uint16_t pkey;
2715
2716         acm_log(1, "\n");
2717         ret = ibv_query_pkey(port->dev->verbs, port->port_num, pkey_index, &pkey);
2718         if (ret)
2719                 return;
2720
2721         if (acm_find_ep(port, pkey)) {
2722                 acm_log(2, "endpoint for pkey 0x%x already exists\n", pkey);
2723                 return;
2724         }
2725
2726         acm_log(2, "creating endpoint for pkey 0x%x\n", pkey);
2727         ep = acm_alloc_ep(port, pkey, pkey_index);
2728         if (!ep)
2729                 return;
2730
2731         ret = acm_assign_ep_names(ep);
2732         if (ret) {
2733                 acm_log(0, "ERROR - unable to assign EP name\n");
2734                 goto err0;
2735         }
2736
2737         sq_size = resolve_depth + sa_depth + send_depth;
2738         ep->cq = ibv_create_cq(port->dev->verbs, sq_size + recv_depth,
2739                 ep, port->dev->channel, 0);
2740         if (!ep->cq) {
2741                 acm_log(0, "ERROR - failed to create CQ\n");
2742                 goto err0;
2743         }
2744
2745         ret = ibv_req_notify_cq(ep->cq, 0);
2746         if (ret) {
2747                 acm_log(0, "ERROR - failed to arm CQ\n");
2748                 goto err1;
2749         }
2750
2751         memset(&init_attr, 0, sizeof init_attr);
2752         init_attr.cap.max_send_wr = sq_size;
2753         init_attr.cap.max_recv_wr = recv_depth;
2754         init_attr.cap.max_send_sge = 1;
2755         init_attr.cap.max_recv_sge = 1;
2756         init_attr.qp_context = ep;
2757         init_attr.sq_sig_all = 1;
2758         init_attr.qp_type = IBV_QPT_UD;
2759         init_attr.send_cq = ep->cq;
2760         init_attr.recv_cq = ep->cq;
2761         ep->qp = ibv_create_qp(ep->port->dev->pd, &init_attr);
2762         if (!ep->qp) {
2763                 acm_log(0, "ERROR - failed to create QP\n");
2764                 goto err1;
2765         }
2766
2767         attr.qp_state = IBV_QPS_INIT;
2768         attr.port_num = port->port_num;
2769         attr.pkey_index = pkey_index;
2770         attr.qkey = ACM_QKEY;
2771         ret = ibv_modify_qp(ep->qp, &attr, IBV_QP_STATE | IBV_QP_PKEY_INDEX |
2772                 IBV_QP_PORT | IBV_QP_QKEY);
2773         if (ret) {
2774                 acm_log(0, "ERROR - failed to modify QP to init\n");
2775                 goto err2;
2776         }
2777
2778         attr.qp_state = IBV_QPS_RTR;
2779         ret = ibv_modify_qp(ep->qp, &attr, IBV_QP_STATE);
2780         if (ret) {
2781                 acm_log(0, "ERROR - failed to modify QP to rtr\n");
2782                 goto err2;
2783         }
2784
2785         attr.qp_state = IBV_QPS_RTS;
2786         attr.sq_psn = 0;
2787         ret = ibv_modify_qp(ep->qp, &attr, IBV_QP_STATE | IBV_QP_SQ_PSN);
2788         if (ret) {
2789                 acm_log(0, "ERROR - failed to modify QP to rts\n");
2790                 goto err2;
2791         }
2792
2793         ret = acm_post_recvs(ep);
2794         if (ret)
2795                 goto err2;
2796
2797         ret = acm_init_ep_loopback(ep);
2798         if (ret) {
2799                 acm_log(0, "ERROR - unable to init loopback\n");
2800                 goto err2;
2801         }
2802         lock_acquire(&port->lock);
2803         DListInsertHead(&ep->entry, &port->ep_list);
2804         lock_release(&port->lock);
2805         return;
2806
2807 err2:
2808         ibv_destroy_qp(ep->qp);
2809 err1:
2810         ibv_destroy_cq(ep->cq);
2811 err0:
2812         free(ep);
2813 }
2814
2815 static void acm_port_up(struct acm_port *port)
2816 {
2817         struct ibv_port_attr attr;
2818         union ibv_gid gid;
2819         uint16_t pkey;
2820         int i, ret;
2821
2822         acm_log(1, "%s %d\n", port->dev->verbs->device->name, port->port_num);
2823         ret = ibv_query_port(port->dev->verbs, port->port_num, &attr);
2824         if (ret) {
2825                 acm_log(0, "ERROR - unable to get port state\n");
2826                 return;
2827         }
2828         if (attr.state != IBV_PORT_ACTIVE) {
2829                 acm_log(1, "port not active\n");
2830                 return;
2831         }
2832
2833         port->mtu = attr.active_mtu;
2834         port->rate = acm_get_rate(attr.active_width, attr.active_speed);
2835         if (attr.subnet_timeout >= 8)
2836                 port->subnet_timeout = 1 << (attr.subnet_timeout - 8);
2837         for (port->gid_cnt = 0;; port->gid_cnt++) {
2838                 ret = ibv_query_gid(port->dev->verbs, port->port_num, port->gid_cnt, &gid);
2839                 if (ret || !gid.global.interface_id)
2840                         break;
2841         }
2842
2843         for (port->pkey_cnt = 0;; port->pkey_cnt++) {
2844                 ret = ibv_query_pkey(port->dev->verbs, port->port_num, port->pkey_cnt, &pkey);
2845                 if (ret || !pkey)
2846                         break;
2847         }
2848         port->lid = attr.lid;
2849         port->lid_mask = 0xffff - ((1 << attr.lmc) - 1);
2850
2851         port->sa_dest.av.src_path_bits = 0;
2852         port->sa_dest.av.dlid = attr.sm_lid;
2853         port->sa_dest.av.sl = attr.sm_sl;
2854         port->sa_dest.av.port_num = port->port_num;
2855         port->sa_dest.remote_qpn = 1;
2856         attr.sm_lid = htons(attr.sm_lid);
2857         acm_set_dest_addr(&port->sa_dest, ACM_ADDRESS_LID,
2858                 (uint8_t *) &attr.sm_lid, sizeof(attr.sm_lid));
2859
2860         port->sa_dest.ah = ibv_create_ah(port->dev->pd, &port->sa_dest.av);
2861         if (!port->sa_dest.ah)
2862                 return;
2863
2864         atomic_set(&port->sa_dest.refcnt, 1);
2865         for (i = 0; i < port->pkey_cnt; i++)
2866                  acm_ep_up(port, (uint16_t) i);
2867
2868         acm_port_join(port);
2869         port->state = IBV_PORT_ACTIVE;
2870         acm_log(1, "%s %d is up\n", port->dev->verbs->device->name, port->port_num);
2871 }
2872
2873 static void acm_port_down(struct acm_port *port)
2874 {
2875         struct ibv_port_attr attr;
2876         int ret;
2877
2878         acm_log(1, "%s %d\n", port->dev->verbs->device->name, port->port_num);
2879         ret = ibv_query_port(port->dev->verbs, port->port_num, &attr);
2880         if (!ret && attr.state == IBV_PORT_ACTIVE) {
2881                 acm_log(1, "port active\n");
2882                 return;
2883         }
2884
2885         port->state = attr.state;
2886
2887         /*
2888          * We wait for the SA destination to be released.  We could use an
2889          * event instead of a sleep loop, but it's not worth it given how
2890          * infrequently we should be processing a port down event in practice.
2891          */
2892         atomic_dec(&port->sa_dest.refcnt);
2893         while (atomic_get(&port->sa_dest.refcnt))
2894                 sleep(0);
2895         ibv_destroy_ah(port->sa_dest.ah);
2896         acm_log(1, "%s %d is down\n", port->dev->verbs->device->name, port->port_num);
2897 }
2898
2899 /*
2900  * There is one event handler thread per device.  This is the only thread that
2901  * modifies the port state or a port endpoint list.  Other threads which access
2902  * those must synchronize against changes accordingly, but this thread only
2903  * needs to lock when making modifications.
2904  */
2905 static void CDECL_FUNC acm_event_handler(void *context)
2906 {
2907         struct acm_device *dev = (struct acm_device *) context;
2908         struct ibv_async_event event;
2909         int i, ret;
2910
2911         acm_log(1, "started\n");
2912         for (i = 0; i < dev->port_cnt; i++) {
2913                 acm_port_up(&dev->port[i]);
2914         }
2915
2916         for (;;) {
2917                 ret = ibv_get_async_event(dev->verbs, &event);
2918                 if (ret)
2919                         continue;
2920
2921                 acm_log(2, "processing async event %s\n",
2922                         ibv_event_type_str(event.event_type));
2923                 i = event.element.port_num - 1;
2924                 switch (event.event_type) {
2925                 case IBV_EVENT_PORT_ACTIVE:
2926                         if (dev->port[i].state != IBV_PORT_ACTIVE)
2927                                 acm_port_up(&dev->port[i]);
2928                         break;
2929                 case IBV_EVENT_PORT_ERR:
2930                         if (dev->port[i].state == IBV_PORT_ACTIVE)
2931                                 acm_port_down(&dev->port[i]);
2932                         break;
2933                 default:
2934                         break;
2935                 }
2936
2937                 ibv_ack_async_event(&event);
2938         }
2939 }
2940
2941 static void acm_activate_devices()
2942 {
2943         struct acm_device *dev;
2944         DLIST_ENTRY *dev_entry;
2945
2946         acm_log(1, "\n");
2947         for (dev_entry = dev_list.Next; dev_entry != &dev_list;
2948                 dev_entry = dev_entry->Next) {
2949
2950                 dev = container_of(dev_entry, struct acm_device, entry);
2951                 beginthread(acm_event_handler, dev);
2952                 beginthread(acm_comp_handler, dev);
2953         }
2954 }
2955
2956 static void acm_open_port(struct acm_port *port, struct acm_device *dev, uint8_t port_num)
2957 {
2958         acm_log(1, "%s %d\n", dev->verbs->device->name, port_num);
2959         port->dev = dev;
2960         port->port_num = port_num;
2961         lock_init(&port->lock);
2962         DListInit(&port->ep_list);
2963         acm_init_dest(&port->sa_dest, ACM_ADDRESS_LID, NULL, 0);
2964
2965         port->mad_portid = umad_open_port(dev->verbs->device->name, port->port_num);
2966         if (port->mad_portid < 0) {
2967                 acm_log(0, "ERROR - unable to open MAD port\n");
2968                 return;
2969         }
2970
2971         port->mad_agentid = umad_register(port->mad_portid,
2972                 IB_MGMT_CLASS_SA, 1, 1, NULL);
2973         if (port->mad_agentid < 0) {
2974                 acm_log(0, "ERROR - unable to register MAD client\n");
2975                 goto err;
2976         }
2977
2978         port->state = IBV_PORT_DOWN;
2979         return;
2980 err:
2981         umad_close_port(port->mad_portid);
2982 }
2983
2984 static void acm_open_dev(struct ibv_device *ibdev)
2985 {
2986         struct acm_device *dev;
2987         struct ibv_device_attr attr;
2988         struct ibv_context *verbs;
2989         size_t size;
2990         int i, ret;
2991
2992         acm_log(1, "%s\n", ibdev->name);
2993         verbs = ibv_open_device(ibdev);
2994         if (verbs == NULL) {
2995                 acm_log(0, "ERROR - opening device %s\n", ibdev->name);
2996                 return;
2997         }
2998
2999         ret = ibv_query_device(verbs, &attr);
3000         if (ret) {
3001                 acm_log(0, "ERROR - ibv_query_device (%s) %d\n", ret, ibdev->name);
3002                 goto err1;
3003         }
3004
3005         size = sizeof(*dev) + sizeof(struct acm_port) * attr.phys_port_cnt;
3006         dev = (struct acm_device *) calloc(1, size);
3007         if (!dev)
3008                 goto err1;
3009
3010         dev->verbs = verbs;
3011         dev->guid = ibv_get_device_guid(ibdev);
3012         dev->port_cnt = attr.phys_port_cnt;
3013
3014         dev->pd = ibv_alloc_pd(dev->verbs);
3015         if (!dev->pd) {
3016                 acm_log(0, "ERROR - unable to allocate PD\n");
3017                 goto err2;
3018         }
3019
3020         dev->channel = ibv_create_comp_channel(dev->verbs);
3021         if (!dev->channel) {
3022                 acm_log(0, "ERROR - unable to create comp channel\n");
3023                 goto err3;
3024         }
3025
3026         for (i = 0; i < dev->port_cnt; i++)
3027                 acm_open_port(&dev->port[i], dev, i + 1);
3028
3029         DListInsertHead(&dev->entry, &dev_list);
3030
3031         acm_log(1, "%s opened\n", ibdev->name);
3032         return;
3033
3034 err3:
3035         ibv_dealloc_pd(dev->pd);
3036 err2:
3037         free(dev);
3038 err1:
3039         ibv_close_device(verbs);
3040 }
3041
3042 static int acm_open_devices(void)
3043 {
3044         struct ibv_device **ibdev;
3045         int dev_cnt;
3046         int i;
3047
3048         acm_log(1, "\n");
3049         ibdev = ibv_get_device_list(&dev_cnt);
3050         if (!ibdev) {
3051                 acm_log(0, "ERROR - unable to get device list\n");
3052                 return -1;
3053         }
3054
3055         for (i = 0; i < dev_cnt; i++)
3056                 acm_open_dev(ibdev[i]);
3057
3058         ibv_free_device_list(ibdev);
3059         if (DListEmpty(&dev_list)) {
3060                 acm_log(0, "ERROR - no devices\n");
3061                 return -1;
3062         }
3063
3064         return 0;
3065 }
3066
3067 static void acm_set_options(void)
3068 {
3069         FILE *f;
3070         char s[120];
3071         char opt[32], value[32];
3072
3073         if (!(f = fopen(opts_file, "r")))
3074                 return;
3075
3076         while (fgets(s, sizeof s, f)) {
3077                 if (s[0] == '#')
3078                         continue;
3079
3080                 if (sscanf(s, "%32s%32s", opt, value) != 2)
3081                         continue;
3082
3083                 if (!stricmp("log_file", opt))
3084                         strcpy(log_file, value);
3085                 else if (!stricmp("log_level", opt))
3086                         log_level = atoi(value);
3087                 else if (!stricmp("lock_file", opt))
3088                         strcpy(lock_file, value);
3089                 else if (!stricmp("addr_prot", opt))
3090                         addr_prot = acm_convert_addr_prot(value);
3091                 else if (!stricmp("addr_timeout", opt))
3092                         addr_timeout = atoi(value);
3093                 else if (!stricmp("route_prot", opt))
3094                         route_prot = acm_convert_route_prot(value);
3095                 else if (!strcmp("route_timeout", opt))
3096                         route_timeout = atoi(value);
3097                 else if (!stricmp("loopback_prot", opt))
3098                         loopback_prot = acm_convert_loopback_prot(value);
3099                 else if (!stricmp("server_port", opt))
3100                         server_port = (short) atoi(value);
3101                 else if (!stricmp("timeout", opt))
3102                         timeout = atoi(value);
3103                 else if (!stricmp("retries", opt))
3104                         retries = atoi(value);
3105                 else if (!stricmp("resolve_depth", opt))
3106                         resolve_depth = atoi(value);
3107                 else if (!stricmp("sa_depth", opt))
3108                         sa_depth = atoi(value);
3109                 else if (!stricmp("send_depth", opt))
3110                         send_depth = atoi(value);
3111                 else if (!stricmp("recv_depth", opt))
3112                         recv_depth = atoi(value);
3113                 else if (!stricmp("min_mtu", opt))
3114                         min_mtu = acm_convert_mtu(atoi(value));
3115                 else if (!stricmp("min_rate", opt))
3116                         min_rate = acm_convert_rate(atoi(value));
3117         }
3118
3119         fclose(f);
3120 }
3121
3122 static void acm_log_options(void)
3123 {
3124         acm_log(0, "log level %d\n", log_level);
3125         acm_log(0, "lock file %s\n", lock_file);
3126         acm_log(0, "address resolution %d\n", addr_prot);
3127         acm_log(0, "address timeout %d\n", addr_timeout);
3128         acm_log(0, "route resolution %d\n", route_prot);
3129         acm_log(0, "route timeout %d\n", route_timeout);
3130         acm_log(0, "loopback resolution %d\n", loopback_prot);
3131         acm_log(0, "server_port %d\n", server_port);
3132         acm_log(0, "timeout %d ms\n", timeout);
3133         acm_log(0, "retries %d\n", retries);
3134         acm_log(0, "resolve depth %d\n", resolve_depth);
3135         acm_log(0, "sa depth %d\n", sa_depth);
3136         acm_log(0, "send depth %d\n", send_depth);
3137         acm_log(0, "receive depth %d\n", recv_depth);
3138         acm_log(0, "minimum mtu %d\n", min_mtu);
3139         acm_log(0, "minimum rate %d\n", min_rate);
3140 }
3141
3142 static FILE *acm_open_log(void)
3143 {
3144         FILE *f;
3145
3146         if (!stricmp(log_file, "stdout"))
3147                 return stdout;
3148
3149         if (!stricmp(log_file, "stderr"))
3150                 return stderr;
3151
3152         if (!(f = fopen(log_file, "w")))
3153                 f = stdout;
3154
3155         return f;
3156 }
3157
3158 static int acm_open_lock_file(void)
3159 {
3160         int lock_fd;
3161         char pid[16];
3162
3163         lock_fd = open(lock_file, O_RDWR | O_CREAT, 0640);
3164         if (lock_fd < 0)
3165                 return lock_fd;
3166
3167         if (lockf(lock_fd, F_TLOCK, 0)) {
3168                 close(lock_fd);
3169                 return -1;
3170         }
3171
3172         snprintf(pid, sizeof pid, "%d\n", getpid());
3173         write(lock_fd, pid, strlen(pid));
3174         return 0;
3175 }
3176
3177 static void daemonize(void)
3178 {
3179         pid_t pid, sid;
3180
3181         pid = fork();
3182         if (pid)
3183                 exit(pid < 0);
3184
3185         sid = setsid();
3186         if (sid < 0)
3187                 exit(1);
3188
3189         if (chdir("/"))
3190                 exit(1);
3191
3192         freopen("/dev/null", "r", stdin);
3193         freopen("/dev/null", "w", stdout);
3194         freopen("/dev/null", "w", stderr);
3195 }
3196
3197 static void show_usage(char *program)
3198 {
3199         printf("usage: %s\n", program);
3200         printf("   [-D]             - run as a daemon (default)\n");
3201         printf("   [-P]             - run as a standard process\n");
3202         printf("   [-A addr_file]   - address configuration file\n");
3203         printf("                      (default %s/%s\n", ACM_CONF_DIR, ACM_ADDR_FILE);
3204         printf("   [-O option_file] - option configuration file\n");
3205         printf("                      (default %s/%s\n", ACM_CONF_DIR, ACM_OPTS_FILE);
3206 }
3207
3208 int CDECL_FUNC main(int argc, char **argv)
3209 {
3210         int i, op, daemon = 1;
3211
3212         while ((op = getopt(argc, argv, "DPA:O:")) != -1) {
3213                 switch (op) {
3214                 case 'D':
3215                         /* option no longer required */
3216                         break;
3217                 case 'P':
3218                         daemon = 0;
3219                         break;
3220                 case 'A':
3221                         addr_file = optarg;
3222                         break;
3223                 case 'O':
3224                         opts_file = optarg;
3225                         break;
3226                 default:
3227                         show_usage(argv[0]);
3228                         exit(1);
3229                 }
3230         }
3231
3232         if (daemon)
3233                 daemonize();
3234
3235         if (osd_init())
3236                 return -1;
3237
3238         acm_set_options();
3239         if (acm_open_lock_file())
3240                 return -1;
3241
3242         lock_init(&log_lock);
3243         flog = acm_open_log();
3244
3245         acm_log(0, "Assistant to the InfiniBand Communication Manager\n");
3246         acm_log_options();
3247
3248         atomic_init(&tid);
3249         atomic_init(&wait_cnt);
3250         DListInit(&dev_list);
3251         DListInit(&timeout_list);
3252         event_init(&timeout_event);
3253         for (i = 0; i < ACM_MAX_COUNTER; i++)
3254                 atomic_init(&counter[i]);
3255
3256         umad_init();
3257         if (acm_open_devices()) {
3258                 acm_log(0, "ERROR - unable to open any devices\n");
3259                 return -1;
3260         }
3261
3262         acm_activate_devices();
3263         acm_log(1, "starting timeout/retry thread\n");
3264         beginthread(acm_retry_handler, NULL);
3265         acm_log(1, "starting server\n");
3266         acm_server();
3267
3268         acm_log(0, "shutting down\n");
3269         fclose(flog);
3270         return 0;
3271 }