Blame Dsap/src/dsap_topology.c

Packit 857059
/* BEGIN_ICS_COPYRIGHT4 ****************************************
Packit 857059
Packit 857059
Copyright (c) 2015-2017, Intel Corporation
Packit 857059
Packit 857059
Redistribution and use in source and binary forms, with or without
Packit 857059
modification, are permitted provided that the following conditions are met:
Packit 857059
Packit 857059
    * Redistributions of source code must retain the above copyright notice,
Packit 857059
      this list of conditions and the following disclaimer.
Packit 857059
    * Redistributions in binary form must reproduce the above copyright
Packit 857059
      notice, this list of conditions and the following disclaimer in the
Packit 857059
      documentation and/or other materials provided with the distribution.
Packit 857059
    * Neither the name of Intel Corporation nor the names of its contributors
Packit 857059
      may be used to endorse or promote products derived from this software
Packit 857059
      without specific prior written permission.
Packit 857059
Packit 857059
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Packit 857059
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit 857059
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Packit 857059
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
Packit 857059
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit 857059
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
Packit 857059
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
Packit 857059
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
Packit 857059
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit 857059
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 857059
Packit 857059
** END_ICS_COPYRIGHT4   ****************************************/
Packit 857059
Packit 857059
#include <stdio.h>
Packit 857059
#include <stdlib.h>
Packit 857059
Packit 857059
/* work around conflicting names */
Packit 857059
#include <infiniband/umad.h>
Packit 857059
#include <infiniband/verbs.h>
Packit 857059
Packit 857059
#include <arpa/inet.h>
Packit 857059
#include "opasadb_debug.h"
Packit 857059
#include "dsap.h"
Packit 857059
#include "dsap_topology.h"
Packit 857059
Packit 857059
static QUICK_LIST subnet_list;
Packit 857059
Packit 857059
/* Command line parsing */
Packit 857059
QUICK_LIST sid_range_args;
Packit 857059
static int sid_range_args_init = 0;
Packit 857059
Packit 857059
/*
Packit 857059
 * Valid formats are "SID" and "SID-SID" where "SID"
Packit 857059
 * is a 64-bit hexadecimal string.
Packit 857059
 */
Packit 857059
int dsap_service_id_range_parser(char *str, void *ptr)
Packit 857059
{
Packit 857059
	uint64 lower, upper;
Packit 857059
	dsap_service_id_record_t *record;
Packit 857059
	int err = 0;
Packit 857059
	char *k=0;
Packit 857059
Packit 857059
	if (!str || !ptr) {
Packit 857059
		acm_log(0, "Bad arguments to sid parser.\n");
Packit 857059
		err = EINVAL;
Packit 857059
		goto exit;
Packit 857059
	}
Packit 857059
Packit 857059
	if (sid_range_args_init == 0) {
Packit 857059
		sid_range_args_init = QListInit(&sid_range_args);
Packit 857059
		if (!sid_range_args_init) {
Packit 857059
			acm_log(0, "Failed to initialize quick list.\n");
Packit 857059
			err = ENOMEM;
Packit 857059
			goto exit;
Packit 857059
		}
Packit 857059
	}
Packit 857059
Packit 857059
	record = malloc(sizeof(dsap_service_id_record_t));
Packit 857059
	if (!record) {
Packit 857059
		acm_log(0, "Failed to allocate memory.\n");
Packit 857059
		err = ENOMEM;
Packit 857059
		goto exit;
Packit 857059
	}
Packit 857059
	memset(record, 0, sizeof(dsap_service_id_record_t));
Packit 857059
Packit 857059
	/* Disabling ranged parameters for now.
Packit 857059
	k = strchr(str,'-');
Packit 857059
	if (k) *k=0; */
Packit 857059
Packit 857059
	lower = strtoull(str, NULL, 0);
Packit 857059
	upper = (k)? strtoull(k+1, NULL, 0) : 0;
Packit 857059
Packit 857059
	record->service_id_range.warned = 0;
Packit 857059
	record->service_id_range.lower_service_id = hton64(lower);
Packit 857059
	record->service_id_range.upper_service_id = hton64(upper);
Packit 857059
Packit 857059
	QListSetObj(&record->item, record);
Packit 857059
	QListInsertTail(&sid_range_args, &record->item);
Packit 857059
Packit 857059
exit:
Packit 857059
	return err;
Packit 857059
}
Packit 857059
Packit 857059
/*
Packit 857059
 * Note that this function isn't re-entrant.
Packit 857059
 */
