|
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 |
}
|