Blame Dsap/src/dsap_scan_fabric.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 <pthread.h>
Packit 857059
#include <signal.h>
Packit 857059
#include <unistd.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 "iba/public/ilist.h"
Packit 857059
#include "iba/public/ievent.h"
Packit 857059
#include "iba/public/ispinlock.h"
Packit 857059
#include "iba/public/itimer.h"
Packit 857059
#include "opasadb_path_private.h"
Packit 857059
#include "opasadb_debug.h"
Packit 857059
#include "dsap_topology.h"
Packit 857059
#include "dsap_notifications.h"
Packit 857059
#include "dsap.h"
Packit 857059
Packit 857059
static int dsap_scanner_end = 0;
Packit 857059
Packit 857059
uint32 dsap_scan_frequency = 600;	/* in secconds */
Packit 857059
uint32 dsap_unsub_scan_frequency = 10;	/* in secconds */
Packit 857059
boolean dsap_publish = 1;
Packit 857059
uint32 dsap_default_fabric = DSAP_DEF_FAB_ACT_NORMAL;
Packit 857059
Packit 857059
static pthread_t dsap_scanner_thread;
Packit 857059
static int dsap_scanner_rescan = 0;
Packit 857059
static SPIN_LOCK dsap_scanner_lock;
Packit 857059
static EVENT dsap_scanner_event;	/* wakes up scanner thread to do
Packit 857059
					another scan */
Packit 857059
Packit 857059
#define SCAN_RING_SIZE 512 	/* Must be power of 2 */
Packit 857059
static struct dsap_scan_port {
Packit 857059
	uint64                  src_guid;
Packit 857059
	uint64                  src_subnet;
Packit 857059
	uint64                  dest_guid;
Packit 857059
	port_event_type_t       event_type;
Packit 857059
} dsap_scan_port_ring[SCAN_RING_SIZE];
Packit 857059
static int scan_ring_put = 0;
Packit 857059
static int scan_ring_take = 0;
Packit 857059
Packit 857059
static op_ppath_writer_t shared_memory_writer;
Packit 857059
Packit 857059
struct sigaction new_action, old_action;
Packit 857059
Packit 857059
static char *port_event[] = {
Packit 857059
	"Source Port Up",
Packit 857059
	"Source Port Down",
Packit 857059
	"Destination Port Up",
Packit 857059
	"Destination Port Down",
Packit 857059
	"Port Scan Request",
Packit 857059
	"Complete Fabric Scan Request"
Packit 857059
};
Packit 857059
Packit 857059
int dsap_default_fabric_parser(char *str, void *ptr)
Packit 857059
{
Packit 857059
	int err = 0;
Packit 857059
Packit 857059
	if (!str || !ptr) {
Packit 857059
		acm_log(0, "Bad arguments to default fabric parser.\n");
Packit 857059
		err = EINVAL;
Packit 857059
		goto exit;
Packit 857059
	}
Packit 857059
Packit 857059
	if (strcmp(str, "none") == 0) {
Packit 857059
		dsap_default_fabric = DSAP_DEF_FAB_ACT_NONE;
Packit 857059
		goto exit;
Packit 857059
	}
Packit 857059
Packit 857059
	if (strcmp(str, "normal") == 0) {
Packit 857059
		dsap_default_fabric = DSAP_DEF_FAB_ACT_NORMAL;
Packit 857059
		goto exit;
Packit 857059
	}
Packit 857059
Packit 857059
	if (strcmp(str, "all") == 0) {
Packit 857059
		dsap_default_fabric = DSAP_DEF_FAB_ACT_ALL;
Packit 857059
		goto exit;
Packit 857059
	}
Packit 857059
Packit 857059
	acm_log(0, "Invalid value (%s) specified for dsap_default_fabric.\n",
Packit 857059
		str);
Packit 857059
	err = EINVAL;
Packit 857059
Packit 857059
exit:
Packit 857059
	return err;
Packit 857059
}
Packit 857059
Packit 857059
char * dsap_default_fabric_printer(void *ptr)
Packit 857059
{
Packit 857059
	switch (dsap_default_fabric) {
Packit 857059
	case DSAP_DEF_FAB_ACT_NONE:
Packit 857059
		return "none";
Packit 857059
Packit 857059
	case DSAP_DEF_FAB_ACT_NORMAL:
Packit 857059
		return "normal";
Packit 857059
Packit 857059
	case DSAP_DEF_FAB_ACT_ALL:
Packit 857059
		return "all";
Packit 857059
Packit 857059
	default:
Packit 857059
		return "UNKNOWN";
Packit 857059
	}
Packit 857059
}
Packit 857059
Packit 857059
/*-----------------------------------------------------------
Packit 857059
 * Wait for an event - this event is NOT interruptible
Packit 857059
 *----------------------------------------------------------- 
Packit 857059
*/ 
Packit 857059
static FSTATUS 
Packit 857059
EventWaitOnSeconds( EVENT *pEvent, int32 wait_seconds)
Packit 857059
{
Packit 857059
	FSTATUS status = FERROR;
Packit 857059
	int retval;
Packit 857059
Packit 857059
	/* Make sure that the event was started  */
Packit 857059
	ASSERT (pEvent->ev_state == Started);
Packit 857059
Packit 857059
	/*
Packit 857059
	 Don't wait if the it has been signaled already!
Packit 857059
	*/
Packit 857059
	pthread_mutex_lock( &pEvent->ev_mutex );
Packit 857059
	if (pEvent->ev_signaled == TRUE) {
Packit 857059
		/* autoclear */
Packit 857059
		pEvent->ev_signaled = FALSE;
Packit 857059
Packit 857059
		pthread_mutex_unlock(&pEvent->ev_mutex);
Packit 857059
		return FSUCCESS;
Packit 857059
	}
Packit 857059
Packit 857059
	if (wait_seconds == EVENT_NO_TIMEOUT) {
Packit 857059
		wait_seconds = 0;
Packit 857059
		/* Wait for condition variable ev_condvar to be signaled or
Packit 857059
		   broadcast. */
Packit 857059
		pthread_cond_wait(&pEvent->ev_condvar,&pEvent->ev_mutex);
Packit 857059
	
Packit 857059
		pEvent->ev_signaled = FALSE;
Packit 857059
		pthread_mutex_unlock(&pEvent->ev_mutex);
Packit 857059
		return FSUCCESS;
Packit 857059
	} else {
Packit 857059
		/* Get the current time */
Packit 857059
		if (gettimeofday(&pEvent->ev_curtime, NULL) == 0) {
Packit 857059
			pEvent->ev_timeout.tv_sec = pEvent->ev_curtime.tv_sec +
Packit 857059
				wait_seconds;
Packit 857059
			pEvent->ev_timeout.tv_nsec = pEvent->ev_curtime.tv_usec;
Packit 857059
		
Packit 857059
			retval = pthread_cond_timedwait(&pEvent->ev_condvar,
Packit 857059
							&pEvent->ev_mutex,
Packit 857059
							&pEvent->ev_timeout);
Packit 857059
			if (retval == ETIMEDOUT) {
Packit 857059
				status = FTIMEOUT;
Packit 857059
			} else {
Packit 857059
				/* We got signalled */
Packit 857059
				status = FSUCCESS;
Packit 857059
			}
Packit 857059
		}
Packit 857059
		pEvent->ev_signaled = FALSE;
Packit 857059
		pthread_mutex_unlock(&pEvent->ev_mutex);
Packit 857059
		return status;
Packit 857059
	}
Packit 857059
}
Packit 857059
Packit 857059
/*
Packit 857059
 * Returns the number of published paths.
Packit 857059
 */