Packit 857059
char *dsap_service_id_range_printer(void *ptr)
Packit 857059
{
Packit 857059
	static char buffer[1024];
Packit 857059
	int p = 0;
Packit 857059
	LIST_ITEM *item;
Packit 857059
	dsap_service_id_record_t *record;
Packit 857059
	uint64_t lo, hi;
Packit 857059
	int count = 0;
Packit 857059
Packit 857059
	if (!sid_range_args_init)
Packit 857059
		return "";
Packit 857059
	else
Packit 857059
		p += sprintf(&buffer[p], "\n\t\t");
Packit 857059
	for (item = QListHead(&sid_range_args);
Packit 857059
		item != NULL && p<960; 
Packit 857059
		item = QListNext(&sid_range_args, item)) {
Packit 857059
		record = QListObj(item);
Packit 857059
		if (record->service_id_range.upper_service_id) {
Packit 857059
			lo = record->service_id_range.lower_service_id;
Packit 857059
			hi = record->service_id_range.upper_service_id;
Packit 857059
			p += sprintf(&buffer[p],
Packit 857059
				     "[0x%016"PRIx64"-0x%016"PRIx64"] ",
Packit 857059
				     ntoh64(lo), ntoh64(hi));
Packit 857059
			count += 2;
Packit 857059
		} else {
Packit 857059
			lo = record->service_id_range.lower_service_id;
Packit 857059
			p +=  sprintf(&buffer[p],"0x%016"PRIx64" ",
Packit 857059
				      ntoh64(lo));
Packit 857059
			count++;
Packit 857059
		}
Packit 857059
		if (!(count % 4))
Packit 857059
			p += sprintf(&buffer[p], "\n\t\t");
Packit 857059
	}
Packit 857059
Packit 857059
	return buffer;
Packit 857059
}
Packit 857059
Packit 857059
/* Comparison Callback Functions */
Packit 857059
Packit 857059
static boolean dsap_compare_pkey(LIST_ITEM *item, void *context)
Packit 857059
{
Packit 857059
	dsap_pkey_t *pkey_item = QListObj(item);
Packit 857059
	uint16_t *pkey = context;
Packit 857059
Packit 857059
	return (pkey_item->pkey == *pkey);
Packit 857059
}
Packit 857059
Packit 857059
static boolean dsap_compare_src_port(LIST_ITEM *item, void *context)
Packit 857059
{
Packit 857059
	dsap_src_port_t *src_port = QListObj(item);
Packit 857059
	union ibv_gid *gid = context;
Packit 857059
Packit 857059
	return (src_port->gid.global.interface_id == gid->global.interface_id);
Packit 857059
}
Packit 857059
Packit 857059
static boolean dsap_compare_src_port_by_lid(LIST_ITEM *item, void *context)
Packit 857059
{
Packit 857059
	dsap_src_port_t *src_port = QListObj(item);
Packit 857059
	unsigned *lid = context;
Packit 857059
	unsigned mask = 0xffff - ((1 << src_port->lmc) - 1);
Packit 857059
Packit 857059
	return ((src_port->base_lid & mask )== (*lid & mask));
Packit 857059
}
Packit 857059
Packit 857059
static boolean dsap_compare_path(LIST_ITEM *item, void *context)
Packit 857059
{
Packit 857059
	dsap_path_record_t *dsap_path = QListObj(item);
Packit 857059
	IB_PATH_RECORD_NO *path     = context;
Packit 857059
	uint16_t key_mask           = htons(0x7fff);
Packit 857059
Packit 857059
	/* Compare Incoming parameters */
Packit 857059
	if (path->ServiceID && (path->ServiceID != dsap_path->path.ServiceID))
Packit 857059
		return 0;
Packit 857059
Packit 857059
	if (path->DGID.Type.Global.InterfaceID && 
Packit 857059
	    (path->DGID.Type.Global.InterfaceID != 
Packit 857059
	     dsap_path->path.DGID.Type.Global.InterfaceID)) 
Packit 857059
		return 0;
Packit 857059
Packit 857059
	if (path->DGID.Type.Global.SubnetPrefix && 
Packit 857059
	    (path->DGID.Type.Global.SubnetPrefix != 
Packit 857059
	     dsap_path->path.DGID.Type.Global.SubnetPrefix)) 
Packit 857059
		return 0;
Packit 857059
Packit 857059
	if (path->DLID && (path->DLID != dsap_path->path.DLID)) 
Packit 857059
		return 0;
Packit 857059
Packit 857059
	if ((path->P_Key & key_mask) && 
Packit 857059
	    (path->P_Key & key_mask) != (dsap_path->path.P_Key & key_mask))
Packit 857059
		return 0;
Packit 857059
Packit 857059
	/* Found */
Packit 857059
	return 1;
Packit 857059
}
Packit 857059
Packit 857059
Packit 857059
static boolean dsap_compare_dst_port(LIST_ITEM *item, void *context)
Packit 857059
{
Packit 857059
	dsap_dst_port_t *dst_port = QListObj(item);
Packit 857059
	union ibv_gid  *gid      = context;
Packit 857059
Packit 857059
	return (dst_port->gid.global.interface_id == gid->global.interface_id);
Packit 857059
}
Packit 857059
Packit 857059
static boolean dsap_compare_dst_port_by_name(LIST_ITEM *item, void *context)
Packit 857059
{
Packit 857059
	dsap_dst_port_t *dst_port = QListObj(item);
Packit 857059
	char  *desc      = (char *)context;
Packit 857059
Packit 857059
	/* We are not doing the exact match here. As long as the user provided
Packit 857059
	   destination is part of the node description, it will be fine for us.
Packit 857059
	   */
Packit 857059
	return (0 == strncasecmp(dst_port->node_desc, desc, strlen(desc))); 
Packit 857059
}
Packit 857059
Packit 857059
static boolean dsap_compare_service_id_record(LIST_ITEM *item, void *context)
Packit 857059
{
Packit 857059
	dsap_service_id_record_t *rec = QListObj(item);
Packit 857059
	dsap_service_id_range_t  *range  = context;
Packit 857059
Packit 857059
	return ((rec->service_id_range.lower_service_id == 
Packit 857059
		 range->lower_service_id) &&
Packit 857059
		(rec->service_id_range.upper_service_id == 
Packit 857059
		 range->upper_service_id));
Packit 857059
}
Packit 857059
Packit 857059
static boolean dsap_compare_virtual_fabric(LIST_ITEM *item, void *context)
Packit 857059
{
Packit 857059
	dsap_virtual_fabric_t *virtual_fabric = QListObj(item);
Packit 857059
	uint8_t *vfName = context;
Packit 857059
Packit 857059
	return (strncmp((const char*)virtual_fabric->vfinfo_record.vfName,
Packit 857059
			(const char*)vfName,
Packit 857059
			sizeof(virtual_fabric->vfinfo_record.vfName)) == 0);
Packit 857059
}
Packit 857059
Packit 857059
static boolean dsap_compare_subnet(LIST_ITEM *item, void *context)
Packit 857059
{
Packit 857059
	dsap_subnet_t *subnet = QListObj(item);
Packit 857059
	uint64_t * subnet_prefix = context;
Packit 857059
Packit 857059
	return (subnet->subnet_prefix == *subnet_prefix);
Packit 857059
}
Packit 857059
Packit 857059
/* Search Utility Routines */
Packit 857059
Packit 857059
dsap_subnet_t* dsap_find_subnet(uint64_t *subnet_prefix)
Packit 857059
{
Packit 857059
	LIST_ITEM *item = QListFindItem(&subnet_list, dsap_compare_subnet,
Packit 857059
					subnet_prefix);
Packit 857059
Packit 857059
	return item ? QListObj(item) : NULL;
Packit 857059
}
Packit 857059
Packit 857059
dsap_src_port_t* dsap_find_src_port(union ibv_gid *gid)
Packit 857059
{
Packit 857059
	LIST_ITEM *subnet_item;
Packit 857059
	dsap_subnet_t *subnet;
Packit 857059
	LIST_ITEM *src_port_item;
Packit 857059
Packit 857059
	for_each (&subnet_list, subnet_item) {
Packit 857059
		subnet = QListObj(subnet_item);
Packit 857059
		src_port_item = QListFindItem(&subnet->src_port_list, 
Packit 857059
					      dsap_compare_src_port, gid);
Packit 857059
		if (src_port_item) 
Packit 857059
			return QListObj(src_port_item);
Packit 857059
	}
Packit 857059
Packit 857059
	return NULL;
Packit 857059
}
Packit 857059
Packit 857059
dsap_src_port_t* dsap_find_src_port_by_lid(unsigned *lid)
Packit 857059
{
Packit 857059
	LIST_ITEM *subnet_item;
Packit 857059
	dsap_subnet_t *subnet;
Packit 857059
	LIST_ITEM *src_port_item;
Packit 857059
Packit 857059
	for_each (&subnet_list, subnet_item) {
Packit 857059
		subnet = QListObj(subnet_item);
Packit 857059
		src_port_item = QListFindItem(&subnet->src_port_list,
Packit 857059
					      dsap_compare_src_port_by_lid,
Packit 857059
					      lid);
Packit 857059
		if (src_port_item)
Packit 857059
			return QListObj(src_port_item);
Packit 857059
	}
Packit 857059
Packit 857059
	return NULL;
Packit 857059
}
Packit 857059
Packit 857059
dsap_path_record_t * dsap_find_path_record(dsap_src_port_t *src_port,
Packit 857059
					   IB_PATH_RECORD_NO *path)
