* [infiniband-diags] [UPDATED PATCH] [1/3] add libibnetdisc caching to libibnetdiscover
@ 2010-01-15 18:23 Al Chu
[not found] ` <1263579793.15172.166.camel-X2zTWyBD0EhliZ7u+bvwcg@public.gmane.org>
0 siblings, 1 reply; 5+ messages in thread
From: Al Chu @ 2010-01-15 18:23 UTC (permalink / raw)
To: sashak-smomgflXvOZWk0Htik3J/w; +Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA
[-- Attachment #1: Type: text/plain, Size: 282 bytes --]
Hi Sahsa,
This patch adds caching functionality to libibnetdisc through the new
functions ibnd_cache_fabric() and ibnd_load_fabric().
Al
--
Albert Chu
chu11-i2BcT+NCU+M@public.gmane.org
Computer Scientist
High Performance Systems Division
Lawrence Livermore National Laboratory
[-- Attachment #2: 0001-add-libibnetdisc-caching-to-libibnetdiscover.patch --]
[-- Type: text/plain, Size: 28617 bytes --]
From: Albert Chu <chu11-i2BcT+NCU+M@public.gmane.org>
Date: Wed, 9 Dec 2009 15:19:24 -0800
Subject: [PATCH] add libibnetdisc caching to libibnetdiscover
Signed-off-by: Albert Chu <chu11-i2BcT+NCU+M@public.gmane.org>
---
infiniband-diags/libibnetdisc/Makefile.am | 3 +-
.../libibnetdisc/include/infiniband/ibnetdisc.h | 6 +
infiniband-diags/libibnetdisc/src/ibnetdisc.c | 6 +-
.../libibnetdisc/src/ibnetdisc_cache.c | 909 ++++++++++++++++++++
infiniband-diags/libibnetdisc/src/internal.h | 6 +
infiniband-diags/libibnetdisc/src/libibnetdisc.map | 2 +
6 files changed, 928 insertions(+), 4 deletions(-)
create mode 100644 infiniband-diags/libibnetdisc/src/ibnetdisc_cache.c
diff --git a/infiniband-diags/libibnetdisc/Makefile.am b/infiniband-diags/libibnetdisc/Makefile.am
index 636d142..a46dbc8 100644
--- a/infiniband-diags/libibnetdisc/Makefile.am
+++ b/infiniband-diags/libibnetdisc/Makefile.am
@@ -22,7 +22,8 @@ else
libibnetdisc_version_script =
endif
-libibnetdisc_la_SOURCES = src/ibnetdisc.c src/chassis.c src/chassis.h src/internal.h
+libibnetdisc_la_SOURCES = src/ibnetdisc.c src/ibnetdisc_cache.c src/chassis.c \
+ src/chassis.h src/internal.h
libibnetdisc_la_CFLAGS = -Wall $(DBGFLAGS)
libibnetdisc_la_LDFLAGS = -version-info $(ibnetdisc_api_version) \
-export-dynamic $(libibnetdisc_version_script) \
diff --git a/infiniband-diags/libibnetdisc/include/infiniband/ibnetdisc.h b/infiniband-diags/libibnetdisc/include/infiniband/ibnetdisc.h
index 8d5ac39..38ca2fb 100644
--- a/infiniband-diags/libibnetdisc/include/infiniband/ibnetdisc.h
+++ b/infiniband-diags/libibnetdisc/include/infiniband/ibnetdisc.h
@@ -170,6 +170,12 @@ MAD_EXPORT ibnd_fabric_t *ibnd_discover_fabric(struct ibmad_port *ibmad_port,
*/
MAD_EXPORT void ibnd_destroy_fabric(ibnd_fabric_t * fabric);
+MAD_EXPORT ibnd_fabric_t *ibnd_load_fabric(const char *file,
+ unsigned int flags);
+
+MAD_EXPORT int ibnd_cache_fabric(ibnd_fabric_t *fabric, const char *file,
+ unsigned int flags);
+
/** =========================================================================
* Node operations
*/
diff --git a/infiniband-diags/libibnetdisc/src/ibnetdisc.c b/infiniband-diags/libibnetdisc/src/ibnetdisc.c
index 9367337..9b24931 100644
--- a/infiniband-diags/libibnetdisc/src/ibnetdisc.c
+++ b/infiniband-diags/libibnetdisc/src/ibnetdisc.c
@@ -286,7 +286,7 @@ ibnd_node_t *ibnd_find_node_dr(ibnd_fabric_t * fabric, char *dr_str)
return rc;
}
-static void add_to_nodeguid_hash(ibnd_node_t * node, ibnd_node_t * hash[])
+void add_to_nodeguid_hash(ibnd_node_t * node, ibnd_node_t * hash[])
{
int hash_idx = HASHGUID(node->guid) % HTSZ;
@@ -294,7 +294,7 @@ static void add_to_nodeguid_hash(ibnd_node_t * node, ibnd_node_t * hash[])
hash[hash_idx] = node;
}
-static void add_to_portguid_hash(ibnd_port_t * port, ibnd_port_t * hash[])
+void add_to_portguid_hash(ibnd_port_t * port, ibnd_port_t * hash[])
{
int hash_idx = HASHGUID(port->guid) % HTSZ;
@@ -302,7 +302,7 @@ static void add_to_portguid_hash(ibnd_port_t * port, ibnd_port_t * hash[])
hash[hash_idx] = port;
}
-static void add_to_type_list(ibnd_node_t * node, ibnd_fabric_t * fabric)
+void add_to_type_list(ibnd_node_t * node, ibnd_fabric_t * fabric)
{
switch (node->type) {
case IB_NODE_CA:
diff --git a/infiniband-diags/libibnetdisc/src/ibnetdisc_cache.c b/infiniband-diags/libibnetdisc/src/ibnetdisc_cache.c
new file mode 100644
index 0000000..403c053
--- /dev/null
+++ b/infiniband-diags/libibnetdisc/src/ibnetdisc_cache.c
@@ -0,0 +1,909 @@
+/*
+ * Copyright (c) 2004-2007 Voltaire Inc. All rights reserved.
+ * Copyright (c) 2007 Xsigo Systems Inc. All rights reserved.
+ * Copyright (c) 2008 Lawrence Livermore National Laboratory
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <inttypes.h>
+
+#include <infiniband/ibnetdisc.h>
+
+#include "internal.h"
+#include "chassis.h"
+
+/* For this caching lib, we always cache little endian */
+
+/* Cache format
+ *
+ * Bytes 1-4 - magic number
+ * Bytes 5-8 - version number
+ * Bytes 9-12 - node count
+ * Bytes 13-16 - port count
+ * Bytes 17-24 - "from node" guid
+ * Bytes 25-28 - maxhops discovered
+ * Bytes X-Y - nodes (variable length)
+ * Bytes X-Y - ports (variable length)
+ *
+ * Nodes are cached as
+ *
+ * 2 bytes - smalid
+ * 1 byte - smalmc
+ * 1 byte - smaenhsp0 flag
+ * IB_SMP_DATA_SIZE bytes - switchinfo
+ * 8 bytes - guid
+ * 1 byte - type
+ * 1 byte - numports
+ * IB_SMP_DATA_SIZE bytes - info
+ * IB_SMP_DATA_SIZE bytes - nodedesc
+ * 1 byte - number of ports stored
+ * 8 bytes - portguid A
+ * 1 byte - port num A
+ * 8 bytes - portguid B
+ * 1 byte - port num B
+ * ... etc., depending on number of ports stored
+ *
+ * Ports are cached as
+ *
+ * 8 bytes - guid
+ * 1 byte - portnum
+ * 1 byte - external portnum
+ * 2 bytes - base lid
+ * 1 byte - lmc
+ * IB_SMP_DATA_SIZE bytes - info
+ * 8 bytes - node guid port "owned" by
+ * 1 byte - flag indicating if remote port exists
+ * 8 bytes - port guid remotely connected to
+ * 1 byte - port num remotely connected to
+ */
+
+/* Structs that hold cache info temporarily before
+ * the real structs can be reconstructed.
+ */
+
+typedef struct ibnd_port_cache_key {
+ uint64_t guid;
+ uint8_t portnum;
+} ibnd_port_cache_key_t;
+
+typedef struct ibnd_node_cache {
+ ibnd_node_t *node;
+ uint8_t ports_stored_count;
+ ibnd_port_cache_key_t *port_cache_keys;
+ struct ibnd_node_cache *next;
+ struct ibnd_node_cache *htnext;
+} ibnd_node_cache_t;
+
+typedef struct ibnd_port_cache {
+ ibnd_port_t *port;
+ uint64_t node_guid;
+ uint8_t remoteport_flag;
+ ibnd_port_cache_key_t remoteport_cache_key;
+ struct ibnd_port_cache *next;
+ struct ibnd_port_cache *htnext;
+} ibnd_port_cache_t;
+
+typedef struct ibnd_fabric_cache {
+ ibnd_fabric_t *fabric;
+ uint64_t from_node_guid;
+ ibnd_node_cache_t *nodes_cache;
+ ibnd_port_cache_t *ports_cache;
+ ibnd_node_cache_t *nodescachetbl[HTSZ];
+ ibnd_port_cache_t *portscachetbl[HTSZ];
+} ibnd_fabric_cache_t;
+
+#define IBND_FABRIC_CACHE_BUFLEN 4096
+#define IBND_FABRIC_CACHE_MAGIC 0x8FE7832B
+#define IBND_FABRIC_CACHE_VERSION 0x00000001
+
+#define IBND_FABRIC_CACHE_COUNT_OFFSET 8
+
+#define IBND_FABRIC_CACHE_HEADER_LEN (28)
+#define IBND_NODE_CACHE_HEADER_LEN (15 + IB_SMP_DATA_SIZE*3)
+#define IBND_PORT_CACHE_KEY_LEN (8 + 1)
+#define IBND_PORT_CACHE_LEN (31 + IB_SMP_DATA_SIZE)
+
+static ssize_t _read(int fd, void *buf, size_t count)
+{
+ size_t count_done = 0;
+ ssize_t ret;
+
+ while ((count - count_done) > 0) {
+ ret = read(fd, buf + count_done, count - count_done);
+ if (ret < 0) {
+ if (errno == EINTR)
+ continue;
+ else {
+ IBND_DEBUG("read: %s\n", strerror(errno));
+ return -1;
+ }
+ }
+ if (!ret)
+ break;
+ count_done += ret;
+ }
+
+ if (count_done != count) {
+ IBND_DEBUG("read: read short\n");
+ return -1;
+ }
+
+ return count_done;
+}
+
+static size_t _unmarshall8(uint8_t *inbuf, uint8_t *num)
+{
+ (*num) = inbuf[0];
+
+ return (sizeof(*num));
+}
+
+static size_t _unmarshall16(uint8_t *inbuf, uint16_t *num)
+{
+ (*num) = (uint64_t)inbuf[0];
+ (*num) |= ((uint16_t)inbuf[1] << 8);
+
+ return (sizeof(*num));
+}
+
+static size_t _unmarshall32(uint8_t *inbuf, uint32_t *num)
+{
+ (*num) = (uint32_t)inbuf[0];
+ (*num) |= ((uint32_t)inbuf[1] << 8);
+ (*num) |= ((uint32_t)inbuf[2] << 16);
+ (*num) |= ((uint32_t)inbuf[3] << 24);
+
+ return (sizeof(*num));
+}
+
+static size_t _unmarshall64(uint8_t *inbuf, uint64_t *num)
+{
+ (*num) = (uint64_t)inbuf[0];
+ (*num) |= ((uint64_t)inbuf[1] << 8);
+ (*num) |= ((uint64_t)inbuf[2] << 16);
+ (*num) |= ((uint64_t)inbuf[3] << 24);
+ (*num) |= ((uint64_t)inbuf[4] << 32);
+ (*num) |= ((uint64_t)inbuf[5] << 40);
+ (*num) |= ((uint64_t)inbuf[6] << 48);
+ (*num) |= ((uint64_t)inbuf[7] << 56);
+
+ return (sizeof(*num));
+}
+
+static size_t _unmarshall_buf(const void *inbuf, void *outbuf, unsigned int len)
+{
+ memcpy(outbuf, inbuf, len);
+
+ return len;
+}
+
+static int _load_header_info(int fd,
+ ibnd_fabric_cache_t *fabric_cache,
+ unsigned int *node_count,
+ unsigned int *port_count)
+{
+ uint8_t buf[IBND_FABRIC_CACHE_BUFLEN];
+ uint32_t magic = 0;
+ uint32_t version = 0;
+ size_t offset = 0;
+ uint32_t tmp32;
+
+ if (_read(fd, buf, IBND_FABRIC_CACHE_HEADER_LEN) < 0)
+ return -1;
+
+ offset += _unmarshall32(buf + offset, &magic);
+
+ if (magic != IBND_FABRIC_CACHE_MAGIC) {
+ IBND_DEBUG("invalid fabric cache file\n");
+ return -1;
+ }
+
+ offset += _unmarshall32(buf + offset, &version);
+
+ if (version != IBND_FABRIC_CACHE_VERSION) {
+ IBND_DEBUG("invalid fabric cache version\n");
+ return -1;
+ }
+
+ offset += _unmarshall32(buf + offset, node_count);
+ offset += _unmarshall32(buf + offset, port_count);
+
+ offset += _unmarshall64(buf + offset, &fabric_cache->from_node_guid);
+ offset += _unmarshall32(buf + offset, &tmp32);
+ fabric_cache->fabric->maxhops_discovered = tmp32;
+
+ return 0;
+}
+
+static void _destroy_ibnd_node_cache(ibnd_node_cache_t *node_cache)
+{
+ free(node_cache->port_cache_keys);
+ free(node_cache);
+}
+
+static void _destroy_ibnd_fabric_cache(ibnd_fabric_cache_t *fabric_cache)
+{
+ ibnd_node_cache_t *node_cache;
+ ibnd_node_cache_t *node_cache_next;
+ ibnd_port_cache_t *port_cache;
+ ibnd_port_cache_t *port_cache_next;
+
+ if (!fabric_cache)
+ return;
+
+ node_cache = fabric_cache->nodes_cache;
+ while (node_cache) {
+ node_cache_next = node_cache->next;
+
+ _destroy_ibnd_node_cache(node_cache);
+
+ node_cache = node_cache_next;
+ }
+
+ port_cache = fabric_cache->ports_cache;
+ while (port_cache) {
+ port_cache_next = port_cache->next;
+
+ free(port_cache);
+
+ port_cache = port_cache_next;
+ }
+
+ free(fabric_cache);
+}
+
+static void store_node_cache(ibnd_node_cache_t *node_cache,
+ ibnd_fabric_cache_t *fabric_cache)
+{
+ int hash_indx = HASHGUID(node_cache->node->guid) % HTSZ;
+
+ node_cache->next = fabric_cache->nodes_cache;
+ fabric_cache->nodes_cache = node_cache;
+
+ node_cache->htnext = fabric_cache->nodescachetbl[hash_indx];
+ fabric_cache->nodescachetbl[hash_indx] = node_cache;
+}
+
+static int _load_node(int fd, ibnd_fabric_cache_t *fabric_cache)
+{
+ uint8_t buf[IBND_FABRIC_CACHE_BUFLEN];
+ ibnd_node_cache_t *node_cache = NULL;
+ ibnd_node_t *node = NULL;
+ size_t offset = 0;
+ uint8_t tmp8;
+
+ node_cache = (ibnd_node_cache_t *)malloc(sizeof(ibnd_node_cache_t));
+ if (!node_cache) {
+ IBND_DEBUG("OOM: node_cache\n");
+ return -1;
+ }
+ memset(node_cache, '\0', sizeof(ibnd_node_cache_t));
+
+ node = (ibnd_node_t *)malloc(sizeof(ibnd_node_t));
+ if (!node) {
+ IBND_DEBUG("OOM: node\n");
+ return -1;
+ }
+ memset(node, '\0', sizeof(ibnd_node_t));
+
+ node_cache->node = node;
+
+ if (_read(fd, buf, IBND_NODE_CACHE_HEADER_LEN) < 0)
+ goto cleanup;
+
+ offset += _unmarshall16(buf + offset, &node->smalid);
+ offset += _unmarshall8(buf + offset, &node->smalmc);
+ offset += _unmarshall8(buf + offset, &tmp8);
+ node->smaenhsp0 = tmp8;
+ offset += _unmarshall_buf(buf + offset, node->switchinfo, IB_SMP_DATA_SIZE);
+ offset += _unmarshall64(buf + offset, &node->guid);
+ offset += _unmarshall8(buf + offset, &tmp8);
+ node->type = tmp8;
+ offset += _unmarshall8(buf + offset, &tmp8);
+ node->numports = tmp8;
+ offset += _unmarshall_buf(buf + offset, node->info, IB_SMP_DATA_SIZE);
+ offset += _unmarshall_buf(buf + offset, node->nodedesc, IB_SMP_DATA_SIZE);
+
+ offset += _unmarshall8(buf + offset, &node_cache->ports_stored_count);
+
+ if (node_cache->ports_stored_count) {
+ unsigned int tomalloc = 0;
+ unsigned int toread = 0;
+ unsigned int i;
+
+ tomalloc = sizeof(ibnd_port_cache_key_t) * node_cache->ports_stored_count;
+
+ toread = IBND_PORT_CACHE_KEY_LEN * node_cache->ports_stored_count;
+
+ node_cache->port_cache_keys = (ibnd_port_cache_key_t *)malloc(tomalloc);
+ if (!node_cache->port_cache_keys) {
+ IBND_DEBUG("OOM: node_cache port_cache_keys\n");
+ goto cleanup;
+ }
+
+ if (_read(fd, buf, toread) < 0)
+ goto cleanup;
+
+ offset = 0;
+
+ for (i = 0; i < node_cache->ports_stored_count; i++) {
+ offset += _unmarshall64(buf + offset,
+ &node_cache->port_cache_keys[i].guid);
+ offset += _unmarshall8(buf + offset,
+ &node_cache->port_cache_keys[i].portnum);
+ }
+ }
+
+ store_node_cache(node_cache, fabric_cache);
+
+ return 0;
+
+cleanup:
+ /* note, no need to destroy node through destroy_node(), nothing else malloced */
+ free(node);
+ _destroy_ibnd_node_cache(node_cache);
+ return -1;
+}
+
+static void store_port_cache(ibnd_port_cache_t *port_cache,
+ ibnd_fabric_cache_t *fabric_cache)
+{
+ int hash_indx = HASHGUID(port_cache->port->guid) % HTSZ;
+
+ port_cache->next = fabric_cache->ports_cache;
+ fabric_cache->ports_cache = port_cache;
+
+ port_cache->htnext = fabric_cache->portscachetbl[hash_indx];
+ fabric_cache->portscachetbl[hash_indx] = port_cache;
+}
+
+static int _load_port(int fd, ibnd_fabric_cache_t *fabric_cache)
+{
+ uint8_t buf[IBND_FABRIC_CACHE_BUFLEN];
+ ibnd_port_cache_t *port_cache = NULL;
+ ibnd_port_t *port = NULL;
+ size_t offset = 0;
+ uint8_t tmp8;
+
+ port_cache = (ibnd_port_cache_t *)malloc(sizeof(ibnd_port_cache_t));
+ if (!port_cache) {
+ IBND_DEBUG("OOM: port_cache\n");
+ return -1;
+ }
+ memset(port_cache, '\0', sizeof(ibnd_port_cache_t));
+
+ port = (ibnd_port_t *)malloc(sizeof(ibnd_port_t));
+ if (!port) {
+ IBND_DEBUG("OOM: port\n");
+ return -1;
+ }
+ memset(port, '\0', sizeof(ibnd_port_t));
+
+ port_cache->port = port;
+
+ if (_read(fd, buf, IBND_PORT_CACHE_LEN) < 0)
+ goto cleanup;
+
+ offset += _unmarshall64(buf + offset, &port->guid);
+ offset += _unmarshall8(buf + offset, &tmp8);
+ port->portnum = tmp8;
+ offset += _unmarshall8(buf + offset, &tmp8);
+ port->ext_portnum = tmp8;
+ offset += _unmarshall16(buf + offset, &port->base_lid);
+ offset += _unmarshall8(buf + offset, &port->lmc);
+ offset += _unmarshall_buf(buf + offset, port->info, IB_SMP_DATA_SIZE);
+ offset += _unmarshall64(buf + offset, &port_cache->node_guid);
+ offset += _unmarshall8(buf + offset, &port_cache->remoteport_flag);
+ offset += _unmarshall64(buf + offset, &port_cache->remoteport_cache_key.guid);
+ offset += _unmarshall8(buf + offset, &port_cache->remoteport_cache_key.portnum);
+
+ store_port_cache(port_cache, fabric_cache);
+
+ return 0;
+
+cleanup:
+ free(port);
+ free(port_cache);
+ return -1;
+}
+
+static ibnd_port_cache_t * _find_port(ibnd_fabric_cache_t *fabric_cache,
+ ibnd_port_cache_key_t *port_cache_key)
+{
+ int hash_indx = HASHGUID(port_cache_key->guid) % HTSZ;
+ ibnd_port_cache_t *port_cache;
+
+ for (port_cache = fabric_cache->portscachetbl[hash_indx];
+ port_cache;
+ port_cache = port_cache->htnext) {
+ if (port_cache->port->guid == port_cache_key->guid
+ && port_cache->port->portnum == port_cache_key->portnum)
+ return port_cache;
+ }
+
+ return NULL;
+}
+
+static ibnd_node_cache_t * _find_node(ibnd_fabric_cache_t *fabric_cache,
+ uint64_t guid)
+{
+ int hash_indx = HASHGUID(guid) % HTSZ;
+ ibnd_node_cache_t *node_cache;
+
+ for (node_cache = fabric_cache->nodescachetbl[hash_indx];
+ node_cache;
+ node_cache = node_cache->htnext) {
+ if (node_cache->node->guid == guid)
+ return node_cache;
+ }
+
+ return NULL;
+}
+
+static int _fill_port(ibnd_fabric_cache_t *fabric_cache,
+ ibnd_node_t *node,
+ ibnd_port_cache_key_t *port_cache_key)
+{
+ ibnd_port_cache_t *port_cache;
+
+ if (!(port_cache = _find_port(fabric_cache, port_cache_key))) {
+ IBND_DEBUG("Cache invalid: cannot find port\n");
+ return -1;
+ }
+
+ node->ports[port_cache->port->portnum] = port_cache->port;
+
+ return 0;
+}
+
+static int _rebuild_nodes(ibnd_fabric_cache_t *fabric_cache)
+{
+ ibnd_node_cache_t *node_cache;
+ ibnd_node_cache_t *node_cache_next;
+
+ node_cache = fabric_cache->nodes_cache;
+ while (node_cache) {
+ ibnd_node_t *node;
+ int i;
+
+ node_cache_next = node_cache->next;
+
+ node = node_cache->node;
+
+ /* Insert node into appropriate data structures */
+
+ node->next = fabric_cache->fabric->nodes;
+ fabric_cache->fabric->nodes = node;
+
+ add_to_nodeguid_hash(node_cache->node, fabric_cache->fabric->nodestbl);
+
+ add_to_type_list(node_cache->node, fabric_cache->fabric);
+
+ /* Rebuild node ports array */
+
+ if (!(node->ports = calloc(sizeof(*node->ports), node->numports + 1))) {
+ IBND_DEBUG("OOM: node->ports\n");
+ return -1;
+ }
+
+ for (i = 0; i < node_cache->ports_stored_count; i++) {
+ if (_fill_port(fabric_cache, node, &node_cache->port_cache_keys[i]) < 0)
+ return -1;
+ }
+
+ node_cache = node_cache_next;
+ }
+
+ return 0;
+}
+
+static int _rebuild_ports(ibnd_fabric_cache_t *fabric_cache)
+{
+ ibnd_port_cache_t *port_cache;
+ ibnd_port_cache_t *port_cache_next;
+
+ port_cache = fabric_cache->ports_cache;
+ while (port_cache) {
+ ibnd_node_cache_t *node_cache;
+ ibnd_port_cache_t *remoteport_cache;
+ ibnd_port_t *port;
+
+ port_cache_next = port_cache->next;
+
+ port = port_cache->port;
+
+ if (!(node_cache = _find_node(fabric_cache, port_cache->node_guid))) {
+ IBND_DEBUG("Cache invalid: cannot find node\n");
+ return -1;
+ }
+
+ port->node = node_cache->node;
+
+ if (port_cache->remoteport_flag) {
+ if (!(remoteport_cache = _find_port(fabric_cache,
+ &port_cache->remoteport_cache_key))) {
+ IBND_DEBUG("Cache invalid: cannot find remote port\n");
+ return -1;
+ }
+
+ port->remoteport = remoteport_cache->port;
+ }
+ else
+ port->remoteport = NULL;
+
+ port_cache = port_cache_next;
+ }
+
+ return 0;
+}
+
+ibnd_fabric_t *ibnd_load_fabric(const char *file, unsigned int flags)
+{
+ unsigned int node_count = 0;
+ unsigned int port_count = 0;
+ ibnd_fabric_cache_t *fabric_cache = NULL;
+ ibnd_fabric_t *fabric = NULL;
+ ibnd_node_cache_t *node_cache = NULL;
+ int fd = -1;
+ unsigned int i;
+
+ if (!file) {
+ IBND_DEBUG("file parameter NULL\n");
+ return NULL;
+ }
+
+ if ((fd = open(file, O_RDONLY)) < 0) {
+ IBND_DEBUG("open: %s\n", strerror(errno));
+ return NULL;
+ }
+
+ fabric_cache = (ibnd_fabric_cache_t *)malloc(sizeof(ibnd_fabric_cache_t));
+ if (!fabric_cache) {
+ IBND_DEBUG("OOM: fabric_cache\n");
+ goto cleanup;
+ }
+ memset(fabric_cache, '\0', sizeof(ibnd_fabric_cache_t));
+
+ fabric = (ibnd_fabric_t *)malloc(sizeof(ibnd_fabric_t));
+ if (!fabric) {
+ IBND_DEBUG("OOM: fabric\n");
+ goto cleanup;
+ }
+ memset(fabric, '\0', sizeof(ibnd_fabric_t));
+
+ fabric_cache->fabric = fabric;
+
+ if (_load_header_info(fd, fabric_cache, &node_count, &port_count) < 0)
+ goto cleanup;
+
+ for (i = 0; i < node_count; i++) {
+ if (_load_node(fd, fabric_cache) < 0)
+ goto cleanup;
+ }
+
+ for (i = 0; i < port_count; i++) {
+ if (_load_port(fd, fabric_cache) < 0)
+ goto cleanup;
+ }
+
+ /* Special case - find from node */
+ if (!(node_cache = _find_node(fabric_cache, fabric_cache->from_node_guid))) {
+ IBND_DEBUG("Cache invalid: cannot find from node\n");
+ goto cleanup;
+ }
+ fabric->from_node = node_cache->node;
+
+ if (_rebuild_nodes(fabric_cache) < 0)
+ goto cleanup;
+
+ if (_rebuild_ports(fabric_cache) < 0)
+ goto cleanup;
+
+ if (group_nodes(fabric))
+ goto cleanup;
+
+ _destroy_ibnd_fabric_cache(fabric_cache);
+ close(fd);
+ return fabric;
+
+cleanup:
+ ibnd_destroy_fabric(fabric);
+ _destroy_ibnd_fabric_cache(fabric_cache);
+ close(fd);
+ return NULL;
+}
+
+static ssize_t _write(int fd, const void *buf, size_t count)
+{
+ size_t count_done = 0;
+ ssize_t ret;
+
+ while ((count - count_done) > 0) {
+ ret = write(fd, buf + count_done, count - count_done);
+ if (ret < 0) {
+ if (errno == EINTR)
+ continue;
+ else {
+ IBND_DEBUG("write: %s\n", strerror(errno));
+ return -1;
+ }
+ }
+ count_done += ret;
+ }
+ return count_done;
+}
+
+
+static size_t _marshall8(uint8_t *outbuf, uint8_t num)
+{
+ outbuf[0] = num;
+
+ return (sizeof(num));
+}
+
+static size_t _marshall16(uint8_t *outbuf, uint16_t num)
+{
+ outbuf[0] = num & 0x00FF;
+ outbuf[1] = (num & 0xFF00) >> 8;
+
+ return (sizeof(num));
+}
+
+static size_t _marshall32(uint8_t *outbuf, uint32_t num)
+{
+ outbuf[0] = num & 0x000000FF;
+ outbuf[1] = (num & 0x0000FF00) >> 8;
+ outbuf[2] = (num & 0x00FF0000) >> 16;
+ outbuf[3] = (num & 0xFF000000) >> 24;
+
+ return (sizeof(num));
+}
+
+static size_t _marshall64(uint8_t *outbuf, uint64_t num)
+{
+ outbuf[0] = num & 0x00000000000000FFULL;
+ outbuf[1] = (num & 0x000000000000FF00ULL) >> 8;
+ outbuf[2] = (num & 0x0000000000FF0000ULL) >> 16;
+ outbuf[3] = (num & 0x00000000FF000000ULL) >> 24;
+ outbuf[4] = (num & 0x000000FF00000000ULL) >> 32;
+ outbuf[5] = (num & 0x0000FF0000000000ULL) >> 40;
+ outbuf[6] = (num & 0x00FF000000000000ULL) >> 48;
+ outbuf[7] = (num & 0xFF00000000000000ULL) >> 56;
+
+ return (sizeof(num));
+}
+
+static size_t _marshall_buf(void *outbuf, const void *inbuf, unsigned int len)
+{
+ memcpy(outbuf, inbuf, len);
+
+ return len;
+}
+
+static int _cache_header_info(int fd, ibnd_fabric_t *fabric)
+{
+ uint8_t buf[IBND_FABRIC_CACHE_BUFLEN];
+ size_t offset = 0;
+
+ /* Store magic number, version, and other important info */
+ /* For this caching lib, we always assume cached as little endian */
+
+ offset += _marshall32(buf + offset, IBND_FABRIC_CACHE_MAGIC);
+ offset += _marshall32(buf + offset, IBND_FABRIC_CACHE_VERSION);
+ /* save space for node count */
+ offset += _marshall32(buf + offset, 0);
+ /* save space for port count */
+ offset += _marshall32(buf + offset, 0);
+ offset += _marshall64(buf + offset, fabric->from_node->guid);
+ offset += _marshall32(buf + offset, fabric->maxhops_discovered);
+
+ if (_write(fd, buf, offset) < 0)
+ return -1;
+
+ return 0;
+}
+
+static int _cache_header_counts(int fd, unsigned int node_count, unsigned int port_count)
+{
+ uint8_t buf[IBND_FABRIC_CACHE_BUFLEN];
+ size_t offset = 0;
+
+ offset += _marshall32(buf + offset, node_count);
+ offset += _marshall32(buf + offset, port_count);
+
+ if (lseek(fd, IBND_FABRIC_CACHE_COUNT_OFFSET, SEEK_SET) < 0) {
+ IBND_DEBUG("lseek: %s\n", strerror(errno));
+ return -1;
+ }
+
+ if (_write(fd, buf, offset) < 0)
+ return -1;
+
+ return 0;
+}
+
+static int _cache_node(int fd, ibnd_node_t *node)
+{
+ uint8_t buf[IBND_FABRIC_CACHE_BUFLEN];
+ size_t offset = 0;
+ size_t ports_stored_offset = 0;
+ unsigned int ports_stored_count = 0;
+ unsigned int i;
+
+ offset += _marshall16(buf + offset, node->smalid);
+ offset += _marshall8(buf + offset, node->smalmc);
+ offset += _marshall8(buf + offset, node->smaenhsp0);
+ offset += _marshall_buf(buf + offset, node->switchinfo, IB_SMP_DATA_SIZE);
+ offset += _marshall64(buf + offset, node->guid);
+ offset += _marshall8(buf + offset, node->type);
+ offset += _marshall8(buf + offset, node->numports);
+ offset += _marshall_buf(buf + offset, node->info, IB_SMP_DATA_SIZE);
+ offset += _marshall_buf(buf + offset, node->nodedesc, IB_SMP_DATA_SIZE);
+ /* need to come back later and store number of stored ports
+ * because port entries can be NULL or (in the case of switches)
+ * there is an additional port 0 not accounted for in numports.
+ */
+ ports_stored_offset = offset;
+ offset += sizeof(uint8_t);
+
+ for (i = 0; i <= node->numports; i++) {
+ if (node->ports[i]) {
+ offset += _marshall64(buf + offset, node->ports[i]->guid);
+ offset += _marshall8(buf + offset, node->ports[i]->portnum);
+ ports_stored_count++;
+ }
+ }
+
+ /* go back and store number of port keys stored */
+ _marshall8(buf + ports_stored_offset, ports_stored_count);
+
+ if (_write(fd, buf, offset) < 0)
+ return -1;
+
+ return 0;
+}
+
+static int _cache_port(int fd, ibnd_port_t *port)
+{
+ uint8_t buf[IBND_FABRIC_CACHE_BUFLEN];
+ size_t offset = 0;
+
+ offset += _marshall64(buf + offset, port->guid);
+ offset += _marshall8(buf + offset, port->portnum);
+ offset += _marshall8(buf + offset, port->ext_portnum);
+ offset += _marshall16(buf + offset, port->base_lid);
+ offset += _marshall8(buf + offset, port->lmc);
+ offset += _marshall_buf(buf + offset, port->info, IB_SMP_DATA_SIZE);
+ offset += _marshall64(buf + offset, port->node->guid);
+ if (port->remoteport) {
+ offset += _marshall8(buf + offset, 1);
+ offset += _marshall64(buf + offset, port->remoteport->guid);
+ offset += _marshall8(buf + offset, port->remoteport->portnum);
+ }
+ else {
+ offset += _marshall8(buf + offset, 0);
+ offset += _marshall64(buf + offset, 0);
+ offset += _marshall8(buf + offset, 0);
+ }
+
+ if (_write(fd, buf, offset) < 0)
+ return -1;
+
+ return 0;
+}
+
+int ibnd_cache_fabric(ibnd_fabric_t *fabric, const char *file, unsigned int flags)
+{
+ struct stat statbuf;
+ ibnd_node_t *node = NULL;
+ ibnd_node_t *node_next = NULL;
+ unsigned int node_count = 0;
+ ibnd_port_t *port = NULL;
+ ibnd_port_t *port_next = NULL;
+ unsigned int port_count = 0;
+ int fd;
+ int i;
+
+ if (!fabric) {
+ IBND_DEBUG("fabric parameter NULL\n");
+ return -1;
+ }
+
+ if (!file) {
+ IBND_DEBUG("file parameter NULL\n");
+ return -1;
+ }
+
+ if (!stat(file, &statbuf)) {
+ IBND_DEBUG("file '%s' already exists\n", file);
+ return -1;
+ }
+
+ if ((fd = open(file, O_CREAT | O_EXCL | O_WRONLY, 0644)) < 0) {
+ IBND_DEBUG("open: %s\n", strerror(errno));
+ return -1;
+ }
+
+ if (_cache_header_info(fd, fabric) < 0)
+ goto cleanup;
+
+ node = fabric->nodes;
+ while (node) {
+ node_next = node->next;
+
+ if (_cache_node(fd, node) < 0)
+ goto cleanup;
+
+ node_count++;
+ node = node_next;
+ }
+
+ for (i = 0; i < HTSZ; i++) {
+ port = fabric->portstbl[i];
+ while (port) {
+ port_next = port->htnext;
+
+ if (_cache_port(fd, port) < 0)
+ goto cleanup;
+
+ port_count++;
+ port = port_next;
+ }
+ }
+
+ if (_cache_header_counts(fd, node_count, port_count) < 0)
+ goto cleanup;
+
+ if (close(fd) < 0) {
+ IBND_DEBUG("close: %s\n", strerror(errno));
+ goto cleanup;
+ }
+
+ return 0;
+
+cleanup:
+ unlink(file);
+ close(fd);
+ return -1;
+}
diff --git a/infiniband-diags/libibnetdisc/src/internal.h b/infiniband-diags/libibnetdisc/src/internal.h
index 5af5f10..348bd0f 100644
--- a/infiniband-diags/libibnetdisc/src/internal.h
+++ b/infiniband-diags/libibnetdisc/src/internal.h
@@ -62,4 +62,10 @@ typedef struct ibnd_scan {
ib_portid_t selfportid;
} ibnd_scan_t;
+void add_to_nodeguid_hash(ibnd_node_t * node, ibnd_node_t * hash[]);
+
+void add_to_portguid_hash(ibnd_port_t * port, ibnd_port_t * hash[]);
+
+void add_to_type_list(ibnd_node_t * node, ibnd_fabric_t * fabric);
+
#endif /* _INTERNAL_H_ */
diff --git a/infiniband-diags/libibnetdisc/src/libibnetdisc.map b/infiniband-diags/libibnetdisc/src/libibnetdisc.map
index 13bb65a..888bdd8 100644
--- a/infiniband-diags/libibnetdisc/src/libibnetdisc.map
+++ b/infiniband-diags/libibnetdisc/src/libibnetdisc.map
@@ -4,6 +4,8 @@ IBNETDISC_1.0 {
ibnd_show_progress;
ibnd_discover_fabric;
ibnd_destroy_fabric;
+ ibnd_load_fabric;
+ ibnd_cache_fabric;
ibnd_find_node_guid;
ibnd_find_node_dr;
ibnd_is_xsigo_guid;
--
1.5.4.5
^ permalink raw reply related [flat|nested] 5+ messages in thread[parent not found: <1263579793.15172.166.camel-X2zTWyBD0EhliZ7u+bvwcg@public.gmane.org>]
* Re: [infiniband-diags] [UPDATED PATCH] [1/3] add libibnetdisc caching to libibnetdiscover [not found] ` <1263579793.15172.166.camel-X2zTWyBD0EhliZ7u+bvwcg@public.gmane.org> @ 2010-01-16 14:12 ` Sasha Khapyorsky 2010-01-16 16:11 ` Al Chu 2010-01-16 14:49 ` Sasha Khapyorsky 1 sibling, 1 reply; 5+ messages in thread From: Sasha Khapyorsky @ 2010-01-16 14:12 UTC (permalink / raw) To: Al Chu; +Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA Hi Al, On 10:23 Fri 15 Jan , Al Chu wrote: > Hi Sahsa, > > This patch adds caching functionality to libibnetdisc through the new > functions ibnd_cache_fabric() and ibnd_load_fabric(). > > Al > > -- > Albert Chu > chu11-i2BcT+NCU+M@public.gmane.org > Computer Scientist > High Performance Systems Division > Lawrence Livermore National Laboratory > From: Albert Chu <chu11-i2BcT+NCU+M@public.gmane.org> > Date: Wed, 9 Dec 2009 15:19:24 -0800 > Subject: [PATCH] add libibnetdisc caching to libibnetdiscover > > > Signed-off-by: Albert Chu <chu11-i2BcT+NCU+M@public.gmane.org> > --- > infiniband-diags/libibnetdisc/Makefile.am | 3 +- > .../libibnetdisc/include/infiniband/ibnetdisc.h | 6 + > infiniband-diags/libibnetdisc/src/ibnetdisc.c | 6 +- > .../libibnetdisc/src/ibnetdisc_cache.c | 909 ++++++++++++++++++++ > infiniband-diags/libibnetdisc/src/internal.h | 6 + > infiniband-diags/libibnetdisc/src/libibnetdisc.map | 2 + > 6 files changed, 928 insertions(+), 4 deletions(-) > create mode 100644 infiniband-diags/libibnetdisc/src/ibnetdisc_cache.c > > diff --git a/infiniband-diags/libibnetdisc/Makefile.am b/infiniband-diags/libibnetdisc/Makefile.am > index 636d142..a46dbc8 100644 > --- a/infiniband-diags/libibnetdisc/Makefile.am > +++ b/infiniband-diags/libibnetdisc/Makefile.am > @@ -22,7 +22,8 @@ else > libibnetdisc_version_script = > endif > > -libibnetdisc_la_SOURCES = src/ibnetdisc.c src/chassis.c src/chassis.h src/internal.h > +libibnetdisc_la_SOURCES = src/ibnetdisc.c src/ibnetdisc_cache.c src/chassis.c \ > + src/chassis.h src/internal.h > libibnetdisc_la_CFLAGS = -Wall $(DBGFLAGS) > libibnetdisc_la_LDFLAGS = -version-info $(ibnetdisc_api_version) \ > -export-dynamic $(libibnetdisc_version_script) \ > diff --git a/infiniband-diags/libibnetdisc/include/infiniband/ibnetdisc.h b/infiniband-diags/libibnetdisc/include/infiniband/ibnetdisc.h > index 8d5ac39..38ca2fb 100644 > --- a/infiniband-diags/libibnetdisc/include/infiniband/ibnetdisc.h > +++ b/infiniband-diags/libibnetdisc/include/infiniband/ibnetdisc.h > @@ -170,6 +170,12 @@ MAD_EXPORT ibnd_fabric_t *ibnd_discover_fabric(struct ibmad_port *ibmad_port, > */ > MAD_EXPORT void ibnd_destroy_fabric(ibnd_fabric_t * fabric); > > +MAD_EXPORT ibnd_fabric_t *ibnd_load_fabric(const char *file, > + unsigned int flags); > + > +MAD_EXPORT int ibnd_cache_fabric(ibnd_fabric_t *fabric, const char *file, > + unsigned int flags); > + What is the purpose of 'flags' parameter (I see that this is not used in any place)? Sasha > /** ========================================================================= > * Node operations > */ > diff --git a/infiniband-diags/libibnetdisc/src/ibnetdisc.c b/infiniband-diags/libibnetdisc/src/ibnetdisc.c > index 9367337..9b24931 100644 > --- a/infiniband-diags/libibnetdisc/src/ibnetdisc.c > +++ b/infiniband-diags/libibnetdisc/src/ibnetdisc.c > @@ -286,7 +286,7 @@ ibnd_node_t *ibnd_find_node_dr(ibnd_fabric_t * fabric, char *dr_str) > return rc; > } > > -static void add_to_nodeguid_hash(ibnd_node_t * node, ibnd_node_t * hash[]) > +void add_to_nodeguid_hash(ibnd_node_t * node, ibnd_node_t * hash[]) > { > int hash_idx = HASHGUID(node->guid) % HTSZ; > > @@ -294,7 +294,7 @@ static void add_to_nodeguid_hash(ibnd_node_t * node, ibnd_node_t * hash[]) > hash[hash_idx] = node; > } > > -static void add_to_portguid_hash(ibnd_port_t * port, ibnd_port_t * hash[]) > +void add_to_portguid_hash(ibnd_port_t * port, ibnd_port_t * hash[]) > { > int hash_idx = HASHGUID(port->guid) % HTSZ; > > @@ -302,7 +302,7 @@ static void add_to_portguid_hash(ibnd_port_t * port, ibnd_port_t * hash[]) > hash[hash_idx] = port; > } > > -static void add_to_type_list(ibnd_node_t * node, ibnd_fabric_t * fabric) > +void add_to_type_list(ibnd_node_t * node, ibnd_fabric_t * fabric) > { > switch (node->type) { > case IB_NODE_CA: > diff --git a/infiniband-diags/libibnetdisc/src/ibnetdisc_cache.c b/infiniband-diags/libibnetdisc/src/ibnetdisc_cache.c > new file mode 100644 > index 0000000..403c053 > --- /dev/null > +++ b/infiniband-diags/libibnetdisc/src/ibnetdisc_cache.c > @@ -0,0 +1,909 @@ > +/* > + * Copyright (c) 2004-2007 Voltaire Inc. All rights reserved. > + * Copyright (c) 2007 Xsigo Systems Inc. All rights reserved. > + * Copyright (c) 2008 Lawrence Livermore National Laboratory > + * > + * This software is available to you under a choice of one of two > + * licenses. You may choose to be licensed under the terms of the GNU > + * General Public License (GPL) Version 2, available from the file > + * COPYING in the main directory of this source tree, or the > + * OpenIB.org BSD license below: > + * > + * Redistribution and use in source and binary forms, with or > + * without modification, are permitted provided that the following > + * conditions are met: > + * > + * - Redistributions of source code must retain the above > + * copyright notice, this list of conditions and the following > + * disclaimer. > + * > + * - Redistributions in binary form must reproduce the above > + * copyright notice, this list of conditions and the following > + * disclaimer in the documentation and/or other materials > + * provided with the distribution. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, > + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF > + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND > + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS > + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN > + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN > + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE > + * SOFTWARE. > + * > + */ > + > +#if HAVE_CONFIG_H > +# include <config.h> > +#endif /* HAVE_CONFIG_H */ > + > +#define _GNU_SOURCE > +#include <stdio.h> > +#include <stdlib.h> > +#include <sys/types.h> > +#include <sys/stat.h> > +#include <unistd.h> > +#include <fcntl.h> > +#include <string.h> > +#include <errno.h> > +#include <inttypes.h> > + > +#include <infiniband/ibnetdisc.h> > + > +#include "internal.h" > +#include "chassis.h" > + > +/* For this caching lib, we always cache little endian */ > + > +/* Cache format > + * > + * Bytes 1-4 - magic number > + * Bytes 5-8 - version number > + * Bytes 9-12 - node count > + * Bytes 13-16 - port count > + * Bytes 17-24 - "from node" guid > + * Bytes 25-28 - maxhops discovered > + * Bytes X-Y - nodes (variable length) > + * Bytes X-Y - ports (variable length) > + * > + * Nodes are cached as > + * > + * 2 bytes - smalid > + * 1 byte - smalmc > + * 1 byte - smaenhsp0 flag > + * IB_SMP_DATA_SIZE bytes - switchinfo > + * 8 bytes - guid > + * 1 byte - type > + * 1 byte - numports > + * IB_SMP_DATA_SIZE bytes - info > + * IB_SMP_DATA_SIZE bytes - nodedesc > + * 1 byte - number of ports stored > + * 8 bytes - portguid A > + * 1 byte - port num A > + * 8 bytes - portguid B > + * 1 byte - port num B > + * ... etc., depending on number of ports stored > + * > + * Ports are cached as > + * > + * 8 bytes - guid > + * 1 byte - portnum > + * 1 byte - external portnum > + * 2 bytes - base lid > + * 1 byte - lmc > + * IB_SMP_DATA_SIZE bytes - info > + * 8 bytes - node guid port "owned" by > + * 1 byte - flag indicating if remote port exists > + * 8 bytes - port guid remotely connected to > + * 1 byte - port num remotely connected to > + */ > + > +/* Structs that hold cache info temporarily before > + * the real structs can be reconstructed. > + */ > + > +typedef struct ibnd_port_cache_key { > + uint64_t guid; > + uint8_t portnum; > +} ibnd_port_cache_key_t; > + > +typedef struct ibnd_node_cache { > + ibnd_node_t *node; > + uint8_t ports_stored_count; > + ibnd_port_cache_key_t *port_cache_keys; > + struct ibnd_node_cache *next; > + struct ibnd_node_cache *htnext; > +} ibnd_node_cache_t; > + > +typedef struct ibnd_port_cache { > + ibnd_port_t *port; > + uint64_t node_guid; > + uint8_t remoteport_flag; > + ibnd_port_cache_key_t remoteport_cache_key; > + struct ibnd_port_cache *next; > + struct ibnd_port_cache *htnext; > +} ibnd_port_cache_t; > + > +typedef struct ibnd_fabric_cache { > + ibnd_fabric_t *fabric; > + uint64_t from_node_guid; > + ibnd_node_cache_t *nodes_cache; > + ibnd_port_cache_t *ports_cache; > + ibnd_node_cache_t *nodescachetbl[HTSZ]; > + ibnd_port_cache_t *portscachetbl[HTSZ]; > +} ibnd_fabric_cache_t; > + > +#define IBND_FABRIC_CACHE_BUFLEN 4096 > +#define IBND_FABRIC_CACHE_MAGIC 0x8FE7832B > +#define IBND_FABRIC_CACHE_VERSION 0x00000001 > + > +#define IBND_FABRIC_CACHE_COUNT_OFFSET 8 > + > +#define IBND_FABRIC_CACHE_HEADER_LEN (28) > +#define IBND_NODE_CACHE_HEADER_LEN (15 + IB_SMP_DATA_SIZE*3) > +#define IBND_PORT_CACHE_KEY_LEN (8 + 1) > +#define IBND_PORT_CACHE_LEN (31 + IB_SMP_DATA_SIZE) > + > +static ssize_t _read(int fd, void *buf, size_t count) > +{ > + size_t count_done = 0; > + ssize_t ret; > + > + while ((count - count_done) > 0) { > + ret = read(fd, buf + count_done, count - count_done); > + if (ret < 0) { > + if (errno == EINTR) > + continue; > + else { > + IBND_DEBUG("read: %s\n", strerror(errno)); > + return -1; > + } > + } > + if (!ret) > + break; > + count_done += ret; > + } > + > + if (count_done != count) { > + IBND_DEBUG("read: read short\n"); > + return -1; > + } > + > + return count_done; > +} > + > +static size_t _unmarshall8(uint8_t *inbuf, uint8_t *num) > +{ > + (*num) = inbuf[0]; > + > + return (sizeof(*num)); > +} > + > +static size_t _unmarshall16(uint8_t *inbuf, uint16_t *num) > +{ > + (*num) = (uint64_t)inbuf[0]; > + (*num) |= ((uint16_t)inbuf[1] << 8); > + > + return (sizeof(*num)); > +} > + > +static size_t _unmarshall32(uint8_t *inbuf, uint32_t *num) > +{ > + (*num) = (uint32_t)inbuf[0]; > + (*num) |= ((uint32_t)inbuf[1] << 8); > + (*num) |= ((uint32_t)inbuf[2] << 16); > + (*num) |= ((uint32_t)inbuf[3] << 24); > + > + return (sizeof(*num)); > +} > + > +static size_t _unmarshall64(uint8_t *inbuf, uint64_t *num) > +{ > + (*num) = (uint64_t)inbuf[0]; > + (*num) |= ((uint64_t)inbuf[1] << 8); > + (*num) |= ((uint64_t)inbuf[2] << 16); > + (*num) |= ((uint64_t)inbuf[3] << 24); > + (*num) |= ((uint64_t)inbuf[4] << 32); > + (*num) |= ((uint64_t)inbuf[5] << 40); > + (*num) |= ((uint64_t)inbuf[6] << 48); > + (*num) |= ((uint64_t)inbuf[7] << 56); > + > + return (sizeof(*num)); > +} > + > +static size_t _unmarshall_buf(const void *inbuf, void *outbuf, unsigned int len) > +{ > + memcpy(outbuf, inbuf, len); > + > + return len; > +} > + > +static int _load_header_info(int fd, > + ibnd_fabric_cache_t *fabric_cache, > + unsigned int *node_count, > + unsigned int *port_count) > +{ > + uint8_t buf[IBND_FABRIC_CACHE_BUFLEN]; > + uint32_t magic = 0; > + uint32_t version = 0; > + size_t offset = 0; > + uint32_t tmp32; > + > + if (_read(fd, buf, IBND_FABRIC_CACHE_HEADER_LEN) < 0) > + return -1; > + > + offset += _unmarshall32(buf + offset, &magic); > + > + if (magic != IBND_FABRIC_CACHE_MAGIC) { > + IBND_DEBUG("invalid fabric cache file\n"); > + return -1; > + } > + > + offset += _unmarshall32(buf + offset, &version); > + > + if (version != IBND_FABRIC_CACHE_VERSION) { > + IBND_DEBUG("invalid fabric cache version\n"); > + return -1; > + } > + > + offset += _unmarshall32(buf + offset, node_count); > + offset += _unmarshall32(buf + offset, port_count); > + > + offset += _unmarshall64(buf + offset, &fabric_cache->from_node_guid); > + offset += _unmarshall32(buf + offset, &tmp32); > + fabric_cache->fabric->maxhops_discovered = tmp32; > + > + return 0; > +} > + > +static void _destroy_ibnd_node_cache(ibnd_node_cache_t *node_cache) > +{ > + free(node_cache->port_cache_keys); > + free(node_cache); > +} > + > +static void _destroy_ibnd_fabric_cache(ibnd_fabric_cache_t *fabric_cache) > +{ > + ibnd_node_cache_t *node_cache; > + ibnd_node_cache_t *node_cache_next; > + ibnd_port_cache_t *port_cache; > + ibnd_port_cache_t *port_cache_next; > + > + if (!fabric_cache) > + return; > + > + node_cache = fabric_cache->nodes_cache; > + while (node_cache) { > + node_cache_next = node_cache->next; > + > + _destroy_ibnd_node_cache(node_cache); > + > + node_cache = node_cache_next; > + } > + > + port_cache = fabric_cache->ports_cache; > + while (port_cache) { > + port_cache_next = port_cache->next; > + > + free(port_cache); > + > + port_cache = port_cache_next; > + } > + > + free(fabric_cache); > +} > + > +static void store_node_cache(ibnd_node_cache_t *node_cache, > + ibnd_fabric_cache_t *fabric_cache) > +{ > + int hash_indx = HASHGUID(node_cache->node->guid) % HTSZ; > + > + node_cache->next = fabric_cache->nodes_cache; > + fabric_cache->nodes_cache = node_cache; > + > + node_cache->htnext = fabric_cache->nodescachetbl[hash_indx]; > + fabric_cache->nodescachetbl[hash_indx] = node_cache; > +} > + > +static int _load_node(int fd, ibnd_fabric_cache_t *fabric_cache) > +{ > + uint8_t buf[IBND_FABRIC_CACHE_BUFLEN]; > + ibnd_node_cache_t *node_cache = NULL; > + ibnd_node_t *node = NULL; > + size_t offset = 0; > + uint8_t tmp8; > + > + node_cache = (ibnd_node_cache_t *)malloc(sizeof(ibnd_node_cache_t)); > + if (!node_cache) { > + IBND_DEBUG("OOM: node_cache\n"); > + return -1; > + } > + memset(node_cache, '\0', sizeof(ibnd_node_cache_t)); > + > + node = (ibnd_node_t *)malloc(sizeof(ibnd_node_t)); > + if (!node) { > + IBND_DEBUG("OOM: node\n"); > + return -1; > + } > + memset(node, '\0', sizeof(ibnd_node_t)); > + > + node_cache->node = node; > + > + if (_read(fd, buf, IBND_NODE_CACHE_HEADER_LEN) < 0) > + goto cleanup; > + > + offset += _unmarshall16(buf + offset, &node->smalid); > + offset += _unmarshall8(buf + offset, &node->smalmc); > + offset += _unmarshall8(buf + offset, &tmp8); > + node->smaenhsp0 = tmp8; > + offset += _unmarshall_buf(buf + offset, node->switchinfo, IB_SMP_DATA_SIZE); > + offset += _unmarshall64(buf + offset, &node->guid); > + offset += _unmarshall8(buf + offset, &tmp8); > + node->type = tmp8; > + offset += _unmarshall8(buf + offset, &tmp8); > + node->numports = tmp8; > + offset += _unmarshall_buf(buf + offset, node->info, IB_SMP_DATA_SIZE); > + offset += _unmarshall_buf(buf + offset, node->nodedesc, IB_SMP_DATA_SIZE); > + > + offset += _unmarshall8(buf + offset, &node_cache->ports_stored_count); > + > + if (node_cache->ports_stored_count) { > + unsigned int tomalloc = 0; > + unsigned int toread = 0; > + unsigned int i; > + > + tomalloc = sizeof(ibnd_port_cache_key_t) * node_cache->ports_stored_count; > + > + toread = IBND_PORT_CACHE_KEY_LEN * node_cache->ports_stored_count; > + > + node_cache->port_cache_keys = (ibnd_port_cache_key_t *)malloc(tomalloc); > + if (!node_cache->port_cache_keys) { > + IBND_DEBUG("OOM: node_cache port_cache_keys\n"); > + goto cleanup; > + } > + > + if (_read(fd, buf, toread) < 0) > + goto cleanup; > + > + offset = 0; > + > + for (i = 0; i < node_cache->ports_stored_count; i++) { > + offset += _unmarshall64(buf + offset, > + &node_cache->port_cache_keys[i].guid); > + offset += _unmarshall8(buf + offset, > + &node_cache->port_cache_keys[i].portnum); > + } > + } > + > + store_node_cache(node_cache, fabric_cache); > + > + return 0; > + > +cleanup: > + /* note, no need to destroy node through destroy_node(), nothing else malloced */ > + free(node); > + _destroy_ibnd_node_cache(node_cache); > + return -1; > +} > + > +static void store_port_cache(ibnd_port_cache_t *port_cache, > + ibnd_fabric_cache_t *fabric_cache) > +{ > + int hash_indx = HASHGUID(port_cache->port->guid) % HTSZ; > + > + port_cache->next = fabric_cache->ports_cache; > + fabric_cache->ports_cache = port_cache; > + > + port_cache->htnext = fabric_cache->portscachetbl[hash_indx]; > + fabric_cache->portscachetbl[hash_indx] = port_cache; > +} > + > +static int _load_port(int fd, ibnd_fabric_cache_t *fabric_cache) > +{ > + uint8_t buf[IBND_FABRIC_CACHE_BUFLEN]; > + ibnd_port_cache_t *port_cache = NULL; > + ibnd_port_t *port = NULL; > + size_t offset = 0; > + uint8_t tmp8; > + > + port_cache = (ibnd_port_cache_t *)malloc(sizeof(ibnd_port_cache_t)); > + if (!port_cache) { > + IBND_DEBUG("OOM: port_cache\n"); > + return -1; > + } > + memset(port_cache, '\0', sizeof(ibnd_port_cache_t)); > + > + port = (ibnd_port_t *)malloc(sizeof(ibnd_port_t)); > + if (!port) { > + IBND_DEBUG("OOM: port\n"); > + return -1; > + } > + memset(port, '\0', sizeof(ibnd_port_t)); > + > + port_cache->port = port; > + > + if (_read(fd, buf, IBND_PORT_CACHE_LEN) < 0) > + goto cleanup; > + > + offset += _unmarshall64(buf + offset, &port->guid); > + offset += _unmarshall8(buf + offset, &tmp8); > + port->portnum = tmp8; > + offset += _unmarshall8(buf + offset, &tmp8); > + port->ext_portnum = tmp8; > + offset += _unmarshall16(buf + offset, &port->base_lid); > + offset += _unmarshall8(buf + offset, &port->lmc); > + offset += _unmarshall_buf(buf + offset, port->info, IB_SMP_DATA_SIZE); > + offset += _unmarshall64(buf + offset, &port_cache->node_guid); > + offset += _unmarshall8(buf + offset, &port_cache->remoteport_flag); > + offset += _unmarshall64(buf + offset, &port_cache->remoteport_cache_key.guid); > + offset += _unmarshall8(buf + offset, &port_cache->remoteport_cache_key.portnum); > + > + store_port_cache(port_cache, fabric_cache); > + > + return 0; > + > +cleanup: > + free(port); > + free(port_cache); > + return -1; > +} > + > +static ibnd_port_cache_t * _find_port(ibnd_fabric_cache_t *fabric_cache, > + ibnd_port_cache_key_t *port_cache_key) > +{ > + int hash_indx = HASHGUID(port_cache_key->guid) % HTSZ; > + ibnd_port_cache_t *port_cache; > + > + for (port_cache = fabric_cache->portscachetbl[hash_indx]; > + port_cache; > + port_cache = port_cache->htnext) { > + if (port_cache->port->guid == port_cache_key->guid > + && port_cache->port->portnum == port_cache_key->portnum) > + return port_cache; > + } > + > + return NULL; > +} > + > +static ibnd_node_cache_t * _find_node(ibnd_fabric_cache_t *fabric_cache, > + uint64_t guid) > +{ > + int hash_indx = HASHGUID(guid) % HTSZ; > + ibnd_node_cache_t *node_cache; > + > + for (node_cache = fabric_cache->nodescachetbl[hash_indx]; > + node_cache; > + node_cache = node_cache->htnext) { > + if (node_cache->node->guid == guid) > + return node_cache; > + } > + > + return NULL; > +} > + > +static int _fill_port(ibnd_fabric_cache_t *fabric_cache, > + ibnd_node_t *node, > + ibnd_port_cache_key_t *port_cache_key) > +{ > + ibnd_port_cache_t *port_cache; > + > + if (!(port_cache = _find_port(fabric_cache, port_cache_key))) { > + IBND_DEBUG("Cache invalid: cannot find port\n"); > + return -1; > + } > + > + node->ports[port_cache->port->portnum] = port_cache->port; > + > + return 0; > +} > + > +static int _rebuild_nodes(ibnd_fabric_cache_t *fabric_cache) > +{ > + ibnd_node_cache_t *node_cache; > + ibnd_node_cache_t *node_cache_next; > + > + node_cache = fabric_cache->nodes_cache; > + while (node_cache) { > + ibnd_node_t *node; > + int i; > + > + node_cache_next = node_cache->next; > + > + node = node_cache->node; > + > + /* Insert node into appropriate data structures */ > + > + node->next = fabric_cache->fabric->nodes; > + fabric_cache->fabric->nodes = node; > + > + add_to_nodeguid_hash(node_cache->node, fabric_cache->fabric->nodestbl); > + > + add_to_type_list(node_cache->node, fabric_cache->fabric); > + > + /* Rebuild node ports array */ > + > + if (!(node->ports = calloc(sizeof(*node->ports), node->numports + 1))) { > + IBND_DEBUG("OOM: node->ports\n"); > + return -1; > + } > + > + for (i = 0; i < node_cache->ports_stored_count; i++) { > + if (_fill_port(fabric_cache, node, &node_cache->port_cache_keys[i]) < 0) > + return -1; > + } > + > + node_cache = node_cache_next; > + } > + > + return 0; > +} > + > +static int _rebuild_ports(ibnd_fabric_cache_t *fabric_cache) > +{ > + ibnd_port_cache_t *port_cache; > + ibnd_port_cache_t *port_cache_next; > + > + port_cache = fabric_cache->ports_cache; > + while (port_cache) { > + ibnd_node_cache_t *node_cache; > + ibnd_port_cache_t *remoteport_cache; > + ibnd_port_t *port; > + > + port_cache_next = port_cache->next; > + > + port = port_cache->port; > + > + if (!(node_cache = _find_node(fabric_cache, port_cache->node_guid))) { > + IBND_DEBUG("Cache invalid: cannot find node\n"); > + return -1; > + } > + > + port->node = node_cache->node; > + > + if (port_cache->remoteport_flag) { > + if (!(remoteport_cache = _find_port(fabric_cache, > + &port_cache->remoteport_cache_key))) { > + IBND_DEBUG("Cache invalid: cannot find remote port\n"); > + return -1; > + } > + > + port->remoteport = remoteport_cache->port; > + } > + else > + port->remoteport = NULL; > + > + port_cache = port_cache_next; > + } > + > + return 0; > +} > + > +ibnd_fabric_t *ibnd_load_fabric(const char *file, unsigned int flags) > +{ > + unsigned int node_count = 0; > + unsigned int port_count = 0; > + ibnd_fabric_cache_t *fabric_cache = NULL; > + ibnd_fabric_t *fabric = NULL; > + ibnd_node_cache_t *node_cache = NULL; > + int fd = -1; > + unsigned int i; > + > + if (!file) { > + IBND_DEBUG("file parameter NULL\n"); > + return NULL; > + } > + > + if ((fd = open(file, O_RDONLY)) < 0) { > + IBND_DEBUG("open: %s\n", strerror(errno)); > + return NULL; > + } > + > + fabric_cache = (ibnd_fabric_cache_t *)malloc(sizeof(ibnd_fabric_cache_t)); > + if (!fabric_cache) { > + IBND_DEBUG("OOM: fabric_cache\n"); > + goto cleanup; > + } > + memset(fabric_cache, '\0', sizeof(ibnd_fabric_cache_t)); > + > + fabric = (ibnd_fabric_t *)malloc(sizeof(ibnd_fabric_t)); > + if (!fabric) { > + IBND_DEBUG("OOM: fabric\n"); > + goto cleanup; > + } > + memset(fabric, '\0', sizeof(ibnd_fabric_t)); > + > + fabric_cache->fabric = fabric; > + > + if (_load_header_info(fd, fabric_cache, &node_count, &port_count) < 0) > + goto cleanup; > + > + for (i = 0; i < node_count; i++) { > + if (_load_node(fd, fabric_cache) < 0) > + goto cleanup; > + } > + > + for (i = 0; i < port_count; i++) { > + if (_load_port(fd, fabric_cache) < 0) > + goto cleanup; > + } > + > + /* Special case - find from node */ > + if (!(node_cache = _find_node(fabric_cache, fabric_cache->from_node_guid))) { > + IBND_DEBUG("Cache invalid: cannot find from node\n"); > + goto cleanup; > + } > + fabric->from_node = node_cache->node; > + > + if (_rebuild_nodes(fabric_cache) < 0) > + goto cleanup; > + > + if (_rebuild_ports(fabric_cache) < 0) > + goto cleanup; > + > + if (group_nodes(fabric)) > + goto cleanup; > + > + _destroy_ibnd_fabric_cache(fabric_cache); > + close(fd); > + return fabric; > + > +cleanup: > + ibnd_destroy_fabric(fabric); > + _destroy_ibnd_fabric_cache(fabric_cache); > + close(fd); > + return NULL; > +} > + > +static ssize_t _write(int fd, const void *buf, size_t count) > +{ > + size_t count_done = 0; > + ssize_t ret; > + > + while ((count - count_done) > 0) { > + ret = write(fd, buf + count_done, count - count_done); > + if (ret < 0) { > + if (errno == EINTR) > + continue; > + else { > + IBND_DEBUG("write: %s\n", strerror(errno)); > + return -1; > + } > + } > + count_done += ret; > + } > + return count_done; > +} > + > + > +static size_t _marshall8(uint8_t *outbuf, uint8_t num) > +{ > + outbuf[0] = num; > + > + return (sizeof(num)); > +} > + > +static size_t _marshall16(uint8_t *outbuf, uint16_t num) > +{ > + outbuf[0] = num & 0x00FF; > + outbuf[1] = (num & 0xFF00) >> 8; > + > + return (sizeof(num)); > +} > + > +static size_t _marshall32(uint8_t *outbuf, uint32_t num) > +{ > + outbuf[0] = num & 0x000000FF; > + outbuf[1] = (num & 0x0000FF00) >> 8; > + outbuf[2] = (num & 0x00FF0000) >> 16; > + outbuf[3] = (num & 0xFF000000) >> 24; > + > + return (sizeof(num)); > +} > + > +static size_t _marshall64(uint8_t *outbuf, uint64_t num) > +{ > + outbuf[0] = num & 0x00000000000000FFULL; > + outbuf[1] = (num & 0x000000000000FF00ULL) >> 8; > + outbuf[2] = (num & 0x0000000000FF0000ULL) >> 16; > + outbuf[3] = (num & 0x00000000FF000000ULL) >> 24; > + outbuf[4] = (num & 0x000000FF00000000ULL) >> 32; > + outbuf[5] = (num & 0x0000FF0000000000ULL) >> 40; > + outbuf[6] = (num & 0x00FF000000000000ULL) >> 48; > + outbuf[7] = (num & 0xFF00000000000000ULL) >> 56; > + > + return (sizeof(num)); > +} > + > +static size_t _marshall_buf(void *outbuf, const void *inbuf, unsigned int len) > +{ > + memcpy(outbuf, inbuf, len); > + > + return len; > +} > + > +static int _cache_header_info(int fd, ibnd_fabric_t *fabric) > +{ > + uint8_t buf[IBND_FABRIC_CACHE_BUFLEN]; > + size_t offset = 0; > + > + /* Store magic number, version, and other important info */ > + /* For this caching lib, we always assume cached as little endian */ > + > + offset += _marshall32(buf + offset, IBND_FABRIC_CACHE_MAGIC); > + offset += _marshall32(buf + offset, IBND_FABRIC_CACHE_VERSION); > + /* save space for node count */ > + offset += _marshall32(buf + offset, 0); > + /* save space for port count */ > + offset += _marshall32(buf + offset, 0); > + offset += _marshall64(buf + offset, fabric->from_node->guid); > + offset += _marshall32(buf + offset, fabric->maxhops_discovered); > + > + if (_write(fd, buf, offset) < 0) > + return -1; > + > + return 0; > +} > + > +static int _cache_header_counts(int fd, unsigned int node_count, unsigned int port_count) > +{ > + uint8_t buf[IBND_FABRIC_CACHE_BUFLEN]; > + size_t offset = 0; > + > + offset += _marshall32(buf + offset, node_count); > + offset += _marshall32(buf + offset, port_count); > + > + if (lseek(fd, IBND_FABRIC_CACHE_COUNT_OFFSET, SEEK_SET) < 0) { > + IBND_DEBUG("lseek: %s\n", strerror(errno)); > + return -1; > + } > + > + if (_write(fd, buf, offset) < 0) > + return -1; > + > + return 0; > +} > + > +static int _cache_node(int fd, ibnd_node_t *node) > +{ > + uint8_t buf[IBND_FABRIC_CACHE_BUFLEN]; > + size_t offset = 0; > + size_t ports_stored_offset = 0; > + unsigned int ports_stored_count = 0; > + unsigned int i; > + > + offset += _marshall16(buf + offset, node->smalid); > + offset += _marshall8(buf + offset, node->smalmc); > + offset += _marshall8(buf + offset, node->smaenhsp0); > + offset += _marshall_buf(buf + offset, node->switchinfo, IB_SMP_DATA_SIZE); > + offset += _marshall64(buf + offset, node->guid); > + offset += _marshall8(buf + offset, node->type); > + offset += _marshall8(buf + offset, node->numports); > + offset += _marshall_buf(buf + offset, node->info, IB_SMP_DATA_SIZE); > + offset += _marshall_buf(buf + offset, node->nodedesc, IB_SMP_DATA_SIZE); > + /* need to come back later and store number of stored ports > + * because port entries can be NULL or (in the case of switches) > + * there is an additional port 0 not accounted for in numports. > + */ > + ports_stored_offset = offset; > + offset += sizeof(uint8_t); > + > + for (i = 0; i <= node->numports; i++) { > + if (node->ports[i]) { > + offset += _marshall64(buf + offset, node->ports[i]->guid); > + offset += _marshall8(buf + offset, node->ports[i]->portnum); > + ports_stored_count++; > + } > + } > + > + /* go back and store number of port keys stored */ > + _marshall8(buf + ports_stored_offset, ports_stored_count); > + > + if (_write(fd, buf, offset) < 0) > + return -1; > + > + return 0; > +} > + > +static int _cache_port(int fd, ibnd_port_t *port) > +{ > + uint8_t buf[IBND_FABRIC_CACHE_BUFLEN]; > + size_t offset = 0; > + > + offset += _marshall64(buf + offset, port->guid); > + offset += _marshall8(buf + offset, port->portnum); > + offset += _marshall8(buf + offset, port->ext_portnum); > + offset += _marshall16(buf + offset, port->base_lid); > + offset += _marshall8(buf + offset, port->lmc); > + offset += _marshall_buf(buf + offset, port->info, IB_SMP_DATA_SIZE); > + offset += _marshall64(buf + offset, port->node->guid); > + if (port->remoteport) { > + offset += _marshall8(buf + offset, 1); > + offset += _marshall64(buf + offset, port->remoteport->guid); > + offset += _marshall8(buf + offset, port->remoteport->portnum); > + } > + else { > + offset += _marshall8(buf + offset, 0); > + offset += _marshall64(buf + offset, 0); > + offset += _marshall8(buf + offset, 0); > + } > + > + if (_write(fd, buf, offset) < 0) > + return -1; > + > + return 0; > +} > + > +int ibnd_cache_fabric(ibnd_fabric_t *fabric, const char *file, unsigned int flags) > +{ > + struct stat statbuf; > + ibnd_node_t *node = NULL; > + ibnd_node_t *node_next = NULL; > + unsigned int node_count = 0; > + ibnd_port_t *port = NULL; > + ibnd_port_t *port_next = NULL; > + unsigned int port_count = 0; > + int fd; > + int i; > + > + if (!fabric) { > + IBND_DEBUG("fabric parameter NULL\n"); > + return -1; > + } > + > + if (!file) { > + IBND_DEBUG("file parameter NULL\n"); > + return -1; > + } > + > + if (!stat(file, &statbuf)) { > + IBND_DEBUG("file '%s' already exists\n", file); > + return -1; > + } > + > + if ((fd = open(file, O_CREAT | O_EXCL | O_WRONLY, 0644)) < 0) { > + IBND_DEBUG("open: %s\n", strerror(errno)); > + return -1; > + } > + > + if (_cache_header_info(fd, fabric) < 0) > + goto cleanup; > + > + node = fabric->nodes; > + while (node) { > + node_next = node->next; > + > + if (_cache_node(fd, node) < 0) > + goto cleanup; > + > + node_count++; > + node = node_next; > + } > + > + for (i = 0; i < HTSZ; i++) { > + port = fabric->portstbl[i]; > + while (port) { > + port_next = port->htnext; > + > + if (_cache_port(fd, port) < 0) > + goto cleanup; > + > + port_count++; > + port = port_next; > + } > + } > + > + if (_cache_header_counts(fd, node_count, port_count) < 0) > + goto cleanup; > + > + if (close(fd) < 0) { > + IBND_DEBUG("close: %s\n", strerror(errno)); > + goto cleanup; > + } > + > + return 0; > + > +cleanup: > + unlink(file); > + close(fd); > + return -1; > +} > diff --git a/infiniband-diags/libibnetdisc/src/internal.h b/infiniband-diags/libibnetdisc/src/internal.h > index 5af5f10..348bd0f 100644 > --- a/infiniband-diags/libibnetdisc/src/internal.h > +++ b/infiniband-diags/libibnetdisc/src/internal.h > @@ -62,4 +62,10 @@ typedef struct ibnd_scan { > ib_portid_t selfportid; > } ibnd_scan_t; > > +void add_to_nodeguid_hash(ibnd_node_t * node, ibnd_node_t * hash[]); > + > +void add_to_portguid_hash(ibnd_port_t * port, ibnd_port_t * hash[]); > + > +void add_to_type_list(ibnd_node_t * node, ibnd_fabric_t * fabric); > + > #endif /* _INTERNAL_H_ */ > diff --git a/infiniband-diags/libibnetdisc/src/libibnetdisc.map b/infiniband-diags/libibnetdisc/src/libibnetdisc.map > index 13bb65a..888bdd8 100644 > --- a/infiniband-diags/libibnetdisc/src/libibnetdisc.map > +++ b/infiniband-diags/libibnetdisc/src/libibnetdisc.map > @@ -4,6 +4,8 @@ IBNETDISC_1.0 { > ibnd_show_progress; > ibnd_discover_fabric; > ibnd_destroy_fabric; > + ibnd_load_fabric; > + ibnd_cache_fabric; > ibnd_find_node_guid; > ibnd_find_node_dr; > ibnd_is_xsigo_guid; > -- > 1.5.4.5 > -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [infiniband-diags] [UPDATED PATCH] [1/3] add libibnetdisc caching to libibnetdiscover 2010-01-16 14:12 ` Sasha Khapyorsky @ 2010-01-16 16:11 ` Al Chu [not found] ` <1263658295.14626.3.camel-RLKWKRZIcZkVVsCFsIUZTRy+HRzXvqW9@public.gmane.org> 0 siblings, 1 reply; 5+ messages in thread From: Al Chu @ 2010-01-16 16:11 UTC (permalink / raw) To: Sasha Khapyorsky; +Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA Hey Sasha, > What is the purpose of 'flags' parameter (I see that this is not used > in any place)? I just added it for potential future extensions, and thus we won't need to change the API in the future. One simple idea might be a flag for overwriting a previous cache if it exists (instead of returning an error). If you prefer we remove it, I can do that too. Al On Sat, 2010-01-16 at 16:12 +0200, Sasha Khapyorsky wrote: > Hi Al, > > On 10:23 Fri 15 Jan , Al Chu wrote: > > Hi Sahsa, > > > > This patch adds caching functionality to libibnetdisc through the new > > functions ibnd_cache_fabric() and ibnd_load_fabric(). > > > > Al > > > > -- > > Albert Chu > > chu11-i2BcT+NCU+M@public.gmane.org > > Computer Scientist > > High Performance Systems Division > > Lawrence Livermore National Laboratory > > > From: Albert Chu <chu11-i2BcT+NCU+M@public.gmane.org> > > Date: Wed, 9 Dec 2009 15:19:24 -0800 > > Subject: [PATCH] add libibnetdisc caching to libibnetdiscover > > > > > > Signed-off-by: Albert Chu <chu11-i2BcT+NCU+M@public.gmane.org> > > --- > > infiniband-diags/libibnetdisc/Makefile.am | 3 +- > > .../libibnetdisc/include/infiniband/ibnetdisc.h | 6 + > > infiniband-diags/libibnetdisc/src/ibnetdisc.c | 6 +- > > .../libibnetdisc/src/ibnetdisc_cache.c | 909 ++++++++++++++++++++ > > infiniband-diags/libibnetdisc/src/internal.h | 6 + > > infiniband-diags/libibnetdisc/src/libibnetdisc.map | 2 + > > 6 files changed, 928 insertions(+), 4 deletions(-) > > create mode 100644 infiniband-diags/libibnetdisc/src/ibnetdisc_cache.c > > > > diff --git a/infiniband-diags/libibnetdisc/Makefile.am b/infiniband-diags/libibnetdisc/Makefile.am > > index 636d142..a46dbc8 100644 > > --- a/infiniband-diags/libibnetdisc/Makefile.am > > +++ b/infiniband-diags/libibnetdisc/Makefile.am > > @@ -22,7 +22,8 @@ else > > libibnetdisc_version_script = > > endif > > > > -libibnetdisc_la_SOURCES = src/ibnetdisc.c src/chassis.c src/chassis.h src/internal.h > > +libibnetdisc_la_SOURCES = src/ibnetdisc.c src/ibnetdisc_cache.c src/chassis.c \ > > + src/chassis.h src/internal.h > > libibnetdisc_la_CFLAGS = -Wall $(DBGFLAGS) > > libibnetdisc_la_LDFLAGS = -version-info $(ibnetdisc_api_version) \ > > -export-dynamic $(libibnetdisc_version_script) \ > > diff --git a/infiniband-diags/libibnetdisc/include/infiniband/ibnetdisc.h b/infiniband-diags/libibnetdisc/include/infiniband/ibnetdisc.h > > index 8d5ac39..38ca2fb 100644 > > --- a/infiniband-diags/libibnetdisc/include/infiniband/ibnetdisc.h > > +++ b/infiniband-diags/libibnetdisc/include/infiniband/ibnetdisc.h > > @@ -170,6 +170,12 @@ MAD_EXPORT ibnd_fabric_t *ibnd_discover_fabric(struct ibmad_port *ibmad_port, > > */ > > MAD_EXPORT void ibnd_destroy_fabric(ibnd_fabric_t * fabric); > > > > +MAD_EXPORT ibnd_fabric_t *ibnd_load_fabric(const char *file, > > + unsigned int flags); > > + > > +MAD_EXPORT int ibnd_cache_fabric(ibnd_fabric_t *fabric, const char *file, > > + unsigned int flags); > > + > > What is the purpose of 'flags' parameter (I see that this is not used in > any place)? > > Sasha > > > /** ========================================================================= > > * Node operations > > */ > > diff --git a/infiniband-diags/libibnetdisc/src/ibnetdisc.c b/infiniband-diags/libibnetdisc/src/ibnetdisc.c > > index 9367337..9b24931 100644 > > --- a/infiniband-diags/libibnetdisc/src/ibnetdisc.c > > +++ b/infiniband-diags/libibnetdisc/src/ibnetdisc.c > > @@ -286,7 +286,7 @@ ibnd_node_t *ibnd_find_node_dr(ibnd_fabric_t * fabric, char *dr_str) > > return rc; > > } > > > > -static void add_to_nodeguid_hash(ibnd_node_t * node, ibnd_node_t * hash[]) > > +void add_to_nodeguid_hash(ibnd_node_t * node, ibnd_node_t * hash[]) > > { > > int hash_idx = HASHGUID(node->guid) % HTSZ; > > > > @@ -294,7 +294,7 @@ static void add_to_nodeguid_hash(ibnd_node_t * node, ibnd_node_t * hash[]) > > hash[hash_idx] = node; > > } > > > > -static void add_to_portguid_hash(ibnd_port_t * port, ibnd_port_t * hash[]) > > +void add_to_portguid_hash(ibnd_port_t * port, ibnd_port_t * hash[]) > > { > > int hash_idx = HASHGUID(port->guid) % HTSZ; > > > > @@ -302,7 +302,7 @@ static void add_to_portguid_hash(ibnd_port_t * port, ibnd_port_t * hash[]) > > hash[hash_idx] = port; > > } > > > > -static void add_to_type_list(ibnd_node_t * node, ibnd_fabric_t * fabric) > > +void add_to_type_list(ibnd_node_t * node, ibnd_fabric_t * fabric) > > { > > switch (node->type) { > > case IB_NODE_CA: > > diff --git a/infiniband-diags/libibnetdisc/src/ibnetdisc_cache.c b/infiniband-diags/libibnetdisc/src/ibnetdisc_cache.c > > new file mode 100644 > > index 0000000..403c053 > > --- /dev/null > > +++ b/infiniband-diags/libibnetdisc/src/ibnetdisc_cache.c > > @@ -0,0 +1,909 @@ > > +/* > > + * Copyright (c) 2004-2007 Voltaire Inc. All rights reserved. > > + * Copyright (c) 2007 Xsigo Systems Inc. All rights reserved. > > + * Copyright (c) 2008 Lawrence Livermore National Laboratory > > + * > > + * This software is available to you under a choice of one of two > > + * licenses. You may choose to be licensed under the terms of the GNU > > + * General Public License (GPL) Version 2, available from the file > > + * COPYING in the main directory of this source tree, or the > > + * OpenIB.org BSD license below: > > + * > > + * Redistribution and use in source and binary forms, with or > > + * without modification, are permitted provided that the following > > + * conditions are met: > > + * > > + * - Redistributions of source code must retain the above > > + * copyright notice, this list of conditions and the following > > + * disclaimer. > > + * > > + * - Redistributions in binary form must reproduce the above > > + * copyright notice, this list of conditions and the following > > + * disclaimer in the documentation and/or other materials > > + * provided with the distribution. > > + * > > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, > > + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF > > + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND > > + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS > > + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN > > + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN > > + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE > > + * SOFTWARE. > > + * > > + */ > > + > > +#if HAVE_CONFIG_H > > +# include <config.h> > > +#endif /* HAVE_CONFIG_H */ > > + > > +#define _GNU_SOURCE > > +#include <stdio.h> > > +#include <stdlib.h> > > +#include <sys/types.h> > > +#include <sys/stat.h> > > +#include <unistd.h> > > +#include <fcntl.h> > > +#include <string.h> > > +#include <errno.h> > > +#include <inttypes.h> > > + > > +#include <infiniband/ibnetdisc.h> > > + > > +#include "internal.h" > > +#include "chassis.h" > > + > > +/* For this caching lib, we always cache little endian */ > > + > > +/* Cache format > > + * > > + * Bytes 1-4 - magic number > > + * Bytes 5-8 - version number > > + * Bytes 9-12 - node count > > + * Bytes 13-16 - port count > > + * Bytes 17-24 - "from node" guid > > + * Bytes 25-28 - maxhops discovered > > + * Bytes X-Y - nodes (variable length) > > + * Bytes X-Y - ports (variable length) > > + * > > + * Nodes are cached as > > + * > > + * 2 bytes - smalid > > + * 1 byte - smalmc > > + * 1 byte - smaenhsp0 flag > > + * IB_SMP_DATA_SIZE bytes - switchinfo > > + * 8 bytes - guid > > + * 1 byte - type > > + * 1 byte - numports > > + * IB_SMP_DATA_SIZE bytes - info > > + * IB_SMP_DATA_SIZE bytes - nodedesc > > + * 1 byte - number of ports stored > > + * 8 bytes - portguid A > > + * 1 byte - port num A > > + * 8 bytes - portguid B > > + * 1 byte - port num B > > + * ... etc., depending on number of ports stored > > + * > > + * Ports are cached as > > + * > > + * 8 bytes - guid > > + * 1 byte - portnum > > + * 1 byte - external portnum > > + * 2 bytes - base lid > > + * 1 byte - lmc > > + * IB_SMP_DATA_SIZE bytes - info > > + * 8 bytes - node guid port "owned" by > > + * 1 byte - flag indicating if remote port exists > > + * 8 bytes - port guid remotely connected to > > + * 1 byte - port num remotely connected to > > + */ > > + > > +/* Structs that hold cache info temporarily before > > + * the real structs can be reconstructed. > > + */ > > + > > +typedef struct ibnd_port_cache_key { > > + uint64_t guid; > > + uint8_t portnum; > > +} ibnd_port_cache_key_t; > > + > > +typedef struct ibnd_node_cache { > > + ibnd_node_t *node; > > + uint8_t ports_stored_count; > > + ibnd_port_cache_key_t *port_cache_keys; > > + struct ibnd_node_cache *next; > > + struct ibnd_node_cache *htnext; > > +} ibnd_node_cache_t; > > + > > +typedef struct ibnd_port_cache { > > + ibnd_port_t *port; > > + uint64_t node_guid; > > + uint8_t remoteport_flag; > > + ibnd_port_cache_key_t remoteport_cache_key; > > + struct ibnd_port_cache *next; > > + struct ibnd_port_cache *htnext; > > +} ibnd_port_cache_t; > > + > > +typedef struct ibnd_fabric_cache { > > + ibnd_fabric_t *fabric; > > + uint64_t from_node_guid; > > + ibnd_node_cache_t *nodes_cache; > > + ibnd_port_cache_t *ports_cache; > > + ibnd_node_cache_t *nodescachetbl[HTSZ]; > > + ibnd_port_cache_t *portscachetbl[HTSZ]; > > +} ibnd_fabric_cache_t; > > + > > +#define IBND_FABRIC_CACHE_BUFLEN 4096 > > +#define IBND_FABRIC_CACHE_MAGIC 0x8FE7832B > > +#define IBND_FABRIC_CACHE_VERSION 0x00000001 > > + > > +#define IBND_FABRIC_CACHE_COUNT_OFFSET 8 > > + > > +#define IBND_FABRIC_CACHE_HEADER_LEN (28) > > +#define IBND_NODE_CACHE_HEADER_LEN (15 + IB_SMP_DATA_SIZE*3) > > +#define IBND_PORT_CACHE_KEY_LEN (8 + 1) > > +#define IBND_PORT_CACHE_LEN (31 + IB_SMP_DATA_SIZE) > > + > > +static ssize_t _read(int fd, void *buf, size_t count) > > +{ > > + size_t count_done = 0; > > + ssize_t ret; > > + > > + while ((count - count_done) > 0) { > > + ret = read(fd, buf + count_done, count - count_done); > > + if (ret < 0) { > > + if (errno == EINTR) > > + continue; > > + else { > > + IBND_DEBUG("read: %s\n", strerror(errno)); > > + return -1; > > + } > > + } > > + if (!ret) > > + break; > > + count_done += ret; > > + } > > + > > + if (count_done != count) { > > + IBND_DEBUG("read: read short\n"); > > + return -1; > > + } > > + > > + return count_done; > > +} > > + > > +static size_t _unmarshall8(uint8_t *inbuf, uint8_t *num) > > +{ > > + (*num) = inbuf[0]; > > + > > + return (sizeof(*num)); > > +} > > + > > +static size_t _unmarshall16(uint8_t *inbuf, uint16_t *num) > > +{ > > + (*num) = (uint64_t)inbuf[0]; > > + (*num) |= ((uint16_t)inbuf[1] << 8); > > + > > + return (sizeof(*num)); > > +} > > + > > +static size_t _unmarshall32(uint8_t *inbuf, uint32_t *num) > > +{ > > + (*num) = (uint32_t)inbuf[0]; > > + (*num) |= ((uint32_t)inbuf[1] << 8); > > + (*num) |= ((uint32_t)inbuf[2] << 16); > > + (*num) |= ((uint32_t)inbuf[3] << 24); > > + > > + return (sizeof(*num)); > > +} > > + > > +static size_t _unmarshall64(uint8_t *inbuf, uint64_t *num) > > +{ > > + (*num) = (uint64_t)inbuf[0]; > > + (*num) |= ((uint64_t)inbuf[1] << 8); > > + (*num) |= ((uint64_t)inbuf[2] << 16); > > + (*num) |= ((uint64_t)inbuf[3] << 24); > > + (*num) |= ((uint64_t)inbuf[4] << 32); > > + (*num) |= ((uint64_t)inbuf[5] << 40); > > + (*num) |= ((uint64_t)inbuf[6] << 48); > > + (*num) |= ((uint64_t)inbuf[7] << 56); > > + > > + return (sizeof(*num)); > > +} > > + > > +static size_t _unmarshall_buf(const void *inbuf, void *outbuf, unsigned int len) > > +{ > > + memcpy(outbuf, inbuf, len); > > + > > + return len; > > +} > > + > > +static int _load_header_info(int fd, > > + ibnd_fabric_cache_t *fabric_cache, > > + unsigned int *node_count, > > + unsigned int *port_count) > > +{ > > + uint8_t buf[IBND_FABRIC_CACHE_BUFLEN]; > > + uint32_t magic = 0; > > + uint32_t version = 0; > > + size_t offset = 0; > > + uint32_t tmp32; > > + > > + if (_read(fd, buf, IBND_FABRIC_CACHE_HEADER_LEN) < 0) > > + return -1; > > + > > + offset += _unmarshall32(buf + offset, &magic); > > + > > + if (magic != IBND_FABRIC_CACHE_MAGIC) { > > + IBND_DEBUG("invalid fabric cache file\n"); > > + return -1; > > + } > > + > > + offset += _unmarshall32(buf + offset, &version); > > + > > + if (version != IBND_FABRIC_CACHE_VERSION) { > > + IBND_DEBUG("invalid fabric cache version\n"); > > + return -1; > > + } > > + > > + offset += _unmarshall32(buf + offset, node_count); > > + offset += _unmarshall32(buf + offset, port_count); > > + > > + offset += _unmarshall64(buf + offset, &fabric_cache->from_node_guid); > > + offset += _unmarshall32(buf + offset, &tmp32); > > + fabric_cache->fabric->maxhops_discovered = tmp32; > > + > > + return 0; > > +} > > + > > +static void _destroy_ibnd_node_cache(ibnd_node_cache_t *node_cache) > > +{ > > + free(node_cache->port_cache_keys); > > + free(node_cache); > > +} > > + > > +static void _destroy_ibnd_fabric_cache(ibnd_fabric_cache_t *fabric_cache) > > +{ > > + ibnd_node_cache_t *node_cache; > > + ibnd_node_cache_t *node_cache_next; > > + ibnd_port_cache_t *port_cache; > > + ibnd_port_cache_t *port_cache_next; > > + > > + if (!fabric_cache) > > + return; > > + > > + node_cache = fabric_cache->nodes_cache; > > + while (node_cache) { > > + node_cache_next = node_cache->next; > > + > > + _destroy_ibnd_node_cache(node_cache); > > + > > + node_cache = node_cache_next; > > + } > > + > > + port_cache = fabric_cache->ports_cache; > > + while (port_cache) { > > + port_cache_next = port_cache->next; > > + > > + free(port_cache); > > + > > + port_cache = port_cache_next; > > + } > > + > > + free(fabric_cache); > > +} > > + > > +static void store_node_cache(ibnd_node_cache_t *node_cache, > > + ibnd_fabric_cache_t *fabric_cache) > > +{ > > + int hash_indx = HASHGUID(node_cache->node->guid) % HTSZ; > > + > > + node_cache->next = fabric_cache->nodes_cache; > > + fabric_cache->nodes_cache = node_cache; > > + > > + node_cache->htnext = fabric_cache->nodescachetbl[hash_indx]; > > + fabric_cache->nodescachetbl[hash_indx] = node_cache; > > +} > > + > > +static int _load_node(int fd, ibnd_fabric_cache_t *fabric_cache) > > +{ > > + uint8_t buf[IBND_FABRIC_CACHE_BUFLEN]; > > + ibnd_node_cache_t *node_cache = NULL; > > + ibnd_node_t *node = NULL; > > + size_t offset = 0; > > + uint8_t tmp8; > > + > > + node_cache = (ibnd_node_cache_t *)malloc(sizeof(ibnd_node_cache_t)); > > + if (!node_cache) { > > + IBND_DEBUG("OOM: node_cache\n"); > > + return -1; > > + } > > + memset(node_cache, '\0', sizeof(ibnd_node_cache_t)); > > + > > + node = (ibnd_node_t *)malloc(sizeof(ibnd_node_t)); > > + if (!node) { > > + IBND_DEBUG("OOM: node\n"); > > + return -1; > > + } > > + memset(node, '\0', sizeof(ibnd_node_t)); > > + > > + node_cache->node = node; > > + > > + if (_read(fd, buf, IBND_NODE_CACHE_HEADER_LEN) < 0) > > + goto cleanup; > > + > > + offset += _unmarshall16(buf + offset, &node->smalid); > > + offset += _unmarshall8(buf + offset, &node->smalmc); > > + offset += _unmarshall8(buf + offset, &tmp8); > > + node->smaenhsp0 = tmp8; > > + offset += _unmarshall_buf(buf + offset, node->switchinfo, IB_SMP_DATA_SIZE); > > + offset += _unmarshall64(buf + offset, &node->guid); > > + offset += _unmarshall8(buf + offset, &tmp8); > > + node->type = tmp8; > > + offset += _unmarshall8(buf + offset, &tmp8); > > + node->numports = tmp8; > > + offset += _unmarshall_buf(buf + offset, node->info, IB_SMP_DATA_SIZE); > > + offset += _unmarshall_buf(buf + offset, node->nodedesc, IB_SMP_DATA_SIZE); > > + > > + offset += _unmarshall8(buf + offset, &node_cache->ports_stored_count); > > + > > + if (node_cache->ports_stored_count) { > > + unsigned int tomalloc = 0; > > + unsigned int toread = 0; > > + unsigned int i; > > + > > + tomalloc = sizeof(ibnd_port_cache_key_t) * node_cache->ports_stored_count; > > + > > + toread = IBND_PORT_CACHE_KEY_LEN * node_cache->ports_stored_count; > > + > > + node_cache->port_cache_keys = (ibnd_port_cache_key_t *)malloc(tomalloc); > > + if (!node_cache->port_cache_keys) { > > + IBND_DEBUG("OOM: node_cache port_cache_keys\n"); > > + goto cleanup; > > + } > > + > > + if (_read(fd, buf, toread) < 0) > > + goto cleanup; > > + > > + offset = 0; > > + > > + for (i = 0; i < node_cache->ports_stored_count; i++) { > > + offset += _unmarshall64(buf + offset, > > + &node_cache->port_cache_keys[i].guid); > > + offset += _unmarshall8(buf + offset, > > + &node_cache->port_cache_keys[i].portnum); > > + } > > + } > > + > > + store_node_cache(node_cache, fabric_cache); > > + > > + return 0; > > + > > +cleanup: > > + /* note, no need to destroy node through destroy_node(), nothing else malloced */ > > + free(node); > > + _destroy_ibnd_node_cache(node_cache); > > + return -1; > > +} > > + > > +static void store_port_cache(ibnd_port_cache_t *port_cache, > > + ibnd_fabric_cache_t *fabric_cache) > > +{ > > + int hash_indx = HASHGUID(port_cache->port->guid) % HTSZ; > > + > > + port_cache->next = fabric_cache->ports_cache; > > + fabric_cache->ports_cache = port_cache; > > + > > + port_cache->htnext = fabric_cache->portscachetbl[hash_indx]; > > + fabric_cache->portscachetbl[hash_indx] = port_cache; > > +} > > + > > +static int _load_port(int fd, ibnd_fabric_cache_t *fabric_cache) > > +{ > > + uint8_t buf[IBND_FABRIC_CACHE_BUFLEN]; > > + ibnd_port_cache_t *port_cache = NULL; > > + ibnd_port_t *port = NULL; > > + size_t offset = 0; > > + uint8_t tmp8; > > + > > + port_cache = (ibnd_port_cache_t *)malloc(sizeof(ibnd_port_cache_t)); > > + if (!port_cache) { > > + IBND_DEBUG("OOM: port_cache\n"); > > + return -1; > > + } > > + memset(port_cache, '\0', sizeof(ibnd_port_cache_t)); > > + > > + port = (ibnd_port_t *)malloc(sizeof(ibnd_port_t)); > > + if (!port) { > > + IBND_DEBUG("OOM: port\n"); > > + return -1; > > + } > > + memset(port, '\0', sizeof(ibnd_port_t)); > > + > > + port_cache->port = port; > > + > > + if (_read(fd, buf, IBND_PORT_CACHE_LEN) < 0) > > + goto cleanup; > > + > > + offset += _unmarshall64(buf + offset, &port->guid); > > + offset += _unmarshall8(buf + offset, &tmp8); > > + port->portnum = tmp8; > > + offset += _unmarshall8(buf + offset, &tmp8); > > + port->ext_portnum = tmp8; > > + offset += _unmarshall16(buf + offset, &port->base_lid); > > + offset += _unmarshall8(buf + offset, &port->lmc); > > + offset += _unmarshall_buf(buf + offset, port->info, IB_SMP_DATA_SIZE); > > + offset += _unmarshall64(buf + offset, &port_cache->node_guid); > > + offset += _unmarshall8(buf + offset, &port_cache->remoteport_flag); > > + offset += _unmarshall64(buf + offset, &port_cache->remoteport_cache_key.guid); > > + offset += _unmarshall8(buf + offset, &port_cache->remoteport_cache_key.portnum); > > + > > + store_port_cache(port_cache, fabric_cache); > > + > > + return 0; > > + > > +cleanup: > > + free(port); > > + free(port_cache); > > + return -1; > > +} > > + > > +static ibnd_port_cache_t * _find_port(ibnd_fabric_cache_t *fabric_cache, > > + ibnd_port_cache_key_t *port_cache_key) > > +{ > > + int hash_indx = HASHGUID(port_cache_key->guid) % HTSZ; > > + ibnd_port_cache_t *port_cache; > > + > > + for (port_cache = fabric_cache->portscachetbl[hash_indx]; > > + port_cache; > > + port_cache = port_cache->htnext) { > > + if (port_cache->port->guid == port_cache_key->guid > > + && port_cache->port->portnum == port_cache_key->portnum) > > + return port_cache; > > + } > > + > > + return NULL; > > +} > > + > > +static ibnd_node_cache_t * _find_node(ibnd_fabric_cache_t *fabric_cache, > > + uint64_t guid) > > +{ > > + int hash_indx = HASHGUID(guid) % HTSZ; > > + ibnd_node_cache_t *node_cache; > > + > > + for (node_cache = fabric_cache->nodescachetbl[hash_indx]; > > + node_cache; > > + node_cache = node_cache->htnext) { > > + if (node_cache->node->guid == guid) > > + return node_cache; > > + } > > + > > + return NULL; > > +} > > + > > +static int _fill_port(ibnd_fabric_cache_t *fabric_cache, > > + ibnd_node_t *node, > > + ibnd_port_cache_key_t *port_cache_key) > > +{ > > + ibnd_port_cache_t *port_cache; > > + > > + if (!(port_cache = _find_port(fabric_cache, port_cache_key))) { > > + IBND_DEBUG("Cache invalid: cannot find port\n"); > > + return -1; > > + } > > + > > + node->ports[port_cache->port->portnum] = port_cache->port; > > + > > + return 0; > > +} > > + > > +static int _rebuild_nodes(ibnd_fabric_cache_t *fabric_cache) > > +{ > > + ibnd_node_cache_t *node_cache; > > + ibnd_node_cache_t *node_cache_next; > > + > > + node_cache = fabric_cache->nodes_cache; > > + while (node_cache) { > > + ibnd_node_t *node; > > + int i; > > + > > + node_cache_next = node_cache->next; > > + > > + node = node_cache->node; > > + > > + /* Insert node into appropriate data structures */ > > + > > + node->next = fabric_cache->fabric->nodes; > > + fabric_cache->fabric->nodes = node; > > + > > + add_to_nodeguid_hash(node_cache->node, fabric_cache->fabric->nodestbl); > > + > > + add_to_type_list(node_cache->node, fabric_cache->fabric); > > + > > + /* Rebuild node ports array */ > > + > > + if (!(node->ports = calloc(sizeof(*node->ports), node->numports + 1))) { > > + IBND_DEBUG("OOM: node->ports\n"); > > + return -1; > > + } > > + > > + for (i = 0; i < node_cache->ports_stored_count; i++) { > > + if (_fill_port(fabric_cache, node, &node_cache->port_cache_keys[i]) < 0) > > + return -1; > > + } > > + > > + node_cache = node_cache_next; > > + } > > + > > + return 0; > > +} > > + > > +static int _rebuild_ports(ibnd_fabric_cache_t *fabric_cache) > > +{ > > + ibnd_port_cache_t *port_cache; > > + ibnd_port_cache_t *port_cache_next; > > + > > + port_cache = fabric_cache->ports_cache; > > + while (port_cache) { > > + ibnd_node_cache_t *node_cache; > > + ibnd_port_cache_t *remoteport_cache; > > + ibnd_port_t *port; > > + > > + port_cache_next = port_cache->next; > > + > > + port = port_cache->port; > > + > > + if (!(node_cache = _find_node(fabric_cache, port_cache->node_guid))) { > > + IBND_DEBUG("Cache invalid: cannot find node\n"); > > + return -1; > > + } > > + > > + port->node = node_cache->node; > > + > > + if (port_cache->remoteport_flag) { > > + if (!(remoteport_cache = _find_port(fabric_cache, > > + &port_cache->remoteport_cache_key))) { > > + IBND_DEBUG("Cache invalid: cannot find remote port\n"); > > + return -1; > > + } > > + > > + port->remoteport = remoteport_cache->port; > > + } > > + else > > + port->remoteport = NULL; > > + > > + port_cache = port_cache_next; > > + } > > + > > + return 0; > > +} > > + > > +ibnd_fabric_t *ibnd_load_fabric(const char *file, unsigned int flags) > > +{ > > + unsigned int node_count = 0; > > + unsigned int port_count = 0; > > + ibnd_fabric_cache_t *fabric_cache = NULL; > > + ibnd_fabric_t *fabric = NULL; > > + ibnd_node_cache_t *node_cache = NULL; > > + int fd = -1; > > + unsigned int i; > > + > > + if (!file) { > > + IBND_DEBUG("file parameter NULL\n"); > > + return NULL; > > + } > > + > > + if ((fd = open(file, O_RDONLY)) < 0) { > > + IBND_DEBUG("open: %s\n", strerror(errno)); > > + return NULL; > > + } > > + > > + fabric_cache = (ibnd_fabric_cache_t *)malloc(sizeof(ibnd_fabric_cache_t)); > > + if (!fabric_cache) { > > + IBND_DEBUG("OOM: fabric_cache\n"); > > + goto cleanup; > > + } > > + memset(fabric_cache, '\0', sizeof(ibnd_fabric_cache_t)); > > + > > + fabric = (ibnd_fabric_t *)malloc(sizeof(ibnd_fabric_t)); > > + if (!fabric) { > > + IBND_DEBUG("OOM: fabric\n"); > > + goto cleanup; > > + } > > + memset(fabric, '\0', sizeof(ibnd_fabric_t)); > > + > > + fabric_cache->fabric = fabric; > > + > > + if (_load_header_info(fd, fabric_cache, &node_count, &port_count) < 0) > > + goto cleanup; > > + > > + for (i = 0; i < node_count; i++) { > > + if (_load_node(fd, fabric_cache) < 0) > > + goto cleanup; > > + } > > + > > + for (i = 0; i < port_count; i++) { > > + if (_load_port(fd, fabric_cache) < 0) > > + goto cleanup; > > + } > > + > > + /* Special case - find from node */ > > + if (!(node_cache = _find_node(fabric_cache, fabric_cache->from_node_guid))) { > > + IBND_DEBUG("Cache invalid: cannot find from node\n"); > > + goto cleanup; > > + } > > + fabric->from_node = node_cache->node; > > + > > + if (_rebuild_nodes(fabric_cache) < 0) > > + goto cleanup; > > + > > + if (_rebuild_ports(fabric_cache) < 0) > > + goto cleanup; > > + > > + if (group_nodes(fabric)) > > + goto cleanup; > > + > > + _destroy_ibnd_fabric_cache(fabric_cache); > > + close(fd); > > + return fabric; > > + > > +cleanup: > > + ibnd_destroy_fabric(fabric); > > + _destroy_ibnd_fabric_cache(fabric_cache); > > + close(fd); > > + return NULL; > > +} > > + > > +static ssize_t _write(int fd, const void *buf, size_t count) > > +{ > > + size_t count_done = 0; > > + ssize_t ret; > > + > > + while ((count - count_done) > 0) { > > + ret = write(fd, buf + count_done, count - count_done); > > + if (ret < 0) { > > + if (errno == EINTR) > > + continue; > > + else { > > + IBND_DEBUG("write: %s\n", strerror(errno)); > > + return -1; > > + } > > + } > > + count_done += ret; > > + } > > + return count_done; > > +} > > + > > + > > +static size_t _marshall8(uint8_t *outbuf, uint8_t num) > > +{ > > + outbuf[0] = num; > > + > > + return (sizeof(num)); > > +} > > + > > +static size_t _marshall16(uint8_t *outbuf, uint16_t num) > > +{ > > + outbuf[0] = num & 0x00FF; > > + outbuf[1] = (num & 0xFF00) >> 8; > > + > > + return (sizeof(num)); > > +} > > + > > +static size_t _marshall32(uint8_t *outbuf, uint32_t num) > > +{ > > + outbuf[0] = num & 0x000000FF; > > + outbuf[1] = (num & 0x0000FF00) >> 8; > > + outbuf[2] = (num & 0x00FF0000) >> 16; > > + outbuf[3] = (num & 0xFF000000) >> 24; > > + > > + return (sizeof(num)); > > +} > > + > > +static size_t _marshall64(uint8_t *outbuf, uint64_t num) > > +{ > > + outbuf[0] = num & 0x00000000000000FFULL; > > + outbuf[1] = (num & 0x000000000000FF00ULL) >> 8; > > + outbuf[2] = (num & 0x0000000000FF0000ULL) >> 16; > > + outbuf[3] = (num & 0x00000000FF000000ULL) >> 24; > > + outbuf[4] = (num & 0x000000FF00000000ULL) >> 32; > > + outbuf[5] = (num & 0x0000FF0000000000ULL) >> 40; > > + outbuf[6] = (num & 0x00FF000000000000ULL) >> 48; > > + outbuf[7] = (num & 0xFF00000000000000ULL) >> 56; > > + > > + return (sizeof(num)); > > +} > > + > > +static size_t _marshall_buf(void *outbuf, const void *inbuf, unsigned int len) > > +{ > > + memcpy(outbuf, inbuf, len); > > + > > + return len; > > +} > > + > > +static int _cache_header_info(int fd, ibnd_fabric_t *fabric) > > +{ > > + uint8_t buf[IBND_FABRIC_CACHE_BUFLEN]; > > + size_t offset = 0; > > + > > + /* Store magic number, version, and other important info */ > > + /* For this caching lib, we always assume cached as little endian */ > > + > > + offset += _marshall32(buf + offset, IBND_FABRIC_CACHE_MAGIC); > > + offset += _marshall32(buf + offset, IBND_FABRIC_CACHE_VERSION); > > + /* save space for node count */ > > + offset += _marshall32(buf + offset, 0); > > + /* save space for port count */ > > + offset += _marshall32(buf + offset, 0); > > + offset += _marshall64(buf + offset, fabric->from_node->guid); > > + offset += _marshall32(buf + offset, fabric->maxhops_discovered); > > + > > + if (_write(fd, buf, offset) < 0) > > + return -1; > > + > > + return 0; > > +} > > + > > +static int _cache_header_counts(int fd, unsigned int node_count, unsigned int port_count) > > +{ > > + uint8_t buf[IBND_FABRIC_CACHE_BUFLEN]; > > + size_t offset = 0; > > + > > + offset += _marshall32(buf + offset, node_count); > > + offset += _marshall32(buf + offset, port_count); > > + > > + if (lseek(fd, IBND_FABRIC_CACHE_COUNT_OFFSET, SEEK_SET) < 0) { > > + IBND_DEBUG("lseek: %s\n", strerror(errno)); > > + return -1; > > + } > > + > > + if (_write(fd, buf, offset) < 0) > > + return -1; > > + > > + return 0; > > +} > > + > > +static int _cache_node(int fd, ibnd_node_t *node) > > +{ > > + uint8_t buf[IBND_FABRIC_CACHE_BUFLEN]; > > + size_t offset = 0; > > + size_t ports_stored_offset = 0; > > + unsigned int ports_stored_count = 0; > > + unsigned int i; > > + > > + offset += _marshall16(buf + offset, node->smalid); > > + offset += _marshall8(buf + offset, node->smalmc); > > + offset += _marshall8(buf + offset, node->smaenhsp0); > > + offset += _marshall_buf(buf + offset, node->switchinfo, IB_SMP_DATA_SIZE); > > + offset += _marshall64(buf + offset, node->guid); > > + offset += _marshall8(buf + offset, node->type); > > + offset += _marshall8(buf + offset, node->numports); > > + offset += _marshall_buf(buf + offset, node->info, IB_SMP_DATA_SIZE); > > + offset += _marshall_buf(buf + offset, node->nodedesc, IB_SMP_DATA_SIZE); > > + /* need to come back later and store number of stored ports > > + * because port entries can be NULL or (in the case of switches) > > + * there is an additional port 0 not accounted for in numports. > > + */ > > + ports_stored_offset = offset; > > + offset += sizeof(uint8_t); > > + > > + for (i = 0; i <= node->numports; i++) { > > + if (node->ports[i]) { > > + offset += _marshall64(buf + offset, node->ports[i]->guid); > > + offset += _marshall8(buf + offset, node->ports[i]->portnum); > > + ports_stored_count++; > > + } > > + } > > + > > + /* go back and store number of port keys stored */ > > + _marshall8(buf + ports_stored_offset, ports_stored_count); > > + > > + if (_write(fd, buf, offset) < 0) > > + return -1; > > + > > + return 0; > > +} > > + > > +static int _cache_port(int fd, ibnd_port_t *port) > > +{ > > + uint8_t buf[IBND_FABRIC_CACHE_BUFLEN]; > > + size_t offset = 0; > > + > > + offset += _marshall64(buf + offset, port->guid); > > + offset += _marshall8(buf + offset, port->portnum); > > + offset += _marshall8(buf + offset, port->ext_portnum); > > + offset += _marshall16(buf + offset, port->base_lid); > > + offset += _marshall8(buf + offset, port->lmc); > > + offset += _marshall_buf(buf + offset, port->info, IB_SMP_DATA_SIZE); > > + offset += _marshall64(buf + offset, port->node->guid); > > + if (port->remoteport) { > > + offset += _marshall8(buf + offset, 1); > > + offset += _marshall64(buf + offset, port->remoteport->guid); > > + offset += _marshall8(buf + offset, port->remoteport->portnum); > > + } > > + else { > > + offset += _marshall8(buf + offset, 0); > > + offset += _marshall64(buf + offset, 0); > > + offset += _marshall8(buf + offset, 0); > > + } > > + > > + if (_write(fd, buf, offset) < 0) > > + return -1; > > + > > + return 0; > > +} > > + > > +int ibnd_cache_fabric(ibnd_fabric_t *fabric, const char *file, unsigned int flags) > > +{ > > + struct stat statbuf; > > + ibnd_node_t *node = NULL; > > + ibnd_node_t *node_next = NULL; > > + unsigned int node_count = 0; > > + ibnd_port_t *port = NULL; > > + ibnd_port_t *port_next = NULL; > > + unsigned int port_count = 0; > > + int fd; > > + int i; > > + > > + if (!fabric) { > > + IBND_DEBUG("fabric parameter NULL\n"); > > + return -1; > > + } > > + > > + if (!file) { > > + IBND_DEBUG("file parameter NULL\n"); > > + return -1; > > + } > > + > > + if (!stat(file, &statbuf)) { > > + IBND_DEBUG("file '%s' already exists\n", file); > > + return -1; > > + } > > + > > + if ((fd = open(file, O_CREAT | O_EXCL | O_WRONLY, 0644)) < 0) { > > + IBND_DEBUG("open: %s\n", strerror(errno)); > > + return -1; > > + } > > + > > + if (_cache_header_info(fd, fabric) < 0) > > + goto cleanup; > > + > > + node = fabric->nodes; > > + while (node) { > > + node_next = node->next; > > + > > + if (_cache_node(fd, node) < 0) > > + goto cleanup; > > + > > + node_count++; > > + node = node_next; > > + } > > + > > + for (i = 0; i < HTSZ; i++) { > > + port = fabric->portstbl[i]; > > + while (port) { > > + port_next = port->htnext; > > + > > + if (_cache_port(fd, port) < 0) > > + goto cleanup; > > + > > + port_count++; > > + port = port_next; > > + } > > + } > > + > > + if (_cache_header_counts(fd, node_count, port_count) < 0) > > + goto cleanup; > > + > > + if (close(fd) < 0) { > > + IBND_DEBUG("close: %s\n", strerror(errno)); > > + goto cleanup; > > + } > > + > > + return 0; > > + > > +cleanup: > > + unlink(file); > > + close(fd); > > + return -1; > > +} > > diff --git a/infiniband-diags/libibnetdisc/src/internal.h b/infiniband-diags/libibnetdisc/src/internal.h > > index 5af5f10..348bd0f 100644 > > --- a/infiniband-diags/libibnetdisc/src/internal.h > > +++ b/infiniband-diags/libibnetdisc/src/internal.h > > @@ -62,4 +62,10 @@ typedef struct ibnd_scan { > > ib_portid_t selfportid; > > } ibnd_scan_t; > > > > +void add_to_nodeguid_hash(ibnd_node_t * node, ibnd_node_t * hash[]); > > + > > +void add_to_portguid_hash(ibnd_port_t * port, ibnd_port_t * hash[]); > > + > > +void add_to_type_list(ibnd_node_t * node, ibnd_fabric_t * fabric); > > + > > #endif /* _INTERNAL_H_ */ > > diff --git a/infiniband-diags/libibnetdisc/src/libibnetdisc.map b/infiniband-diags/libibnetdisc/src/libibnetdisc.map > > index 13bb65a..888bdd8 100644 > > --- a/infiniband-diags/libibnetdisc/src/libibnetdisc.map > > +++ b/infiniband-diags/libibnetdisc/src/libibnetdisc.map > > @@ -4,6 +4,8 @@ IBNETDISC_1.0 { > > ibnd_show_progress; > > ibnd_discover_fabric; > > ibnd_destroy_fabric; > > + ibnd_load_fabric; > > + ibnd_cache_fabric; > > ibnd_find_node_guid; > > ibnd_find_node_dr; > > ibnd_is_xsigo_guid; > > -- > > 1.5.4.5 > > > -- Albert Chu chu11-i2BcT+NCU+M@public.gmane.org Computer Scientist High Performance Systems Division Lawrence Livermore National Laboratory -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 5+ messages in thread
[parent not found: <1263658295.14626.3.camel-RLKWKRZIcZkVVsCFsIUZTRy+HRzXvqW9@public.gmane.org>]
* Re: [infiniband-diags] [UPDATED PATCH] [1/3] add libibnetdisc caching to libibnetdiscover [not found] ` <1263658295.14626.3.camel-RLKWKRZIcZkVVsCFsIUZTRy+HRzXvqW9@public.gmane.org> @ 2010-01-16 18:24 ` Sasha Khapyorsky 0 siblings, 0 replies; 5+ messages in thread From: Sasha Khapyorsky @ 2010-01-16 18:24 UTC (permalink / raw) To: Al Chu; +Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA On 08:11 Sat 16 Jan , Al Chu wrote: > > If you prefer we remove it, I can do that too. Not necessary, just wanted to be sure that this what was supposed. Sasha -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [infiniband-diags] [UPDATED PATCH] [1/3] add libibnetdisc caching to libibnetdiscover [not found] ` <1263579793.15172.166.camel-X2zTWyBD0EhliZ7u+bvwcg@public.gmane.org> 2010-01-16 14:12 ` Sasha Khapyorsky @ 2010-01-16 14:49 ` Sasha Khapyorsky 1 sibling, 0 replies; 5+ messages in thread From: Sasha Khapyorsky @ 2010-01-16 14:49 UTC (permalink / raw) To: Al Chu; +Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA On 10:23 Fri 15 Jan , Al Chu wrote: > Hi Sahsa, > > This patch adds caching functionality to libibnetdisc through the new > functions ibnd_cache_fabric() and ibnd_load_fabric(). > > Al > > -- > Albert Chu > chu11-i2BcT+NCU+M@public.gmane.org > Computer Scientist > High Performance Systems Division > Lawrence Livermore National Laboratory > From: Albert Chu <chu11-i2BcT+NCU+M@public.gmane.org> > Date: Wed, 9 Dec 2009 15:19:24 -0800 > Subject: [PATCH] add libibnetdisc caching to libibnetdiscover > > > Signed-off-by: Albert Chu <chu11-i2BcT+NCU+M@public.gmane.org> Applied. Thanks. Sasha -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2010-01-16 18:24 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-01-15 18:23 [infiniband-diags] [UPDATED PATCH] [1/3] add libibnetdisc caching to libibnetdiscover Al Chu
[not found] ` <1263579793.15172.166.camel-X2zTWyBD0EhliZ7u+bvwcg@public.gmane.org>
2010-01-16 14:12 ` Sasha Khapyorsky
2010-01-16 16:11 ` Al Chu
[not found] ` <1263658295.14626.3.camel-RLKWKRZIcZkVVsCFsIUZTRy+HRzXvqW9@public.gmane.org>
2010-01-16 18:24 ` Sasha Khapyorsky
2010-01-16 14:49 ` Sasha Khapyorsky
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox