2 * Copyright (c) 2004-2007 Voltaire Inc. All rights reserved.
3 * Copyright (c) 2007 Xsigo Systems Inc. All rights reserved.
4 * Copyright (c) 2008 Lawrence Livermore National Laboratory
6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU
8 * General Public License (GPL) Version 2, available from the file
9 * COPYING in the main directory of this source tree, or the
10 * OpenIB.org BSD license below:
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
16 * - Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
20 * - Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials
23 * provided with the distribution.
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38 #endif /* HAVE_CONFIG_H */
43 #include <sys/types.h>
51 #include <infiniband/ibnetdisc.h>
56 /* For this caching lib, we always cache little endian */
60 * Bytes 1-4 - magic number
61 * Bytes 5-8 - version number
62 * Bytes 9-12 - node count
63 * Bytes 13-16 - port count
64 * Bytes 17-24 - "from node" guid
65 * Bytes 25-28 - maxhops discovered
66 * Bytes X-Y - nodes (variable length)
67 * Bytes X-Y - ports (variable length)
73 * 1 byte - smaenhsp0 flag
74 * IB_SMP_DATA_SIZE bytes - switchinfo
78 * IB_SMP_DATA_SIZE bytes - info
79 * IB_SMP_DATA_SIZE bytes - nodedesc
80 * 1 byte - number of ports stored
81 * 8 bytes - portguid A
83 * 8 bytes - portguid B
85 * ... etc., depending on number of ports stored
91 * 1 byte - external portnum
94 * IB_SMP_DATA_SIZE bytes - info
95 * 8 bytes - node guid port "owned" by
96 * 1 byte - flag indicating if remote port exists
97 * 8 bytes - port guid remotely connected to
98 * 1 byte - port num remotely connected to
101 /* Structs that hold cache info temporarily before
102 * the real structs can be reconstructed.
105 typedef struct ibnd_port_cache_key {
108 } ibnd_port_cache_key_t;
110 typedef struct ibnd_node_cache {
112 uint8_t ports_stored_count;
113 ibnd_port_cache_key_t *port_cache_keys;
114 struct ibnd_node_cache *next;
115 struct ibnd_node_cache *htnext;
116 int node_stored_to_fabric;
119 typedef struct ibnd_port_cache {
122 uint8_t remoteport_flag;
123 ibnd_port_cache_key_t remoteport_cache_key;
124 struct ibnd_port_cache *next;
125 struct ibnd_port_cache *htnext;
126 int port_stored_to_fabric;
129 typedef struct ibnd_fabric_cache {
131 uint64_t from_node_guid;
132 ibnd_node_cache_t *nodes_cache;
133 ibnd_port_cache_t *ports_cache;
134 ibnd_node_cache_t *nodescachetbl[HTSZ];
135 ibnd_port_cache_t *portscachetbl[HTSZ];
136 } ibnd_fabric_cache_t;
138 #define IBND_FABRIC_CACHE_BUFLEN 4096
139 #define IBND_FABRIC_CACHE_MAGIC 0x8FE7832B
140 #define IBND_FABRIC_CACHE_VERSION 0x00000001
142 #define IBND_FABRIC_CACHE_COUNT_OFFSET 8
144 #define IBND_FABRIC_CACHE_HEADER_LEN (28)
145 #define IBND_NODE_CACHE_HEADER_LEN (15 + IB_SMP_DATA_SIZE*3)
146 #define IBND_PORT_CACHE_KEY_LEN (8 + 1)
147 #define IBND_PORT_CACHE_LEN (31 + IB_SMP_DATA_SIZE)
149 static ssize_t ibnd_read(int fd, void *buf, size_t count)
151 size_t count_done = 0;
154 while ((count - count_done) > 0) {
155 ret = read(fd, ((char *) buf) + count_done, count - count_done);
160 IBND_DEBUG("read: %s\n", strerror(errno));
169 if (count_done != count) {
170 IBND_DEBUG("read: read short\n");
177 static size_t _unmarshall8(uint8_t * inbuf, uint8_t * num)
181 return (sizeof(*num));
184 static size_t _unmarshall16(uint8_t * inbuf, uint16_t * num)
186 (*num) = ((uint16_t) inbuf[1] << 8) | inbuf[0];
188 return (sizeof(*num));
191 static size_t _unmarshall32(uint8_t * inbuf, uint32_t * num)
193 (*num) = (uint32_t) inbuf[0];
194 (*num) |= ((uint32_t) inbuf[1] << 8);
195 (*num) |= ((uint32_t) inbuf[2] << 16);
196 (*num) |= ((uint32_t) inbuf[3] << 24);
198 return (sizeof(*num));
201 static size_t _unmarshall64(uint8_t * inbuf, uint64_t * num)
203 (*num) = (uint64_t) inbuf[0];
204 (*num) |= ((uint64_t) inbuf[1] << 8);
205 (*num) |= ((uint64_t) inbuf[2] << 16);
206 (*num) |= ((uint64_t) inbuf[3] << 24);
207 (*num) |= ((uint64_t) inbuf[4] << 32);
208 (*num) |= ((uint64_t) inbuf[5] << 40);
209 (*num) |= ((uint64_t) inbuf[6] << 48);
210 (*num) |= ((uint64_t) inbuf[7] << 56);
212 return (sizeof(*num));
215 static size_t _unmarshall_buf(const void *inbuf, void *outbuf, unsigned int len)
217 memcpy(outbuf, inbuf, len);
222 static int _load_header_info(int fd, ibnd_fabric_cache_t * fabric_cache,
223 unsigned int *node_count, unsigned int *port_count)
225 uint8_t buf[IBND_FABRIC_CACHE_BUFLEN];
227 uint32_t version = 0;
231 if (ibnd_read(fd, buf, IBND_FABRIC_CACHE_HEADER_LEN) < 0)
234 offset += _unmarshall32(buf + offset, &magic);
236 if (magic != IBND_FABRIC_CACHE_MAGIC) {
237 IBND_DEBUG("invalid fabric cache file\n");
241 offset += _unmarshall32(buf + offset, &version);
243 if (version != IBND_FABRIC_CACHE_VERSION) {
244 IBND_DEBUG("invalid fabric cache version\n");
248 offset += _unmarshall32(buf + offset, node_count);
249 offset += _unmarshall32(buf + offset, port_count);
251 offset += _unmarshall64(buf + offset, &fabric_cache->from_node_guid);
252 offset += _unmarshall32(buf + offset, &tmp32);
253 fabric_cache->f_int->fabric.maxhops_discovered = tmp32;
258 static void _destroy_ibnd_node_cache(ibnd_node_cache_t * node_cache)
260 free(node_cache->port_cache_keys);
261 if (!node_cache->node_stored_to_fabric && node_cache->node)
262 destroy_node(node_cache->node);
266 static void _destroy_ibnd_fabric_cache(ibnd_fabric_cache_t * fabric_cache)
268 ibnd_node_cache_t *node_cache;
269 ibnd_node_cache_t *node_cache_next;
270 ibnd_port_cache_t *port_cache;
271 ibnd_port_cache_t *port_cache_next;
276 node_cache = fabric_cache->nodes_cache;
278 node_cache_next = node_cache->next;
280 _destroy_ibnd_node_cache(node_cache);
282 node_cache = node_cache_next;
285 port_cache = fabric_cache->ports_cache;
287 port_cache_next = port_cache->next;
289 if (!port_cache->port_stored_to_fabric && port_cache->port)
290 free(port_cache->port);
293 port_cache = port_cache_next;
299 static void store_node_cache(ibnd_node_cache_t * node_cache,
300 ibnd_fabric_cache_t * fabric_cache)
302 int hash_indx = HASHGUID(node_cache->node->guid) % HTSZ;
304 node_cache->next = fabric_cache->nodes_cache;
305 fabric_cache->nodes_cache = node_cache;
307 node_cache->htnext = fabric_cache->nodescachetbl[hash_indx];
308 fabric_cache->nodescachetbl[hash_indx] = node_cache;
311 static int _load_node(int fd, ibnd_fabric_cache_t * fabric_cache)
313 uint8_t buf[IBND_FABRIC_CACHE_BUFLEN];
314 ibnd_node_cache_t *node_cache = NULL;
315 ibnd_node_t *node = NULL;
319 node_cache = (ibnd_node_cache_t *) malloc(sizeof(ibnd_node_cache_t));
321 IBND_DEBUG("OOM: node_cache\n");
324 memset(node_cache, '\0', sizeof(ibnd_node_cache_t));
326 node = (ibnd_node_t *) malloc(sizeof(ibnd_node_t));
328 IBND_DEBUG("OOM: node\n");
332 memset(node, '\0', sizeof(ibnd_node_t));
334 node_cache->node = node;
336 if (ibnd_read(fd, buf, IBND_NODE_CACHE_HEADER_LEN) < 0)
339 offset += _unmarshall16(buf + offset, &node->smalid);
340 offset += _unmarshall8(buf + offset, &node->smalmc);
341 offset += _unmarshall8(buf + offset, &tmp8);
342 node->smaenhsp0 = tmp8;
343 offset += _unmarshall_buf(buf + offset, node->switchinfo,
345 offset += _unmarshall64(buf + offset, &node->guid);
346 offset += _unmarshall8(buf + offset, &tmp8);
348 offset += _unmarshall8(buf + offset, &tmp8);
349 node->numports = tmp8;
350 offset += _unmarshall_buf(buf + offset, node->info, IB_SMP_DATA_SIZE);
351 offset += _unmarshall_buf(buf + offset, node->nodedesc,
354 offset += _unmarshall8(buf + offset, &node_cache->ports_stored_count);
356 if (node_cache->ports_stored_count) {
357 unsigned int tomalloc = 0;
358 unsigned int toread = 0;
362 sizeof(ibnd_port_cache_key_t) *
363 node_cache->ports_stored_count;
366 IBND_PORT_CACHE_KEY_LEN * node_cache->ports_stored_count;
368 node_cache->port_cache_keys =
369 (ibnd_port_cache_key_t *) malloc(tomalloc);
370 if (!node_cache->port_cache_keys) {
371 IBND_DEBUG("OOM: node_cache port_cache_keys\n");
375 if (ibnd_read(fd, buf, toread) < 0)
380 for (i = 0; i < node_cache->ports_stored_count; i++) {
382 _unmarshall64(buf + offset,
383 &node_cache->port_cache_keys[i].guid);
385 _unmarshall8(buf + offset,
387 port_cache_keys[i].portnum);
391 store_node_cache(node_cache, fabric_cache);
396 _destroy_ibnd_node_cache(node_cache);
400 static void store_port_cache(ibnd_port_cache_t * port_cache,
401 ibnd_fabric_cache_t * fabric_cache)
403 int hash_indx = HASHGUID(port_cache->port->guid) % HTSZ;
405 port_cache->next = fabric_cache->ports_cache;
406 fabric_cache->ports_cache = port_cache;
408 port_cache->htnext = fabric_cache->portscachetbl[hash_indx];
409 fabric_cache->portscachetbl[hash_indx] = port_cache;
412 static int _load_port(int fd, ibnd_fabric_cache_t * fabric_cache)
414 uint8_t buf[IBND_FABRIC_CACHE_BUFLEN];
415 ibnd_port_cache_t *port_cache = NULL;
416 ibnd_port_t *port = NULL;
420 port_cache = (ibnd_port_cache_t *) malloc(sizeof(ibnd_port_cache_t));
422 IBND_DEBUG("OOM: port_cache\n");
425 memset(port_cache, '\0', sizeof(ibnd_port_cache_t));
427 port = (ibnd_port_t *) malloc(sizeof(ibnd_port_t));
429 IBND_DEBUG("OOM: port\n");
433 memset(port, '\0', sizeof(ibnd_port_t));
435 port_cache->port = port;
437 if (ibnd_read(fd, buf, IBND_PORT_CACHE_LEN) < 0)
440 offset += _unmarshall64(buf + offset, &port->guid);
441 offset += _unmarshall8(buf + offset, &tmp8);
442 port->portnum = tmp8;
443 offset += _unmarshall8(buf + offset, &tmp8);
444 port->ext_portnum = tmp8;
445 offset += _unmarshall16(buf + offset, &port->base_lid);
446 offset += _unmarshall8(buf + offset, &port->lmc);
447 offset += _unmarshall_buf(buf + offset, port->info, IB_SMP_DATA_SIZE);
448 offset += _unmarshall64(buf + offset, &port_cache->node_guid);
449 offset += _unmarshall8(buf + offset, &port_cache->remoteport_flag);
451 _unmarshall64(buf + offset, &port_cache->remoteport_cache_key.guid);
453 _unmarshall8(buf + offset,
454 &port_cache->remoteport_cache_key.portnum);
456 store_port_cache(port_cache, fabric_cache);
466 static ibnd_port_cache_t *_find_port(ibnd_fabric_cache_t * fabric_cache,
467 ibnd_port_cache_key_t * port_cache_key)
469 int hash_indx = HASHGUID(port_cache_key->guid) % HTSZ;
470 ibnd_port_cache_t *port_cache;
472 for (port_cache = fabric_cache->portscachetbl[hash_indx];
473 port_cache; port_cache = port_cache->htnext) {
474 if (port_cache->port->guid == port_cache_key->guid
475 && port_cache->port->portnum == port_cache_key->portnum)
482 static ibnd_node_cache_t *_find_node(ibnd_fabric_cache_t * fabric_cache,
485 int hash_indx = HASHGUID(guid) % HTSZ;
486 ibnd_node_cache_t *node_cache;
488 for (node_cache = fabric_cache->nodescachetbl[hash_indx];
489 node_cache; node_cache = node_cache->htnext) {
490 if (node_cache->node->guid == guid)
497 static int _fill_port(ibnd_fabric_cache_t * fabric_cache, ibnd_node_t * node,
498 ibnd_port_cache_key_t * port_cache_key)
500 ibnd_port_cache_t *port_cache;
502 if (!(port_cache = _find_port(fabric_cache, port_cache_key))) {
503 IBND_DEBUG("Cache invalid: cannot find port\n");
507 if (port_cache->port_stored_to_fabric) {
508 IBND_DEBUG("Cache invalid: duplicate port discovered\n");
512 node->ports[port_cache->port->portnum] = port_cache->port;
513 port_cache->port_stored_to_fabric++;
515 /* achu: needed if user wishes to re-cache a loaded fabric.
516 * Otherwise, mostly unnecessary to do this.
518 int rc = add_to_portguid_hash(port_cache->port,
519 fabric_cache->f_int->fabric.portstbl);
521 IBND_DEBUG("Error Occurred when trying"
522 " to insert new port guid 0x%016" PRIx64 " to DB\n",
523 port_cache->port->guid);
528 static int _rebuild_nodes(ibnd_fabric_cache_t * fabric_cache)
530 ibnd_node_cache_t *node_cache;
531 ibnd_node_cache_t *node_cache_next;
533 node_cache = fabric_cache->nodes_cache;
538 node_cache_next = node_cache->next;
540 node = node_cache->node;
542 /* Insert node into appropriate data structures */
544 node->next = fabric_cache->f_int->fabric.nodes;
545 fabric_cache->f_int->fabric.nodes = node;
547 int rc = add_to_nodeguid_hash(node_cache->node,
552 IBND_DEBUG("Error Occurred when trying"
553 " to insert new node guid 0x%016" PRIx64 " to DB\n",
554 node_cache->node->guid);
557 add_to_type_list(node_cache->node, fabric_cache->f_int);
559 node_cache->node_stored_to_fabric++;
561 /* Rebuild node ports array */
564 calloc(sizeof(*node->ports), node->numports + 1))) {
565 IBND_DEBUG("OOM: node->ports\n");
569 for (i = 0; i < node_cache->ports_stored_count; i++) {
570 if (_fill_port(fabric_cache, node,
571 &node_cache->port_cache_keys[i]) < 0)
575 node_cache = node_cache_next;
581 static int _rebuild_ports(ibnd_fabric_cache_t * fabric_cache)
583 ibnd_port_cache_t *port_cache;
584 ibnd_port_cache_t *port_cache_next;
586 port_cache = fabric_cache->ports_cache;
588 ibnd_node_cache_t *node_cache;
589 ibnd_port_cache_t *remoteport_cache;
592 port_cache_next = port_cache->next;
594 port = port_cache->port;
597 _find_node(fabric_cache, port_cache->node_guid))) {
598 IBND_DEBUG("Cache invalid: cannot find node\n");
602 port->node = node_cache->node;
604 if (port_cache->remoteport_flag) {
605 if (!(remoteport_cache = _find_port(fabric_cache,
606 &port_cache->remoteport_cache_key)))
609 ("Cache invalid: cannot find remote port\n");
613 port->remoteport = remoteport_cache->port;
615 port->remoteport = NULL;
617 add_to_portlid_hash(port, fabric_cache->f_int->lid2guid);
618 port_cache = port_cache_next;
624 ibnd_fabric_t *ibnd_load_fabric(const char *file, unsigned int flags)
626 unsigned int node_count = 0;
627 unsigned int port_count = 0;
628 ibnd_fabric_cache_t *fabric_cache = NULL;
629 f_internal_t *f_int = NULL;
630 ibnd_node_cache_t *node_cache = NULL;
635 IBND_DEBUG("file parameter NULL\n");
639 if ((fd = open(file, O_RDONLY)) < 0) {
640 IBND_DEBUG("open: %s\n", strerror(errno));
645 (ibnd_fabric_cache_t *) malloc(sizeof(ibnd_fabric_cache_t));
647 IBND_DEBUG("OOM: fabric_cache\n");
650 memset(fabric_cache, '\0', sizeof(ibnd_fabric_cache_t));
652 f_int = allocate_fabric_internal();
654 IBND_DEBUG("OOM: fabric\n");
658 fabric_cache->f_int = f_int;
660 if (_load_header_info(fd, fabric_cache, &node_count, &port_count) < 0)
663 for (i = 0; i < node_count; i++) {
664 if (_load_node(fd, fabric_cache) < 0)
668 for (i = 0; i < port_count; i++) {
669 if (_load_port(fd, fabric_cache) < 0)
673 /* Special case - find from node */
675 _find_node(fabric_cache, fabric_cache->from_node_guid))) {
676 IBND_DEBUG("Cache invalid: cannot find from node\n");
679 f_int->fabric.from_node = node_cache->node;
681 if (_rebuild_nodes(fabric_cache) < 0)
684 if (_rebuild_ports(fabric_cache) < 0)
687 if (group_nodes(&f_int->fabric))
690 _destroy_ibnd_fabric_cache(fabric_cache);
692 return (ibnd_fabric_t *)&f_int->fabric;
695 ibnd_destroy_fabric((ibnd_fabric_t *)f_int);
696 _destroy_ibnd_fabric_cache(fabric_cache);
701 static ssize_t ibnd_write(int fd, const void *buf, size_t count)
703 size_t count_done = 0;
706 while ((count - count_done) > 0) {
707 ret = write(fd, ((char *) buf) + count_done, count - count_done);
712 IBND_DEBUG("write: %s\n", strerror(errno));
721 static size_t _marshall8(uint8_t * outbuf, uint8_t num)
725 return (sizeof(num));
728 static size_t _marshall16(uint8_t * outbuf, uint16_t num)
730 outbuf[0] = num & 0x00FF;
731 outbuf[1] = (num & 0xFF00) >> 8;
733 return (sizeof(num));
736 static size_t _marshall32(uint8_t * outbuf, uint32_t num)
738 outbuf[0] = num & 0x000000FF;
739 outbuf[1] = (num & 0x0000FF00) >> 8;
740 outbuf[2] = (num & 0x00FF0000) >> 16;
741 outbuf[3] = (num & 0xFF000000) >> 24;
743 return (sizeof(num));
746 static size_t _marshall64(uint8_t * outbuf, uint64_t num)
748 outbuf[0] = (uint8_t) num;
749 outbuf[1] = (uint8_t) (num >> 8);
750 outbuf[2] = (uint8_t) (num >> 16);
751 outbuf[3] = (uint8_t) (num >> 24);
752 outbuf[4] = (uint8_t) (num >> 32);
753 outbuf[5] = (uint8_t) (num >> 40);
754 outbuf[6] = (uint8_t) (num >> 48);
755 outbuf[7] = (uint8_t) (num >> 56);
757 return (sizeof(num));
760 static size_t _marshall_buf(void *outbuf, const void *inbuf, unsigned int len)
762 memcpy(outbuf, inbuf, len);
767 static int _cache_header_info(int fd, ibnd_fabric_t * fabric)
769 uint8_t buf[IBND_FABRIC_CACHE_BUFLEN];
772 /* Store magic number, version, and other important info */
773 /* For this caching lib, we always assume cached as little endian */
775 offset += _marshall32(buf + offset, IBND_FABRIC_CACHE_MAGIC);
776 offset += _marshall32(buf + offset, IBND_FABRIC_CACHE_VERSION);
777 /* save space for node count */
778 offset += _marshall32(buf + offset, 0);
779 /* save space for port count */
780 offset += _marshall32(buf + offset, 0);
781 offset += _marshall64(buf + offset, fabric->from_node->guid);
782 offset += _marshall32(buf + offset, fabric->maxhops_discovered);
784 if (ibnd_write(fd, buf, offset) < 0)
790 static int _cache_header_counts(int fd, unsigned int node_count,
791 unsigned int port_count)
793 uint8_t buf[IBND_FABRIC_CACHE_BUFLEN];
796 offset += _marshall32(buf + offset, node_count);
797 offset += _marshall32(buf + offset, port_count);
799 if (lseek(fd, IBND_FABRIC_CACHE_COUNT_OFFSET, SEEK_SET) < 0) {
800 IBND_DEBUG("lseek: %s\n", strerror(errno));
804 if (ibnd_write(fd, buf, offset) < 0)
810 static int _cache_node(int fd, ibnd_node_t * node)
812 uint8_t buf[IBND_FABRIC_CACHE_BUFLEN];
814 size_t ports_stored_offset = 0;
815 uint8_t ports_stored_count = 0;
818 offset += _marshall16(buf + offset, node->smalid);
819 offset += _marshall8(buf + offset, node->smalmc);
820 offset += _marshall8(buf + offset, (uint8_t) node->smaenhsp0);
821 offset += _marshall_buf(buf + offset, node->switchinfo,
823 offset += _marshall64(buf + offset, node->guid);
824 offset += _marshall8(buf + offset, (uint8_t) node->type);
825 offset += _marshall8(buf + offset, (uint8_t) node->numports);
826 offset += _marshall_buf(buf + offset, node->info, IB_SMP_DATA_SIZE);
827 offset += _marshall_buf(buf + offset, node->nodedesc, IB_SMP_DATA_SIZE);
828 /* need to come back later and store number of stored ports
829 * because port entries can be NULL or (in the case of switches)
830 * there is an additional port 0 not accounted for in numports.
832 ports_stored_offset = offset;
833 offset += sizeof(uint8_t);
835 for (i = 0; i <= node->numports; i++) {
836 if (node->ports[i]) {
837 offset += _marshall64(buf + offset,
838 node->ports[i]->guid);
839 offset += _marshall8(buf + offset,
840 (uint8_t) node->ports[i]->portnum);
841 ports_stored_count++;
845 /* go back and store number of port keys stored */
846 _marshall8(buf + ports_stored_offset, ports_stored_count);
848 if (ibnd_write(fd, buf, offset) < 0)
854 static int _cache_port(int fd, ibnd_port_t * port)
856 uint8_t buf[IBND_FABRIC_CACHE_BUFLEN];
859 offset += _marshall64(buf + offset, port->guid);
860 offset += _marshall8(buf + offset, (uint8_t) port->portnum);
861 offset += _marshall8(buf + offset, (uint8_t) port->ext_portnum);
862 offset += _marshall16(buf + offset, port->base_lid);
863 offset += _marshall8(buf + offset, port->lmc);
864 offset += _marshall_buf(buf + offset, port->info, IB_SMP_DATA_SIZE);
865 offset += _marshall64(buf + offset, port->node->guid);
866 if (port->remoteport) {
867 offset += _marshall8(buf + offset, 1);
868 offset += _marshall64(buf + offset, port->remoteport->guid);
869 offset += _marshall8(buf + offset, (uint8_t) port->remoteport->portnum);
871 offset += _marshall8(buf + offset, 0);
872 offset += _marshall64(buf + offset, 0);
873 offset += _marshall8(buf + offset, 0);
876 if (ibnd_write(fd, buf, offset) < 0)
882 int ibnd_cache_fabric(ibnd_fabric_t * fabric, const char *file,
886 ibnd_node_t *node = NULL;
887 ibnd_node_t *node_next = NULL;
888 unsigned int node_count = 0;
889 ibnd_port_t *port = NULL;
890 ibnd_port_t *port_next = NULL;
891 unsigned int port_count = 0;
896 IBND_DEBUG("fabric parameter NULL\n");
901 IBND_DEBUG("file parameter NULL\n");
905 if (!(flags & IBND_CACHE_FABRIC_FLAG_NO_OVERWRITE)) {
906 if (!stat(file, &statbuf)) {
907 if (unlink(file) < 0) {
908 IBND_DEBUG("error removing '%s': %s\n",
909 file, strerror(errno));
915 if (!stat(file, &statbuf)) {
916 IBND_DEBUG("file '%s' already exists\n", file);
921 if ((fd = open(file, O_CREAT | O_EXCL | O_WRONLY, 0644)) < 0) {
922 IBND_DEBUG("open: %s\n", strerror(errno));
926 if (_cache_header_info(fd, fabric) < 0)
929 node = fabric->nodes;
931 node_next = node->next;
933 if (_cache_node(fd, node) < 0)
940 for (i = 0; i < HTSZ; i++) {
941 port = fabric->portstbl[i];
943 port_next = port->htnext;
945 if (_cache_port(fd, port) < 0)
953 if (_cache_header_counts(fd, node_count, port_count) < 0)
957 IBND_DEBUG("close: %s\n", strerror(errno));