Packit 857059
{
Packit 857059
	LIST_ITEM *path_item = QListFindFromHead(&src_port->path_record_list,
Packit 857059
						 dsap_compare_path, path);
Packit 857059
	if (path_item) 
Packit 857059
		return QListObj(path_item);
Packit 857059
	return NULL;
Packit 857059
}
Packit 857059
Packit 857059
Packit 857059
dsap_dst_port_t* dsap_find_dst_port(union ibv_gid *gid)
Packit 857059
{
Packit 857059
	LIST_ITEM *subnet_item;
Packit 857059
	LIST_ITEM *dst_port_item;
Packit 857059
Packit 857059
	for_each (&subnet_list, subnet_item) {
Packit 857059
		dsap_subnet_t *subnet = QListObj(subnet_item);
Packit 857059
		dst_port_item = QListFindItem(&subnet->dst_port_list,
Packit 857059
					      dsap_compare_dst_port, gid);
Packit 857059
		if (dst_port_item)
Packit 857059
			return QListObj(dst_port_item);
Packit 857059
	}
Packit 857059
Packit 857059
	return NULL;
Packit 857059
}
Packit 857059
Packit 857059
dsap_dst_port_t* dsap_find_dst_port_by_name(char *node_desc)
Packit 857059
{
Packit 857059
	LIST_ITEM *subnet_item;
Packit 857059
	LIST_ITEM *dst_port_item;
Packit 857059
Packit 857059
	for_each (&subnet_list, subnet_item) {
Packit 857059
		dsap_subnet_t *subnet = QListObj(subnet_item);
Packit 857059
		dst_port_item = QListFindItem(&subnet->dst_port_list,
Packit 857059
					      dsap_compare_dst_port_by_name,
Packit 857059
					      node_desc);
Packit 857059
		if (dst_port_item) {
Packit 857059
			return QListObj(dst_port_item);
Packit 857059
		}
Packit 857059
	}
Packit 857059
Packit 857059
	return NULL;
Packit 857059
}
Packit 857059
Packit 857059
dsap_virtual_fabric_t* dsap_find_virtual_fabric(uint8_t *vfName, 
Packit 857059
						dsap_subnet_t *subnet)