Packit 857059
uintn dsap_publish_paths(void)
Packit 857059
{
Packit 857059
	int err;
Packit 857059
	uintn i;
Packit 857059
	uintn count=0;
Packit 857059
	uintn subnet_count=0;
Packit 857059
	uint32 port_count;
Packit 857059
	dsap_subnet_t *subnet;
Packit 857059
	LIST_ITEM *vf_item;
Packit 857059
	dsap_virtual_fabric_t *vfab;
Packit 857059
	LIST_ITEM *sid_item;
Packit 857059
	dsap_service_id_record_t *record;
Packit 857059
	LIST_ITEM *sport_item;
Packit 857059
	int j;
Packit 857059
	dsap_src_port_t *sport;
Packit 857059
	LIST_ITEM *path_item;
Packit 857059
	LIST_ITEM *pkey_item;
Packit 857059
	op_ppath_port_record_t op_port;
Packit 857059
	dsap_pkey_t *pkey;
Packit 857059
	dsap_path_record_t *path;
Packit 857059
Packit 857059
	acm_log(2, "\n");
Packit 857059
Packit 857059
	subnet_count = dsap_subnet_count();
Packit 857059
	if (subnet_count == 0) {
Packit 857059
		acm_log(0, "No subnets to publish.\n");
Packit 857059
		goto exit;
Packit 857059
	}
Packit 857059
Packit 857059
	/*
Packit 857059
	 * We reserve one extra slot for SID 0 (i.e., no SID)
Packit 857059
	 */
Packit 857059
	err = op_ppath_initialize_subnets(&shared_memory_writer, subnet_count,
Packit 857059
					  dsap_tot_sid_rec_count() + 1);
Packit 857059
	if (err) {
Packit 857059
		acm_log(0, "Failed to create the subnet table: %s.\n",
Packit 857059
			strerror(err));
Packit 857059
		goto exit;
Packit 857059
	}
Packit 857059
		
Packit 857059
	port_count = dsap_tot_src_port_count();
Packit 857059
	err = op_ppath_initialize_ports(&shared_memory_writer, port_count);
Packit 857059
	if (err) {
Packit 857059
		acm_log(0, "Failed to create the port table: %s.\n",
Packit 857059
			strerror(err));
Packit 857059
		goto exit;
Packit 857059
	}
Packit 857059
		
Packit 857059
	err = op_ppath_initialize_vfabrics(&shared_memory_writer, 
Packit 857059
					   dsap_tot_vfab_count() + 1);
Packit 857059
	if (err) {
Packit 857059
		acm_log(0, "Failed to create the virtual fabric table: %s.\n",
Packit 857059
			strerror(err));
Packit 857059
		goto exit;
Packit 857059
	}
Packit 857059
		
Packit 857059
	err = op_ppath_initialize_paths(&shared_memory_writer,
Packit 857059
					dsap_tot_path_rec_count());
Packit 857059
	if (err) {
Packit 857059
		acm_log(0, "Failed to create the path table: %s.\n",
Packit 857059
			strerror(err));
Packit 857059
		goto exit;
Packit 857059
	}
Packit 857059
Packit 857059
	for (i=0; i< subnet_count; i++) {
Packit 857059
		subnet = dsap_get_subnet_at(i);
Packit 857059
		if (!subnet) 
Packit 857059
			continue;
Packit 857059
		vf_item = QListHead(&subnet->virtual_fabric_list);
Packit 857059
Packit 857059
		err = op_ppath_add_subnet(&shared_memory_writer,
Packit 857059
					  subnet->subnet_prefix);
Packit 857059
		if (err) {
Packit 857059
			acm_log(0, "Failed to add subnet: %s\n",
Packit 857059
				strerror(err));
Packit 857059
			goto exit;
Packit 857059
		}
Packit 857059
Packit 857059
		while (vf_item) {
Packit 857059
			vfab = QListObj(vf_item);
Packit 857059
			sid_item = QListHead(&vfab->service_id_record_list);
Packit 857059
Packit 857059
			err = op_ppath_add_vfab(
Packit 857059
				&shared_memory_writer,
Packit 857059
				(char *) vfab->vfinfo_record.vfName,
Packit 857059
				subnet->subnet_prefix,
Packit 857059
				vfab->vfinfo_record.pKey,
Packit 857059
				vfab->vfinfo_record.s1.slBase);
Packit 857059
			if (err) {
Packit 857059
				acm_log(0, "Failed to add vfab: %s\n",
Packit 857059
					strerror(err));
Packit 857059
				goto exit;
Packit 857059
			}
Packit 857059
Packit 857059
			while (sid_item) {
Packit 857059
				record = QListObj(sid_item);
Packit 857059
Packit 857059
				err = op_ppath_add_sid(
Packit 857059
				    &shared_memory_writer,
Packit 857059
				    subnet->subnet_prefix,
Packit 857059
				    record->service_id_range.lower_service_id,
Packit 857059
				    record->service_id_range.upper_service_id,
Packit 857059
				    (char *) vfab->vfinfo_record.vfName);
Packit 857059
				if (err) {
Packit 857059
					acm_log(0, "Failed to add SID range: "
Packit 857059
						   "%s\n",
Packit 857059
						strerror(err));
Packit 857059
					goto exit;
Packit 857059
				}
Packit 857059
				sid_item = QListNext(
Packit 857059
				   &vfab->service_id_record_list, sid_item);
Packit 857059
			}
Packit 857059
Packit 857059
			vf_item = QListNext(&subnet->virtual_fabric_list,
Packit 857059
					    vf_item);
Packit 857059
		}
Packit 857059
Packit 857059
		sport_item = QListHead(&subnet->src_port_list);
Packit 857059
		while (sport_item) {
Packit 857059
			sport = QListObj(sport_item);
Packit 857059
			path_item = QListHead(&sport->path_record_list);
Packit 857059
			pkey_item = QListHead(&sport->pkey_list);
Packit 857059
Packit 857059
			if (sport->state != IBV_PORT_ACTIVE) {
Packit 857059
				acm_log(2, "Skip inact port (0x%016"PRIx64")\n",
Packit 857059
					ntoh64(sport->gid.global.interface_id));
Packit 857059
				sport_item = QListNext(&subnet->src_port_list,
Packit 857059
						       sport_item);
Packit 857059
				continue;
Packit 857059
			}
Packit 857059
Packit 857059
			memset(&op_port, 0, sizeof(op_port));
Packit 857059
Packit 857059
			op_port.source_prefix = 
Packit 857059
				sport->gid.global.subnet_prefix;
Packit 857059
			op_port.source_guid = sport->gid.global.interface_id;
Packit 857059
			op_port.base_lid = sport->base_lid;
Packit 857059
			op_port.lmc = sport->lmc;
Packit 857059
			op_port.port = sport->port_num;
Packit 857059
			strcpy(op_port.hfi_name, sport->hfi_name);
Packit 857059
Packit 857059
			j=0; 
Packit 857059
			while (pkey_item && j < PKEY_TABLE_LENGTH) {
Packit 857059
				pkey = QListObj(pkey_item);
Packit 857059
				op_port.pkey[j] = pkey->pkey;
Packit 857059
				j++;
Packit 857059
				
Packit 857059
				pkey_item = QListNext(&sport->pkey_list,
Packit 857059
						      pkey_item);
Packit 857059
			}
Packit 857059
Packit 857059
			err = op_ppath_add_port(&shared_memory_writer,
Packit 857059
						op_port);
Packit 857059
			if (err) {
Packit 857059
				acm_log(0, "Failed to add port: %s\n",
Packit 857059
					strerror(err));
Packit 857059
				goto exit;
Packit 857059
			}
Packit 857059
Packit 857059
			while (path_item) {
Packit 857059
				path = QListObj(path_item);
Packit 857059
Packit 857059
				err = op_ppath_add_path(&shared_memory_writer,
Packit 857059
							&path->path);
Packit 857059
				if (err) {
Packit 857059
					acm_log(0, "Failed to add path: %s\n",
Packit 857059
						strerror(err));
Packit 857059
					break;
Packit 857059
				}		
Packit 857059
				path_item = QListNext(&sport->path_record_list,
Packit 857059
						      path_item);
Packit 857059
				count++;
Packit 857059
			}
Packit 857059
			sport_item = QListNext(&subnet->src_port_list, 
Packit 857059
					       sport_item);
Packit 857059
		}
Packit 857059
	}
Packit 857059
Packit 857059
exit:
Packit 857059
	op_ppath_publish(&shared_memory_writer);
Packit 857059
Packit 857059
	_DBG_FUNC_EXIT;
Packit 857059
	return count;
Packit 857059
}
Packit 857059
Packit 857059
static void dsap_full_rescan(void)
Packit 857059
{
Packit 857059
	acm_log(2, "\n");
Packit 857059
	dsap_scanner_rescan = 1;
Packit 857059
	EventTrigger(&dsap_scanner_event);
Packit 857059
}
Packit 857059
Packit 857059
Packit 857059
static void dsap_rescan(union ibv_gid *src_gid)
Packit 857059
{
Packit 857059
	acm_log(2, "\n");
Packit 857059
	dsap_port_event(src_gid->global.interface_id,
Packit 857059
			src_gid->global.subnet_prefix,
Packit 857059
			src_gid->global.interface_id, DSAP_PT_EVT_PORT_RESCAN);
Packit 857059
}
Packit 857059
Packit 857059
static FSTATUS dsap_add_vfinfo_records(dsap_subnet_t *subnet)
Packit 857059
{
Packit 857059
	FSTATUS rval = FSUCCESS;
Packit 857059
	LIST_ITEM *sid_range_item;
Packit 857059
	dsap_service_id_record_t *record;
Packit 857059
Packit 857059
	acm_log(2, "\n");
Packit 857059
Packit 857059
	for_each(&sid_range_args, sid_range_item) {
Packit 857059
		record = QListObj(sid_range_item);
Packit 857059
		
Packit 857059
		rval = dsap_query_vfinfo_records(subnet, 
Packit 857059
						 &record->service_id_range);
Packit 857059
		if (rval == FBUSY) 
Packit 857059
			break;
Packit 857059
		if (rval == FDUPLICATE) 
Packit 857059
			rval = FSUCCESS;
Packit 857059
		if (rval != FSUCCESS) {
Packit 857059
			acm_log(0, "Vfinfo query failed with status %d\n",
Packit 857059
				rval);
Packit 857059
			rval = FSUCCESS;
Packit 857059
		}
Packit 857059
	}
Packit 857059
Packit 857059
	return rval;
Packit 857059
}
Packit 857059
Packit 857059
static boolean dsap_pkey_match_found(dsap_src_port_t *src_port,
Packit 857059
				     uint16_t vfab_pKey)