Packit 857059
{
Packit 857059
	LIST_ITEM *vf_item;
Packit 857059
	LIST_ITEM *subnet_item;
Packit 857059
Packit 857059
	if (subnet) {
Packit 857059
		vf_item = QListFindItem(&subnet->virtual_fabric_list, 
Packit 857059
					dsap_compare_virtual_fabric, vfName);
Packit 857059
		return vf_item ? QListObj(vf_item) : NULL;
Packit 857059
	}
Packit 857059
Packit 857059
	for_each (&subnet_list, subnet_item) {
Packit 857059
		subnet = (dsap_subnet_t *)ListObj(subnet_item);
Packit 857059
		vf_item = QListFindItem(&subnet->virtual_fabric_list, 
Packit 857059
					dsap_compare_virtual_fabric, vfName);
Packit 857059
		if (vf_item) 
Packit 857059
			return QListObj(vf_item);
Packit 857059
	}
Packit 857059
Packit 857059
	return NULL;
Packit 857059
}
Packit 857059
Packit 857059
size_t dsap_tot_src_port_count(void)
Packit 857059
{
Packit 857059
	size_t total_count = 0;
Packit 857059
	LIST_ITEM *item;
Packit 857059
Packit 857059
	for_each (&subnet_list, item) {
Packit 857059
		total_count += dsap_src_port_count(
Packit 857059
		   (dsap_subnet_t*)QListObj(item));
Packit 857059
	}
Packit 857059
Packit 857059
	return total_count;
Packit 857059
}
Packit 857059
Packit 857059
size_t dsap_tot_dst_port_count(void)
Packit 857059
{
Packit 857059
	size_t total_count = 0;
Packit 857059
	LIST_ITEM *item;
Packit 857059
Packit 857059
	for_each (&subnet_list, item) {
Packit 857059
		total_count += dsap_dst_port_count(
Packit 857059
		   (dsap_subnet_t*)QListObj(item));
Packit 857059
	}
Packit 857059
Packit 857059
	return total_count;
Packit 857059
}
Packit 857059
Packit 857059
size_t dsap_tot_vfab_count(void)
Packit 857059
{
Packit 857059
	size_t total_count = 0;
Packit 857059
	LIST_ITEM *item;
Packit 857059
Packit 857059
	for_each (&subnet_list, item) {
Packit 857059
		total_count += dsap_virtual_fabric_count(
Packit 857059
		   (dsap_subnet_t*)QListObj(item));
Packit 857059
	}
Packit 857059
Packit 857059
	return total_count;
Packit 857059
}
Packit 857059
Packit 857059
size_t dsap_tot_sid_rec_count(void)
Packit 857059
{
Packit 857059
	size_t total_count = 0;
Packit 857059
	LIST_ITEM *item1, *item2;
Packit 857059
	dsap_subnet_t *subnet;
Packit 857059
Packit 857059
	for_each (&subnet_list, item1) {
Packit 857059
		subnet = QListObj(item1);
Packit 857059
		
Packit 857059
		for_each (&subnet->virtual_fabric_list, item2) {
Packit 857059
			total_count += dsap_service_id_record_count(
Packit 857059
			   (dsap_virtual_fabric_t*)QListObj(item2));
Packit 857059
		}
Packit 857059
	}
Packit 857059
Packit 857059
	return total_count;
Packit 857059
}
Packit 857059
Packit 857059
size_t dsap_subnet_path_record_count(dsap_subnet_t *subnet)
Packit 857059
{
Packit 857059
	size_t total_count = 0;
Packit 857059
	LIST_ITEM *item;
Packit 857059
	for_each (&subnet->src_port_list, item) {
Packit 857059
		total_count += dsap_path_record_count(
Packit 857059
		   (dsap_src_port_t*)QListObj(item));
Packit 857059
	}
Packit 857059
Packit 857059
	return total_count;
Packit 857059
}
Packit 857059
Packit 857059
size_t dsap_tot_path_rec_count(void)
Packit 857059
{
Packit 857059
	size_t total_count = 0;
Packit 857059
	LIST_ITEM *item1;
Packit 857059
	dsap_subnet_t *subnet;
Packit 857059
Packit 857059
	for_each (&subnet_list, item1) {
Packit 857059
		subnet = QListObj(item1);
Packit 857059
		total_count += dsap_subnet_path_record_count(subnet);
Packit 857059
	}
Packit 857059
Packit 857059
	return total_count;
Packit 857059
}
Packit 857059
Packit 857059
size_t dsap_tot_pkey_count(void)
Packit 857059
{
Packit 857059
	size_t total_count = 0;
Packit 857059
	LIST_ITEM *item1, *item2;
Packit 857059
Packit 857059
	for_each (&subnet_list, item1) {
Packit 857059
		dsap_subnet_t *subnet = QListObj(item1);
Packit 857059
		
Packit 857059
		for_each (&subnet->src_port_list, item2) {
Packit 857059
			total_count += dsap_pkey_count(
Packit 857059
			   (dsap_src_port_t*)QListObj(item2));
Packit 857059
		}
Packit 857059
	}
Packit 857059
Packit 857059
	return total_count;
Packit 857059
}
Packit 857059
Packit 857059
/* PKEY Handling functions */
Packit 857059
Packit 857059
size_t dsap_pkey_count(dsap_src_port_t *src_port)
Packit 857059
{
Packit 857059
	return QListCount(&src_port->pkey_list);
Packit 857059
}
Packit 857059
Packit 857059
/* pkey is in network byte order */
Packit 857059
FSTATUS dsap_add_pkey(dsap_src_port_t *src_port, uint16_t pkey)
Packit 857059
{
Packit 857059
	dsap_pkey_t *new_pkey = malloc(sizeof(*new_pkey));
Packit 857059
Packit 857059
	if (new_pkey == NULL)
Packit 857059
		return FINSUFFICIENT_MEMORY;
Packit 857059
Packit 857059
	ListItemInitState(&new_pkey->item);
Packit 857059
	QListSetObj(&new_pkey->item, new_pkey);
Packit 857059
	new_pkey->pkey = pkey;
Packit 857059
	QListInsertTail(&src_port->pkey_list, &new_pkey->item);
Packit 857059
Packit 857059
	return FSUCCESS;
Packit 857059
}
Packit 857059
Packit 857059
FSTATUS dsap_empty_pkey_list(dsap_src_port_t *src_port)
Packit 857059
{
Packit 857059
	LIST_ITEM *item;
Packit 857059
Packit 857059
	while ((item = QListRemoveHead(&src_port->pkey_list)) != NULL) {
Packit 857059
		free(QListObj(item));
Packit 857059
	}
Packit 857059
Packit 857059
	return FSUCCESS;
Packit 857059
}
Packit 857059
Packit 857059
FSTATUS dsap_remove_pkey(dsap_src_port_t *src_port, uint16_t pkey)
Packit 857059
{
Packit 857059
	LIST_ITEM *item = 
Packit 857059
		QListFindItem(&src_port->pkey_list, dsap_compare_pkey, &pkey);
Packit 857059
Packit 857059
	if (!item)
Packit 857059
		return FNOT_FOUND;
Packit 857059
Packit 857059
	QListRemoveItem(&src_port->pkey_list, item);
Packit 857059
	free(QListObj(item));
Packit 857059
Packit 857059
	return FSUCCESS;
Packit 857059
}
Packit 857059
Packit 857059
/* Path Record Handling functions */
Packit 857059
Packit 857059
size_t dsap_path_record_count(dsap_src_port_t *src_port)
Packit 857059
{
Packit 857059
	return QListCount(&src_port->path_record_list);
Packit 857059
}
Packit 857059
Packit 857059
FSTATUS dsap_add_path_record(dsap_src_port_t *src_port,
Packit 857059
			     IB_PATH_RECORD_NO *path_record)
Packit 857059
{
Packit 857059
	dsap_path_record_t *new_path_record = malloc(sizeof(*new_path_record));
Packit 857059
Packit 857059
	if (new_path_record == NULL) 
Packit 857059
		return FINSUFFICIENT_MEMORY;
Packit 857059
Packit 857059
	ListItemInitState(&new_path_record->item);
Packit 857059
	QListSetObj(&new_path_record->item, new_path_record);
Packit 857059
	new_path_record->path = *path_record;
Packit 857059
	QListInsertTail(&src_port->path_record_list, &new_path_record->item);
Packit 857059
Packit 857059
	return FSUCCESS;
Packit 857059
}
Packit 857059
Packit 857059
Packit 857059
FSTATUS dsap_empty_path_record_list(dsap_src_port_t *src_port)
Packit 857059
{
Packit 857059
	LIST_ITEM *item;
Packit 857059
Packit 857059
	while ((item = QListRemoveHead(&src_port->path_record_list)) != NULL) {
Packit 857059
		free(QListObj(item));
Packit 857059
	}
Packit 857059
Packit 857059
	return FSUCCESS;
Packit 857059
}
Packit 857059
Packit 857059
FSTATUS dsap_remove_path_records(dsap_src_port_t *src_port, 
Packit 857059
				 union ibv_gid *dst_port_gid)
Packit 857059
{
Packit 857059
	LIST_ITEM *item, *next_item;
Packit 857059
	dsap_path_record_t *path_record;
Packit 857059
Packit 857059
	for (item = QListHead(&src_port->path_record_list); item != NULL;
Packit 857059
	      item = next_item) {
Packit 857059
		next_item = QListNext(&src_port->path_record_list, item);
Packit 857059
		path_record = QListObj(item);
Packit 857059
		if (dst_port_gid->global.interface_id == 
Packit 857059
		    path_record->path.DGID.Type.Global.InterfaceID) {
Packit 857059
			QListRemoveItem(&src_port->path_record_list, 
Packit 857059
					&path_record->item);
Packit 857059
			free(path_record);
Packit 857059
		}
Packit 857059
	}
Packit 857059
Packit 857059
	return FSUCCESS;
Packit 857059
}
Packit 857059
Packit 857059
/* Src Port Handling functions */
Packit 857059
Packit 857059
size_t dsap_src_port_count(dsap_subnet_t *subnet)
Packit 857059
{
Packit 857059
	return QListCount(&subnet->src_port_list);
Packit 857059
}
Packit 857059
Packit 857059
/* The port lock is held */
Packit 857059
FSTATUS dsap_update_src_port(dsap_src_port_t *src_port, struct dsap_port *port)
Packit 857059
{
Packit 857059
	LIST_ITEM * ep_item;
Packit 857059
	struct dsap_ep *ep;
Packit 857059
Packit 857059
	strncpy(src_port->hfi_name, port->dev->device->verbs->device->name,
Packit 857059
		sizeof(src_port->hfi_name)-1);
Packit 857059
	src_port->hfi_name[sizeof(src_port->hfi_name)-1]=0;
Packit 857059
	src_port->port_num = port->port->port_num;
Packit 857059
	src_port->base_lid = port->lid;
Packit 857059
	src_port->lmc = port->lmc;
Packit 857059
	src_port->state = port->state;
Packit 857059
	dsap_empty_pkey_list(src_port);
Packit 857059
	dsap_empty_path_record_list(src_port);
Packit 857059
	
Packit 857059
	/* Get the pkey from the ep list */
Packit 857059
	for_each(&port->ep_list, ep_item) {
Packit 857059
		ep = QListObj(ep_item);
Packit 857059
		if (dsap_add_pkey(src_port, htons(ep->endpoint->pkey))
Packit 857059
		    != FSUCCESS) {
Packit 857059
			dsap_empty_pkey_list(src_port);
Packit 857059
			return FINSUFFICIENT_MEMORY;
Packit 857059
		}
Packit 857059
	}
Packit 857059
Packit 857059
	acm_log(2, "Updated port %d on HFI %s: base_lid 0x%x, lmc 0x%x\n",
Packit 857059
		src_port->port_num, src_port->hfi_name,
Packit 857059
		src_port->base_lid, src_port->lmc);
Packit 857059
Packit 857059
	return FSUCCESS;
Packit 857059
}
Packit 857059
Packit 857059
FSTATUS dsap_remove_src_port(union ibv_gid *src_gid)
Packit 857059
{
Packit 857059
	dsap_src_port_t *src_port;
Packit 857059
	dsap_subnet_t *subnet;
Packit 857059
Packit 857059
	acm_log(2, "\n");
Packit 857059
Packit 857059
	src_port = dsap_find_src_port(src_gid);
Packit 857059
	if (!src_port) 
Packit 857059
		return FNOT_FOUND;
Packit 857059
Packit 857059
	/* It should be in the dst port list */
Packit 857059
	if (dsap_remove_dst_port(src_gid)) {
Packit 857059
		acm_log(0, "Failure Removing Dst Port 0x%016"PRIx64":0x%016"
Packit 857059
			   PRIx64"\n",
Packit 857059
			ntoh64(src_gid->global.subnet_prefix),
Packit 857059
			ntoh64(src_gid->global.interface_id));
Packit 857059
	}
Packit 857059
Packit 857059
	dsap_empty_pkey_list(src_port);
Packit 857059
	dsap_empty_path_record_list(src_port);
Packit 857059
Packit 857059
	subnet = dsap_find_subnet((uint64_t *)&src_port->gid.global.subnet_prefix);
Packit 857059
	if (subnet) 
Packit 857059
		QListRemoveItem(&subnet->src_port_list, &src_port->item);
Packit 857059
Packit 857059
	free(src_port);
Packit 857059
Packit 857059
	return FSUCCESS;
Packit 857059
}
Packit 857059
Packit 857059
/* The port lock is held */
Packit 857059
FSTATUS dsap_add_src_port(struct dsap_port *port)
Packit 857059
{
Packit 857059
	FSTATUS rval;
Packit 857059
	dsap_subnet_t *subnet;
Packit 857059
	union ibv_gid src_port_gid;
Packit 857059
	dsap_src_port_t *src_port;
Packit 857059
Packit 857059
	if (acm_get_gid((struct acm_port *) port->port, 0, &src_port_gid))
Packit 857059
		return FNOT_FOUND;
Packit 857059
Packit 857059
Packit 857059
	subnet = dsap_find_subnet((uint64_t *)&src_port_gid.global.subnet_prefix);
Packit 857059
	if (!subnet) {
Packit 857059
		if (dsap_add_subnet(src_port_gid.global.subnet_prefix) != 
Packit 857059
		    FSUCCESS)
Packit 857059
			return FINSUFFICIENT_MEMORY;
Packit 857059
Packit 857059
		subnet = dsap_find_subnet((uint64_t *)&src_port_gid.global.subnet_prefix);
Packit 857059
		if (!subnet) 
Packit 857059
			return FNOT_FOUND; /* This better not happen */
Packit 857059
	}
Packit 857059
Packit 857059
	src_port = dsap_find_src_port(&src_port_gid);
Packit 857059
	if (src_port) 
Packit 857059
		return FDUPLICATE;
Packit 857059
Packit 857059
	src_port = malloc(sizeof(*src_port));
Packit 857059
	if (src_port == NULL) {
Packit 857059
		return FINSUFFICIENT_MEMORY;
Packit 857059
	}
Packit 857059
Packit 857059
	ListItemInitState(&src_port->item);
Packit 857059
	QListSetObj(&src_port->item, src_port);
Packit 857059
	src_port->gid = src_port_gid;
Packit 857059
	QListInitState(&src_port->pkey_list);
Packit 857059
	QListInit(&src_port->pkey_list);
Packit 857059
	QListInitState(&src_port->path_record_list);
Packit 857059
	QListInit(&src_port->path_record_list);
Packit 857059
	QListInsertTail(&subnet->src_port_list, &src_port->item);
Packit 857059
Packit 857059
	rval = dsap_update_src_port(src_port, port);
Packit 857059
	if (rval != FSUCCESS) {
Packit 857059
		free(src_port);
Packit 857059
		return rval;
Packit 857059
	}
Packit 857059
Packit 857059
	acm_log(2, "Added port %d on HFI %s\n", src_port->port_num, 
Packit 857059
		src_port->hfi_name);
Packit 857059
Packit 857059
	return FSUCCESS;
Packit 857059
}
Packit 857059
Packit 857059
FSTATUS dsap_empty_src_port_list(dsap_subnet_t *subnet)
Packit 857059
{
Packit 857059
	LIST_ITEM *item;
Packit 857059
Packit 857059
	while ((item = QListRemoveHead(&subnet->src_port_list)) != NULL) {
Packit 857059
		dsap_src_port_t *src_port = QListObj(item);
Packit 857059
		dsap_empty_path_record_list(src_port);
Packit 857059
		dsap_empty_pkey_list(src_port);
Packit 857059
		QListDestroy(&src_port->path_record_list);
Packit 857059
		free(src_port);
Packit 857059
	}
Packit 857059
Packit 857059
	return FSUCCESS;
Packit 857059
}
Packit 857059
Packit 857059
/* Dst Port Handling functions */
Packit 857059
Packit 857059
size_t dsap_dst_port_count(dsap_subnet_t *subnet)
Packit 857059
{
Packit 857059
	return QListCount(&subnet->dst_port_list);
Packit 857059
}
Packit 857059
Packit 857059
FSTATUS dsap_add_dst_port(union ibv_gid *dst_port_gid, NODE_TYPE node_type,
Packit 857059
			  char * node_desc)