Packit 857059
{
Packit 857059
	LIST_ITEM *pkey_item;
Packit 857059
	dsap_pkey_t *pkey;
Packit 857059
Packit 857059
	acm_log(2, "\n");
Packit 857059
	
Packit 857059
	for_each (&src_port->pkey_list, pkey_item) {
Packit 857059
		pkey = QListObj(pkey_item);
Packit 857059
		/* Mask off the high bit (fields are in network byte order) */
Packit 857059
		if ((pkey->pkey & 0xff7f) == (vfab_pKey & 0xff7f))
Packit 857059
			return TRUE;
Packit 857059
	}
Packit 857059
Packit 857059
	return FALSE;
Packit 857059
}
Packit 857059
Packit 857059
static FSTATUS dsap_for_each_service_id_record(dsap_src_port_t *src_port,
Packit 857059
					       dsap_dst_port_t *dst_port,
Packit 857059
					       dsap_virtual_fabric_t *vfab)
Packit 857059
{
Packit 857059
	FSTATUS rval = FSUCCESS;
Packit 857059
	LIST_ITEM *sid_rec_item;
Packit 857059
	dsap_service_id_record_t *sid_rec;
Packit 857059
Packit 857059
	acm_log(2, "\n");
Packit 857059
	
Packit 857059
	for_each (&vfab->service_id_record_list, sid_rec_item) {
Packit 857059
		sid_rec = QListObj(sid_rec_item);
Packit 857059
Packit 857059
		if (dsap_scanner_end)
Packit 857059
			break;
Packit 857059
		rval = dsap_query_path_records(
Packit 857059
		   src_port, dst_port, 
Packit 857059
		   sid_rec->service_id_range.lower_service_id,
Packit 857059
		   vfab->vfinfo_record.pKey);
Packit 857059
		/* We only need to find one set of path records */
Packit 857059
		/* So only scan until a successful set is returned */
Packit 857059
		/* or we have exhausted all possible avenues */
Packit 857059
		if (rval == FSUCCESS) 
Packit 857059
			break;
Packit 857059
Packit 857059
		/* If the SM is busy retry the scan at a later time */
Packit 857059
		/* in order to alleviate congestion.*/
Packit 857059
		if (rval == FBUSY) 
Packit 857059
			break;
Packit 857059
	}
Packit 857059
Packit 857059
	return rval;
Packit 857059
}
Packit 857059
Packit 857059
static FSTATUS dsap_for_each_virtual_fabric(dsap_subnet_t *subnet,
Packit 857059
					    dsap_src_port_t *src_port,
Packit 857059
					    dsap_dst_port_t *dst_port)