Packit 857059
{
Packit 857059
	dsap_subnet_t *subnet = dsap_find_subnet(
Packit 857059
				(uint64_t *)&dst_port_gid->global.subnet_prefix);
Packit 857059
	dsap_dst_port_t *dst_port;
Packit 857059
Packit 857059
	if (!subnet) 
Packit 857059
		return FNOT_DONE;
Packit 857059
Packit 857059
	dst_port = dsap_find_dst_port(dst_port_gid);
Packit 857059
	if (dst_port) 
Packit 857059
		return FDUPLICATE;
Packit 857059
Packit 857059
	dst_port = malloc(sizeof(*dst_port));
Packit 857059
	if (dst_port == NULL) 
Packit 857059
		return FINSUFFICIENT_MEMORY;
Packit 857059
Packit 857059
	ListItemInitState(&dst_port->item);
Packit 857059
	QListSetObj(&dst_port->item, dst_port);
Packit 857059
	dst_port->gid       = *dst_port_gid;
Packit 857059
	dst_port->node_type = node_type;
Packit 857059
	memcpy(dst_port->node_desc, node_desc, NODE_DESCRIPTION_ARRAY_SIZE);
Packit 857059
	QListInsertTail(&subnet->dst_port_list, &dst_port->item);
Packit 857059
Packit 857059
#ifdef PRINT_PORTS_FOUND
Packit 857059
	if (dst_port->node_type == STL_NODE_FI) {
Packit 857059
		acm_log(2, "Added HFI Port 0x%016"PRIx64":0x%016"PRIx64"\n",
Packit 857059
			ntoh64(dst_port->gid.global.subnet_prefix),
Packit 857059
			ntoh64(dst_port->gid.global.interface_id));
Packit 857059
	} else {
Packit 857059
		acm_log(2, "Added Switch Port 0x%016"PRIx64":0x%016"PRIx64"\n",
Packit 857059
			ntoh64(dst_port->gid.global.subnet_prefix),
Packit 857059
			ntoh64(dst_port->gid.global.interface_id));
Packit 857059
	}
Packit 857059
#endif
Packit 857059
Packit 857059
	return FSUCCESS;
Packit 857059
}
Packit 857059
Packit 857059
FSTATUS dsap_empty_dst_port_list(dsap_subnet_t *subnet)
Packit 857059
{
Packit 857059
	LIST_ITEM *item;
Packit 857059
Packit 857059
	while ((item = QListRemoveHead(&subnet->dst_port_list)) != NULL) {
Packit 857059
		free(QListObj(item));
Packit 857059
	}
Packit 857059
Packit 857059
	return FSUCCESS;
Packit 857059
}
Packit 857059
Packit 857059
FSTATUS dsap_remove_dst_port(union ibv_gid *dst_port_gid)
Packit 857059
{
Packit 857059
	dsap_subnet_t *subnet;
Packit 857059
	dsap_dst_port_t *dst_port;
Packit 857059
	LIST_ITEM *item;
Packit 857059
Packit 857059
	dst_port = dsap_find_dst_port(dst_port_gid);
Packit 857059
	if (!dst_port) {
Packit 857059
		return FNOT_FOUND;
Packit 857059
	}
Packit 857059
Packit 857059
	subnet = dsap_find_subnet((uint64_t *)&dst_port_gid->global.subnet_prefix);
Packit 857059
	if (!subnet) {
Packit 857059
		free(dst_port);
Packit 857059
		return FNOT_FOUND;
Packit 857059
	}
Packit 857059
Packit 857059
	if (dst_port->node_type == STL_NODE_FI) {
Packit 857059
		for_each (&subnet->src_port_list, item) {
Packit 857059
			dsap_remove_path_records(
Packit 857059
			   (dsap_src_port_t *)ListObj(item), &dst_port->gid);
Packit 857059
		}
Packit 857059
	}
Packit 857059
Packit 857059
	QListRemoveItem(&subnet->dst_port_list, &dst_port->item);
Packit 857059
	free(dst_port);
Packit 857059
Packit 857059
	return FSUCCESS;
Packit 857059
}
Packit 857059
Packit 857059
/* Service ID Record Handling functions */
Packit 857059
Packit 857059
size_t dsap_service_id_record_count(dsap_virtual_fabric_t *virtual_fabric)
Packit 857059
{
Packit 857059
	return QListCount(&virtual_fabric->service_id_record_list);
Packit 857059
}
Packit 857059
Packit 857059
FSTATUS dsap_add_service_id_record(dsap_virtual_fabric_t *virtual_fabric,
Packit 857059
				   dsap_service_id_range_t *service_id_range)
Packit 857059
{
Packit 857059
	LIST_ITEM *item = QListFindItem(&virtual_fabric->service_id_record_list,
Packit 857059
					dsap_compare_service_id_record, 
Packit 857059
					service_id_range);
Packit 857059
	dsap_service_id_record_t *new_service_id_record;
Packit 857059
Packit 857059
	if (item) 
Packit 857059
		return FDUPLICATE;
Packit 857059
Packit 857059
	new_service_id_record = malloc(sizeof(*new_service_id_record));
Packit 857059
	if (new_service_id_record == NULL) {
Packit 857059
		return FINSUFFICIENT_MEMORY;
Packit 857059
	}
Packit 857059
Packit 857059
	ListItemInitState(&new_service_id_record->item);
Packit 857059
	QListSetObj(&new_service_id_record->item, new_service_id_record);
Packit 857059
	new_service_id_record->service_id_range = *service_id_range;
Packit 857059
	QListInsertTail(&virtual_fabric->service_id_record_list, 
Packit 857059
			&new_service_id_record->item);
Packit 857059
Packit 857059
	return FSUCCESS;
Packit 857059
}
Packit 857059
Packit 857059
FSTATUS dsap_empty_service_id_record_list(dsap_virtual_fabric_t *vfab)
Packit 857059
{
Packit 857059
	LIST_ITEM *item;
Packit 857059
Packit 857059
	while ((item = QListRemoveHead(&vfab->service_id_record_list))
Packit 857059
	       != NULL) {
Packit 857059
		free(QListObj(item));
Packit 857059
	}
Packit 857059
Packit 857059
	return FSUCCESS;
Packit 857059
}
Packit 857059
Packit 857059
FSTATUS dsap_remove_service_id_record(dsap_virtual_fabric_t *vfab,
Packit 857059
				      dsap_service_id_range_t *sid_range)
Packit 857059
{
Packit 857059
	LIST_ITEM *item = QListFindItem(&vfab->service_id_record_list,
Packit 857059
					dsap_compare_service_id_record,
Packit 857059
					sid_range);
Packit 857059
Packit 857059
	if (!item) 
Packit 857059
		return FNOT_FOUND;
Packit 857059
Packit 857059
	QListRemoveItem(&vfab->service_id_record_list, item);
Packit 857059
	free(QListObj(item));
Packit 857059
Packit 857059
	return FSUCCESS;
Packit 857059
}
Packit 857059
Packit 857059
/* Virtual Fabric Record Handling functions */
Packit 857059
Packit 857059
size_t dsap_virtual_fabric_count(dsap_subnet_t *subnet)
Packit 857059
{
Packit 857059
	return QListCount(&subnet->virtual_fabric_list);
Packit 857059
}
Packit 857059
Packit 857059
FSTATUS dsap_add_virtual_fabric(dsap_subnet_t *subnet,
Packit 857059
				STL_VFINFO_RECORD *vfinfo_record)