Packit 857059
{
Packit 857059
	FSTATUS rval = FSUCCESS;
Packit 857059
	LIST_ITEM *vfab_item;
Packit 857059
	dsap_virtual_fabric_t *vfab;
Packit 857059
Packit 857059
	acm_log(2, "\n");
Packit 857059
	
Packit 857059
	for_each (&subnet->virtual_fabric_list, vfab_item) {
Packit 857059
		vfab = QListObj(vfab_item);
Packit 857059
Packit 857059
		if (dsap_scanner_end) 
Packit 857059
			break;
Packit 857059
Packit 857059
		if (dsap_pkey_match_found(src_port, 
Packit 857059
					  vfab->vfinfo_record.pKey)) {
Packit 857059
			rval = dsap_for_each_service_id_record(
Packit 857059
			   src_port, dst_port, vfab);
Packit 857059
			if (rval != FSUCCESS)
Packit 857059
				break;
Packit 857059
		}
Packit 857059
	}
Packit 857059
Packit 857059
	return rval;
Packit 857059
}
Packit 857059
Packit 857059
static FSTATUS dsap_for_each_dst_port(dsap_subnet_t *subnet, 
Packit 857059
				      dsap_src_port_t *src_port)
Packit 857059
{
Packit 857059
	FSTATUS rval = FSUCCESS;
Packit 857059
	LIST_ITEM *dst_port_item;
Packit 857059
	dsap_dst_port_t *dst_port;
Packit 857059
Packit 857059
	acm_log(2, "\n");
Packit 857059
	
Packit 857059
	for_each (&subnet->dst_port_list, dst_port_item) {
Packit 857059
		dst_port = QListObj(dst_port_item);
Packit 857059
Packit 857059
		if (dsap_scanner_end) {
Packit 857059
			break;
Packit 857059
		}
Packit 857059
Packit 857059
		if (dst_port->node_type != STL_NODE_FI) {
Packit 857059
#ifdef PRINT_PORTS_FOUND
Packit 857059
			acm_log(2,  "Found Switch Port 0x%016"PRIx64":0x%016"
Packit 857059
				    PRIx64".\n",
Packit 857059
				ntoh64(dst_port->gid.global.subnet_prefix),
Packit 857059
				ntoh64(dst_port->gid.global.interface_id));
Packit 857059
#endif
Packit 857059
			continue;
Packit 857059
		}
Packit 857059
Packit 857059
#ifdef PRINT_PORTS_FOUND
Packit 857059
		acm_log(2, "Found 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
#endif
Packit 857059
		rval = dsap_for_each_virtual_fabric(subnet, src_port,
Packit 857059
						    dst_port);
Packit 857059
		if (rval != FSUCCESS)
Packit 857059
			break;
Packit 857059
	}
Packit 857059
Packit 857059
	return rval;
Packit 857059
}
Packit 857059
Packit 857059
static FSTATUS dsap_add_path_records(dsap_subnet_t *subnet)
Packit 857059
{
Packit 857059
	FSTATUS rval = FSUCCESS;
Packit 857059
	LIST_ITEM *src_port_item;
Packit 857059
	dsap_src_port_t *src_port;
Packit 857059
Packit 857059
	acm_log(2, "\n");
Packit 857059
	
Packit 857059
	for_each (&subnet->src_port_list, src_port_item) {
Packit 857059
		src_port = QListObj(src_port_item);
Packit 857059
Packit 857059
		if (dsap_scanner_end) {
Packit 857059
			break;
Packit 857059
		}
Packit 857059
Packit 857059
		rval = dsap_for_each_dst_port(subnet, src_port);
Packit 857059
		if (rval != FSUCCESS) 
Packit 857059
			break;
Packit 857059
		
Packit 857059
		acm_log(2, "Found %u path records on port 0x%016"PRIx64".\n",
Packit 857059
			(unsigned int)dsap_path_record_count(src_port),
Packit 857059
			ntoh64(src_port->gid.global.interface_id));
Packit 857059
	}
Packit 857059
Packit 857059
	return rval;
Packit 857059
}
Packit 857059
Packit 857059
FSTATUS dsap_scan_subnets(void)
Packit 857059
{
Packit 857059
	FSTATUS  rval = FERROR;
Packit 857059
	uint32_t subnet_index;
Packit 857059
	int      retry_needed = 0;
Packit 857059
	int      error_occurred = 0;
Packit 857059
	uint64_t prefix;
Packit 857059
Packit 857059
	acm_log(2, "\n");
Packit 857059
	for (subnet_index = 0; subnet_index < dsap_subnet_count();
Packit 857059
	     subnet_index++) {
Packit 857059
		dsap_subnet_t *subnet = dsap_get_subnet_at(subnet_index);
Packit 857059
		if (!subnet) 
Packit 857059
			continue;
Packit 857059
Packit 857059
		if (dsap_scanner_end)
Packit 857059
			break;
Packit 857059
Packit 857059
		if (!subnet->current) {
Packit 857059
			if (FBUSY == (rval = dsap_query_dst_ports(subnet))) {
Packit 857059
				retry_needed = 1; 
Packit 857059
				continue;
Packit 857059
			} else if (rval != FSUCCESS) {
Packit 857059
				error_occurred = 1;
Packit 857059
				continue;
Packit 857059
			} else {
Packit 857059
				prefix = subnet->subnet_prefix;
Packit 857059
				acm_log(0, "Found %u dest ports for subnet "
Packit 857059
					   "0x%016"PRIx64"\n",
Packit 857059
					(unsigned int)dsap_dst_port_count(subnet),
Packit 857059
					ntoh64(prefix));
Packit 857059
			}
Packit 857059
Packit 857059
			rval = dsap_add_vfinfo_records(subnet);
Packit 857059
			if (rval == FBUSY) {
Packit 857059
				retry_needed = 1; 
Packit 857059
				continue;
Packit 857059
			} else if (rval != FSUCCESS) {
Packit 857059
				error_occurred = 1;
Packit 857059
				continue;
Packit 857059
			} else {
Packit 857059
				prefix = subnet->subnet_prefix;
Packit 857059
				acm_log(0, "Found %u vfabs for subnet 0x%016"
Packit 857059
					   PRIx64"\n",
Packit 857059
					(unsigned int)dsap_virtual_fabric_count(subnet),
Packit 857059
					ntoh64(prefix));
Packit 857059
			}
Packit 857059
Packit 857059
			rval = dsap_add_path_records(subnet);
Packit 857059
			if (rval == FBUSY) {
Packit 857059
				retry_needed = 1; 
Packit 857059
				continue;
Packit 857059
			} else if (rval != FSUCCESS) {
Packit 857059
				error_occurred = 1;
Packit 857059
				continue;
Packit 857059
			} else {
Packit 857059
				prefix = subnet->subnet_prefix;
Packit 857059
				acm_log(0, "Found %u paths for subnet 0x%016"
Packit 857059
					   PRIx64"\n",
Packit 857059
					(unsigned int)dsap_subnet_path_record_count(subnet),
Packit 857059
					ntoh64(prefix));
Packit 857059
			}
Packit 857059
			subnet->current = 1;
Packit 857059
		}
Packit 857059
	}
Packit 857059
Packit 857059
	if (error_occurred) 
Packit 857059
		rval = FERROR;
Packit 857059
	else if (retry_needed)
Packit 857059
		rval = FBUSY;
Packit 857059
	else 
Packit 857059
		rval = FSUCCESS;
Packit 857059
Packit 857059
	return rval;
Packit 857059
}
Packit 857059
Packit 857059
static boolean dsap_dst_port_up(union ibv_gid *dst_gid, union ibv_gid *src_gid)
Packit 857059
{
Packit 857059
	FSTATUS rval;
Packit 857059
	NODE_TYPE node_type;
Packit 857059
	char node_desc[NODE_DESCRIPTION_ARRAY_SIZE];
Packit 857059
	dsap_subnet_t *subnet;
Packit 857059
	dsap_src_port_t *src_port;
Packit 857059
	dsap_dst_port_t *dst_port;
Packit 857059
Packit 857059
	acm_log(2, "\n");
Packit 857059
	
Packit 857059
	rval = dsap_query_dst_port(dst_gid, &node_type, node_desc);
Packit 857059
	if ((rval != FSUCCESS) || (node_type != STL_NODE_FI)) {
Packit 857059
		dsap_full_rescan();
Packit 857059
		return FALSE;
Packit 857059
	}
Packit 857059
Packit 857059
	rval = dsap_add_dst_port(dst_gid, node_type, node_desc);
Packit 857059
	if ((rval == FSUCCESS) || (rval == FDUPLICATE)) {
Packit 857059
		subnet = dsap_find_subnet((uint64_t *)&dst_gid->global.subnet_prefix);
Packit 857059
		src_port = dsap_find_src_port(src_gid);
Packit 857059
		dst_port = dsap_find_dst_port(dst_gid);
Packit 857059
Packit 857059
		dsap_remove_path_records(src_port, dst_gid);
Packit 857059
Packit 857059
		rval = dsap_for_each_virtual_fabric(subnet, src_port,
Packit 857059
						    dst_port);
Packit 857059
		if (rval != FSUCCESS) {
Packit 857059
			dsap_rescan(src_gid);
Packit 857059
			return FALSE;
Packit 857059
		}
Packit 857059
Packit 857059
		return TRUE;
Packit 857059
	}
Packit 857059
Packit 857059
	acm_log(0, "Failure Adding Dest Port 0x%016"PRIx64":0x%016"PRIx64"\n",
Packit 857059
		ntoh64(dst_gid->global.subnet_prefix),
Packit 857059
		ntoh64(dst_gid->global.interface_id));
Packit 857059
Packit 857059
	return FALSE;
Packit 857059
}
Packit 857059
Packit 857059
static boolean dsap_dst_port_down(union ibv_gid *dst_gid)
Packit 857059
{
Packit 857059
	dsap_dst_port_t *dst_port = dsap_find_dst_port(dst_gid);
Packit 857059
Packit 857059
	acm_log(2, "\n");
Packit 857059
Packit 857059
	if (dst_port != NULL) {
Packit 857059
		if (dst_port->node_type != STL_NODE_FI) {
Packit 857059
			dsap_full_rescan();
Packit 857059
			return TRUE;
Packit 857059
		}
Packit 857059
Packit 857059
		if (dsap_remove_dst_port(dst_gid) == FSUCCESS)
Packit 857059
			return TRUE;
Packit 857059
	}
Packit 857059
Packit 857059
	acm_log(1, "Unable To Remove Dst Port 0x%016"PRIx64":0x%016"PRIx64"\n",
Packit 857059
		ntoh64(dst_gid->global.subnet_prefix),
Packit 857059
		ntoh64(dst_gid->global.interface_id));
Packit 857059
Packit 857059
	return FALSE;
Packit 857059
}
Packit 857059
Packit 857059
static boolean dsap_src_port_down(union ibv_gid *src_gid)
Packit 857059
{
Packit 857059
	acm_log(2, "\n");
Packit 857059
Packit 857059
	if (dsap_remove_src_port(src_gid) == FSUCCESS)
Packit 857059
		return TRUE;
Packit 857059
Packit 857059
	acm_log(0, "Unable To Find Src Port 0x%016"PRIx64":0x%016"PRIx64"\n",
Packit 857059
		ntoh64(src_gid->global.subnet_prefix),
Packit 857059
		ntoh64(src_gid->global.interface_id));
Packit 857059
Packit 857059
	return FALSE;
Packit 857059
}
Packit 857059
Packit 857059
static boolean dsap_src_port_up(union ibv_gid *src_gid, char *src_desc)
Packit 857059
{
Packit 857059
	FSTATUS rval;
Packit 857059
	dsap_src_port_t *src_port = dsap_find_src_port(src_gid);
Packit 857059
	struct dsap_port *port;
Packit 857059
Packit 857059
	acm_log(2, "\n");
Packit 857059
Packit 857059
	if (!src_port) 
Packit 857059
		return FALSE;
Packit 857059
	rval = dsap_add_dst_port(src_gid, STL_NODE_FI,
Packit 857059
				 src_desc);
Packit 857059
	if ((rval == FSUCCESS) || (rval == FDUPLICATE)) {
Packit 857059
		port = dsap_lock_prov_port(src_port);
Packit 857059
		if (port != NULL) {
Packit 857059
			rval = dsap_update_src_port(src_port, port);
Packit 857059
			dsap_release_prov_port(port);
Packit 857059
			if (rval == FSUCCESS)
Packit 857059
				return TRUE;
Packit 857059
		}
Packit 857059
	}
Packit 857059
Packit 857059
	acm_log(0, "Unable To Locate Src Port 0x%016"PRIx64":0x%016"PRIx64"\n",
Packit 857059
		ntoh64(src_gid->global.subnet_prefix),
Packit 857059
		ntoh64(src_gid->global.interface_id));
Packit 857059
Packit 857059
	dsap_full_rescan();
Packit 857059
Packit 857059
	return FALSE;
Packit 857059
}
Packit 857059
Packit 857059
static boolean dsap_src_port_rescan(union ibv_gid *src_gid)
Packit 857059
{
Packit 857059
	dsap_subnet_t *subnet = dsap_find_subnet(
Packit 857059
				(uint64_t *)&src_gid->global.subnet_prefix);
Packit 857059
	dsap_src_port_t *src_port = dsap_find_src_port(src_gid);
Packit 857059
	FSTATUS rval;
Packit 857059
Packit 857059
	acm_log(2, "\n");
Packit 857059
Packit 857059
	if (!subnet || !src_port) 
Packit 857059
		return FALSE;
Packit 857059
Packit 857059
	if (dsap_src_port_up(src_gid, src_port->hfi_name) == FALSE)
Packit 857059
		return FALSE;
Packit 857059
Packit 857059
	rval = dsap_for_each_dst_port(subnet, src_port);
Packit 857059
	if (rval != FSUCCESS) {
Packit 857059
		dsap_rescan(src_gid);
Packit 857059
		return FALSE;
Packit 857059
	}
Packit 857059
Packit 857059
	return TRUE;
Packit 857059
}
Packit 857059
Packit 857059
static boolean dsap_process_port_events(void)
Packit 857059
{
Packit 857059
	boolean publish = FALSE;
Packit 857059
	uint64 src_guid, src_subnet, dest_guid;
Packit 857059
	port_event_type_t event_type;
Packit 857059
	union ibv_gid src_gid;
Packit 857059
	union ibv_gid dst_gid;
Packit 857059
	dsap_src_port_t *src_port;
Packit 857059
Packit 857059
	acm_log(2, "\n");
Packit 857059
Packit 857059
	SpinLockAcquire(&dsap_scanner_lock);
Packit 857059
Packit 857059
	while(scan_ring_put != scan_ring_take) {
Packit 857059
		scan_ring_take++;
Packit 857059
		scan_ring_take &= (SCAN_RING_SIZE - 1);
Packit 857059
		src_guid = dsap_scan_port_ring[scan_ring_take].src_guid;
Packit 857059
		src_subnet = dsap_scan_port_ring[scan_ring_take].src_subnet;
Packit 857059
		dest_guid = dsap_scan_port_ring[scan_ring_take].dest_guid;
Packit 857059
		event_type = dsap_scan_port_ring[scan_ring_take].event_type;
Packit 857059
		SpinLockRelease(&dsap_scanner_lock);
Packit 857059
Packit 857059
		src_gid.global.subnet_prefix = src_subnet;
Packit 857059
		src_gid.global.interface_id = src_guid;
Packit 857059
Packit 857059
		dst_gid.global.subnet_prefix = src_subnet;
Packit 857059
		dst_gid.global.interface_id = dest_guid;
Packit 857059
Packit 857059
		switch (event_type) {
Packit 857059
		case DSAP_PT_EVT_DST_PORT_UP:
Packit 857059
			acm_log(1, "PROCESSING GID(0x%016"PRIx64") IN SERVICE"
Packit 857059
				   "ON PORT 0x%016"PRIx64".\n",
Packit 857059
				ntoh64(dest_guid), ntoh64(src_guid));
Packit 857059
Packit 857059
			src_port = dsap_find_src_port(&src_gid);
Packit 857059
			if (src_port == NULL) {
Packit 857059
				acm_log(0, "Unable to find src port.\n");
Packit 857059
				dsap_full_rescan();
Packit 857059
				break;
Packit 857059
			}
Packit 857059
Packit 857059
			if (dsap_dst_port_up(&dst_gid, &src_gid) == TRUE)
Packit 857059
				publish = TRUE;
Packit 857059
			break;
Packit 857059
Packit 857059
		case DSAP_PT_EVT_DST_PORT_DOWN:
Packit 857059
			acm_log(1, "PROCESSING GID(0x%016"PRIx64") OUT OF"
Packit 857059
				   "SERVICE ON PORT 0x%016"PRIx64".\n",
Packit 857059
				ntoh64(dest_guid),
Packit 857059
				ntoh64(src_guid));
Packit 857059
			if (dsap_dst_port_down(&dst_gid) == TRUE)
Packit 857059
				publish = TRUE;
Packit 857059
			break;
Packit 857059
Packit 857059
		case DSAP_PT_EVT_SRC_PORT_UP:
Packit 857059
			acm_log(1, "PROCESSING LOCAL PORT(0x%016"PRIx64") "
Packit 857059
				   "ACTIVE.\n", ntoh64(src_guid));
Packit 857059
			publish = TRUE;
Packit 857059
			dsap_scanner_rescan = 1;
Packit 857059
			break;
Packit 857059
Packit 857059
		case DSAP_PT_EVT_SRC_PORT_DOWN:
Packit 857059
			acm_log(1, "PROCESSING LOCAL PORT(0x%016"PRIx64") "
Packit 857059
				   "DOWN.\n", ntoh64(src_guid));
Packit 857059
			if (dsap_src_port_down(&src_gid) == TRUE)
Packit 857059
				publish = TRUE;
Packit 857059
			break;
Packit 857059
Packit 857059
		case DSAP_PT_EVT_PORT_RESCAN:
Packit 857059
			acm_log(1, "PROCESSING RESCAN REQUEST FOR PORT(0x%016"
Packit 857059
				   PRIx64").\n", ntoh64(src_guid));
Packit 857059
Packit 857059
			if (dsap_src_port_rescan(&src_gid) == TRUE)
Packit 857059
				publish = TRUE;
Packit 857059
			break;
Packit 857059
Packit 857059
		case DSAP_PT_EVT_FULL_RESCAN:
Packit 857059
			acm_log(1, "PROCESSING FULL FABRIC RESCAN REQUESTED BY"
Packit 857059
				   " PORT(0x%016"PRIx64").\n",
Packit 857059
				ntoh64(src_guid));
Packit 857059
			dsap_full_rescan();
Packit 857059
			goto exit;
Packit 857059
		}
Packit 857059
		SpinLockAcquire(&dsap_scanner_lock);
Packit 857059
	}
Packit 857059
	SpinLockRelease(&dsap_scanner_lock);
Packit 857059
Packit 857059
exit:
Packit 857059
	return publish;
Packit 857059
}
Packit 857059
Packit 857059
void dsap_port_event(uint64 src_guid, uint64 src_subnet, uint64 dest_guid,
Packit 857059
		     port_event_type_t event_type)
Packit 857059
{
Packit 857059
	acm_log(2, "Port Event Src %"PRIx64":%"PRIx64", Dst %"PRIx64", %s.\n",
Packit 857059
		ntoh64(src_subnet), ntoh64(src_guid), ntoh64(dest_guid),
Packit 857059
		port_event[event_type]);
Packit 857059
	SpinLockAcquire(&dsap_scanner_lock);
Packit 857059
	scan_ring_put++;
Packit 857059
	scan_ring_put &= (SCAN_RING_SIZE - 1);
Packit 857059
	if(scan_ring_put == scan_ring_take) {
Packit 857059
		/* full ring, just do a full scan, leave ring empty as side
Packit 857059
		   effect */
Packit 857059
		dsap_scanner_rescan = 1;
Packit 857059
	} else {
Packit 857059
		dsap_scan_port_ring[scan_ring_put].src_guid = src_guid;
Packit 857059
		dsap_scan_port_ring[scan_ring_put].src_subnet = src_subnet;
Packit 857059
		dsap_scan_port_ring[scan_ring_put].dest_guid = dest_guid;
Packit 857059
		dsap_scan_port_ring[scan_ring_put].event_type = event_type;
Packit 857059
	}
Packit 857059
	SpinLockRelease(&dsap_scanner_lock);
Packit 857059
	EventTrigger(&dsap_scanner_event);
Packit 857059
}
Packit 857059
Packit 857059
static void kill_proc_handler(int signo){
Packit 857059
	if (signo == SIGTERM) {
Packit 857059
		dsap_scanner_cleanup();
Packit 857059
		if(sigaction(SIGTERM, &old_action, NULL) < 0)
Packit 857059
                	acm_log(2, "Signal handler Restore failed \n");
Packit 857059
		raise(SIGTERM);
Packit 857059
	}
Packit 857059
}
Packit 857059
Packit 857059
#define SCAN_DELAY 5
Packit 857059
Packit 857059
static void * dsap_scanner(void* dummy)
Packit 857059
{
Packit 857059
	int32                  timeout_sec;
Packit 857059
	uint64                 last_scan = 0;
Packit 857059
	int32                  scan_delay = SCAN_DELAY;
Packit 857059
	uintn                  pub_count = 0;
Packit 857059
	uintn                  publish = 0;
Packit 857059
	FSTATUS                rval;
Packit 857059
	int                    err;
Packit 857059
	uint64                 time_stamp;
Packit 857059
	uint64                 since_scan;
Packit 857059
Packit 857059
	acm_log(2, "\n");
Packit 857059
Packit 857059
	/* Setting up signal handler to cleanup database*/
Packit 857059
	new_action.sa_handler = kill_proc_handler;
Packit 857059
	sigemptyset (&new_action.sa_mask);
Packit 857059
	new_action.sa_flags = 0;
Packit 857059
	if(sigaction(SIGTERM, &new_action, &old_action) < 0)
Packit 857059
		acm_log(2, "Signal handler Init failed \n");
Packit 857059
Packit 857059
	timeout_sec = 0;
Packit 857059
Packit 857059
	if (dsap_publish) {
Packit 857059
		if (op_ppath_version() != 3) {
Packit 857059
			acm_log(0, "opasadb mis-match %u. Cannot Publish.\n",
Packit 857059
				OPA_SA_DB_PATH_TABLE_VERSION);
Packit 857059
			return NULL;
Packit 857059
		}
Packit 857059
		err = op_ppath_create_writer(&shared_memory_writer);
Packit 857059
		if (err != 0) {
Packit 857059
			acm_log(0, "Failed to create shared memory tables.\n");
Packit 857059
			return NULL;
Packit 857059
		}
Packit 857059
	}
Packit 857059
Packit 857059
	while (!dsap_scanner_end) {
Packit 857059
		if (dsap_process_port_events()) 
Packit 857059
			publish = 1;
Packit 857059
Packit 857059
		if (dsap_scanner_rescan) {
Packit 857059
			acm_log(2, "Attempting Fabric Rescan.\n");
Packit 857059
			SpinLockAcquire(&dsap_scanner_lock);
Packit 857059
			scan_ring_take = scan_ring_put;
Packit 857059
			SpinLockRelease(&dsap_scanner_lock);
Packit 857059
Packit 857059
			/* Don't do fabric scans more than once every
Packit 857059
			 * scan_delay second(s).
Packit 857059
			 */
Packit 857059
			if ((GetTimeStamp() / 1000000) < 
Packit 857059
			     (last_scan + scan_delay)) {
Packit 857059
				timeout_sec = scan_delay;
Packit 857059
				acm_log(2, "Delaying Fabric Sweep By %u Sec\n",
Packit 857059
					scan_delay);
Packit 857059
				goto delay_scan;
Packit 857059
			}
Packit 857059
Packit 857059
			/* Set the last scan time to the last time a full scan
Packit 857059
			   was started, not when it was finished. */
Packit 857059
			last_scan = GetTimeStamp() / 1000000;
Packit 857059
Packit 857059
			acm_log(2, "Performing Full Fabric Sweep.\n");
Packit 857059
			dsap_empty_subnet_list();
Packit 857059
Packit 857059
			rval = dsap_add_src_ports();
Packit 857059
			if (rval != FSUCCESS) {
Packit 857059
				/* Wait a bit before trying to add the ports
Packit 857059
				   again.*/
Packit 857059
				timeout_sec = dsap_unsub_scan_frequency;
Packit 857059
				scan_delay = dsap_unsub_scan_frequency;
Packit 857059
				goto delay_scan;
Packit 857059
			}
Packit 857059
Packit 857059
			acm_log(2, "After adding src ports there are %lu "
Packit 857059
				   "subnets %lu total src ports\n\t\t%lu "
Packit 857059
				   "total dst ports %lu total virtual "
Packit 857059
				   "fabrics %lu pkeys %lu path_records.\n",
Packit 857059
				dsap_subnet_count(),
Packit 857059
				dsap_tot_src_port_count(),
Packit 857059
				dsap_tot_dst_port_count(),
Packit 857059
				dsap_tot_vfab_count(),
Packit 857059
				dsap_tot_pkey_count(),
Packit 857059
				dsap_tot_path_rec_count());
Packit 857059
Packit 857059
			while (((rval = dsap_scan_subnets()) == FBUSY) && 
Packit 857059
			       !dsap_scanner_end) {
Packit 857059
				scan_delay = lrand48() % 
Packit 857059
					dsap_unsub_scan_frequency;
Packit 857059
				timeout_sec = scan_delay;
Packit 857059
				acm_log(2, "An SM Reported Busy. Delaying "
Packit 857059
					   "Fabric Scan %u Seconds.\n",
Packit 857059
					(unsigned)(scan_delay));
Packit 857059
				EventWaitOnSeconds(&dsap_scanner_event, 
Packit 857059
						   timeout_sec);
Packit 857059
			}
Packit 857059
Packit 857059
			dsap_scanner_rescan = 0;
Packit 857059
			publish = 1;
Packit 857059
	
Packit 857059
			if (dsap_no_subscribe) 
Packit 857059
				timeout_sec = dsap_unsub_scan_frequency;
Packit 857059
			else
Packit 857059
				timeout_sec = dsap_scan_frequency;
Packit 857059
Packit 857059
			acm_log(2, "After fabric scan there are %lu local ports"
Packit 857059
				   " on %lu subnets,\n\t\t%lu destination ports,"
Packit 857059
				   " %lu total virtual fabrics, %lu pkeys and %lu"
Packit 857059
				   " path_records.\n",
Packit 857059
				dsap_tot_src_port_count(),
Packit 857059
				dsap_subnet_count(),
Packit 857059
				dsap_tot_dst_port_count(),
Packit 857059
				dsap_tot_vfab_count(),
Packit 857059
				dsap_tot_pkey_count(),
Packit 857059
				dsap_tot_path_rec_count());
Packit 857059
		}
Packit 857059
Packit 857059
		if (publish && dsap_publish) {
Packit 857059
			pub_count = dsap_publish_paths();
Packit 857059
			acm_log(2, "Published %lu paths.\n", pub_count);
Packit 857059
			publish=0;
Packit 857059
		}
Packit 857059
Packit 857059
delay_scan:
Packit 857059
		if (timeout_sec != 0) {
Packit 857059
			time_stamp = GetTimeStamp() / 1000000;
Packit 857059
Packit 857059
			if (time_stamp >= last_scan) {
Packit 857059
				since_scan = (time_stamp - last_scan);
Packit 857059
			} else {
Packit 857059
				/* Something or someone set the system clock
Packit 857059
				   back in time */
Packit 857059
				acm_log(2, "current time_stamp < last_scan."
Packit 857059
					   "Forcing full fabric sweep\n");
Packit 857059
				since_scan = timeout_sec;
Packit 857059
				last_scan = time_stamp;
Packit 857059
			}
Packit 857059
Packit 857059
			if (since_scan >= timeout_sec) {
Packit 857059
				acm_log(2, "since_scan >= timeout_sec. "
Packit 857059
					   "Performing full fabric sweep.\n");
Packit 857059
				dsap_scanner_rescan = 1;
Packit 857059
			} else {
Packit 857059
				acm_log(2, "Waiting on scanner event for %d "
Packit 857059
					   "sec.\n",
Packit 857059
					(int32)(timeout_sec - since_scan));
Packit 857059
				if (EventWaitOnSeconds(
Packit 857059
				      &dsap_scanner_event,
Packit 857059
				      timeout_sec - since_scan) != FSUCCESS)
Packit 857059
					dsap_scanner_rescan = 1;
Packit 857059
			}
Packit 857059
		} else {
Packit 857059
			EventWaitOnSeconds(&dsap_scanner_event, 
Packit 857059
					   EVENT_NO_TIMEOUT);
Packit 857059
		}
Packit 857059
	}
Packit 857059
Packit 857059
	return NULL;
Packit 857059
}
Packit 857059
Packit 857059
FSTATUS dsap_scanner_init(void)
Packit 857059
{
Packit 857059
	srand48(GetTimeStamp());
Packit 857059
Packit 857059
	SpinLockInitState(&dsap_scanner_lock);
Packit 857059
	if (! SpinLockInit(&dsap_scanner_lock))
Packit 857059
		goto faillock;
Packit 857059
Packit 857059
	EventInitState(&dsap_scanner_event);
Packit 857059
	if (! EventInit(&dsap_scanner_event))
Packit 857059
		goto failsevent;
Packit 857059
Packit 857059
	return FSUCCESS;
Packit 857059
Packit 857059
failsevent:
Packit 857059
	SpinLockDestroy(&dsap_scanner_lock);
Packit 857059
faillock:
Packit 857059
	return FINSUFFICIENT_RESOURCES;
Packit 857059
}
Packit 857059
Packit 857059
FSTATUS dsap_scanner_start(void)
Packit 857059
{
Packit 857059
	int rval;
Packit 857059
Packit 857059
	rval = pthread_create(&dsap_scanner_thread, NULL, dsap_scanner, NULL);
Packit 857059
Packit 857059
	return rval ? FINSUFFICIENT_RESOURCES: FSUCCESS;
Packit 857059
}
Packit 857059
Packit 857059
void dsap_scanner_cleanup(void)
Packit 857059
{
Packit 857059
	acm_log(2, "\n");
Packit 857059
Packit 857059
	dsap_scanner_end = 1;
Packit 857059
	EventTrigger(&dsap_scanner_event);
Packit 857059
	pthread_join(dsap_scanner_thread, NULL);
Packit 857059
	EventDestroy(&dsap_scanner_event);
Packit 857059
	SpinLockDestroy(&dsap_scanner_lock);
Packit 857059
Packit 857059
	acm_log(1, "Closing shared memory.\n");
Packit 857059
	op_ppath_close_writer(&shared_memory_writer);
Packit 857059
Packit 857059
Packit 857059
	return;
Packit 857059
}