Packit 857059
{
Packit 857059
	dsap_virtual_fabric_t *vfab = 
Packit 857059
		dsap_find_virtual_fabric(vfinfo_record->vfName, subnet);
Packit 857059
Packit 857059
	if (vfab) 
Packit 857059
		return FDUPLICATE;
Packit 857059
Packit 857059
	vfab = malloc(sizeof(*vfab));
Packit 857059
	if (vfab == NULL) 
Packit 857059
		return FINSUFFICIENT_MEMORY;
Packit 857059
Packit 857059
	ListItemInitState(&vfab->item);
Packit 857059
	QListSetObj(&vfab->item, vfab);
Packit 857059
	vfab->vfinfo_record = *vfinfo_record;
Packit 857059
	QListInitState(&vfab->service_id_record_list);
Packit 857059
	QListInit(&vfab->service_id_record_list);
Packit 857059
	QListInsertTail(&subnet->virtual_fabric_list, &vfab->item);
Packit 857059
Packit 857059
	return FSUCCESS;
Packit 857059
}
Packit 857059
Packit 857059
FSTATUS dsap_empty_virtual_fabric_list(dsap_subnet_t *subnet)
Packit 857059
{
Packit 857059
	LIST_ITEM *item;
Packit 857059
	dsap_virtual_fabric_t *vfab;
Packit 857059
Packit 857059
	while ((item = QListRemoveHead(&subnet->virtual_fabric_list))
Packit 857059
	       != NULL) {
Packit 857059
		vfab = QListObj(item);
Packit 857059
		dsap_empty_service_id_record_list(vfab);
Packit 857059
		QListDestroy(&vfab->service_id_record_list);
Packit 857059
		free(vfab);
Packit 857059
	}
Packit 857059
Packit 857059
	return FSUCCESS;
Packit 857059
}
Packit 857059
Packit 857059
FSTATUS dsap_remove_virtual_fabric(dsap_subnet_t *subnet, uint8_t *vfName)
Packit 857059
{
Packit 857059
	dsap_virtual_fabric_t *vfab = dsap_find_virtual_fabric(vfName, subnet);
Packit 857059
Packit 857059
	if (!vfab) 
Packit 857059
		return FNOT_FOUND;
Packit 857059
Packit 857059
	QListRemoveItem(&subnet->virtual_fabric_list, &vfab->item);
Packit 857059
	dsap_empty_service_id_record_list(vfab);
Packit 857059
	QListDestroy(&vfab->service_id_record_list);
Packit 857059
	free(vfab);
Packit 857059
Packit 857059
	return FSUCCESS;
Packit 857059
}
Packit 857059
Packit 857059
/* Subnet Handling functions */
Packit 857059
Packit 857059
size_t dsap_subnet_count(void)
Packit 857059
{
Packit 857059
	return QListCount(&subnet_list);
Packit 857059
}
Packit 857059
Packit 857059
dsap_subnet_t* dsap_get_subnet_at(uint32_t index)
Packit 857059
{
Packit 857059
	LIST_ITEM *item = QListGetItemAt(&subnet_list, index);
Packit 857059
Packit 857059
	if (item) 
Packit 857059
		return (dsap_subnet_t*)QListObj(item);
Packit 857059
Packit 857059
	return NULL;
Packit 857059
}
Packit 857059
Packit 857059
FSTATUS dsap_add_subnet(uint64_t subnet_prefix)
Packit 857059
{
Packit 857059
	dsap_subnet_t *subnet = dsap_find_subnet(&subnet_prefix);
Packit 857059
Packit 857059
	if (subnet) 
Packit 857059
		return FDUPLICATE;
Packit 857059
Packit 857059
	subnet = malloc(sizeof(*subnet));
Packit 857059
	if (subnet == NULL)
Packit 857059
		return FINSUFFICIENT_MEMORY;
Packit 857059
	memset((void*)subnet,0,sizeof(*subnet));
Packit 857059
Packit 857059
	ListItemInitState(&subnet->item);
Packit 857059
	QListSetObj(&subnet->item, subnet);
Packit 857059
	subnet->subnet_prefix = subnet_prefix;
Packit 857059
	QListInitState(&subnet->src_port_list);
Packit 857059
	QListInit(&subnet->src_port_list);
Packit 857059
	QListInitState(&subnet->dst_port_list);
Packit 857059
	QListInit(&subnet->dst_port_list);
Packit 857059
	QListInitState(&subnet->virtual_fabric_list);
Packit 857059
	QListInit(&subnet->virtual_fabric_list);
Packit 857059
	QListInsertTail(&subnet_list, &subnet->item);
Packit 857059
Packit 857059
	return FSUCCESS;
Packit 857059
}
Packit 857059
Packit 857059
FSTATUS dsap_empty_subnet_list(void)
Packit 857059
{
Packit 857059
	LIST_ITEM *item;
Packit 857059
	dsap_subnet_t *subnet;
Packit 857059
Packit 857059
	acm_log(2, "Emptying subnet list.\n");
Packit 857059
Packit 857059
	while ((item = QListRemoveHead(&subnet_list)) != NULL) {
Packit 857059
		subnet = QListObj(item);
Packit 857059
		dsap_empty_src_port_list(subnet);
Packit 857059
		dsap_empty_dst_port_list(subnet);
Packit 857059
		dsap_empty_virtual_fabric_list(subnet);
Packit 857059
		QListDestroy(&subnet->src_port_list);
Packit 857059
		QListDestroy(&subnet->dst_port_list);
Packit 857059
		QListDestroy(&subnet->virtual_fabric_list);
Packit 857059
		free(subnet);
Packit 857059
	}
Packit 857059
Packit 857059
	return FSUCCESS;
Packit 857059
}
Packit 857059
Packit 857059
void dsap_topology_cleanup(void)
Packit 857059
{
Packit 857059
	dsap_empty_subnet_list();
Packit 857059
}
Packit 857059
Packit 857059
FSTATUS dsap_topology_init(void)
Packit 857059
{
Packit 857059
	QListInitState(&subnet_list);
Packit 857059
	QListInit(&subnet_list);
Packit 857059
Packit 857059
	return FSUCCESS;
Packit 857059
}