/** =========================================================================
 * Resolve local CA characteristics using the umad layer rather than using
 * ib_resolve_self_via which requires SMP queries on the local port.
 */
int resolve_self(char *ca_name, uint8_t ca_port, ib_portid_t *portid,
		 int *portnum, ibmad_gid_t *gid)
{
	umad_port_t port;
	uint64_t prefix, guid;
	int rc;

	if (!(portid || portnum || gid))
		return (-1);

	if ((rc = umad_get_port(ca_name, ca_port, &port)) < 0)
		return rc;

	if (portid) {
		memset(portid, 0, sizeof(*portid));
		portid->lid = port.base_lid;
		portid->sl = port.sm_sl;
	}
	if (portnum)
		*portnum = port.portnum;
	if (gid) {
		memset(gid, 0, sizeof(*gid));
		prefix = cl_hton64(port.gid_prefix);
		guid = cl_hton64(port.port_guid);
		mad_encode_field(*gid, IB_GID_PREFIX_F, &prefix);
		mad_encode_field(*gid, IB_GID_GUID_F, &guid);
	}

	umad_release_port(&port);

	return 0;
}
示例#2
0
static void print_all_guids(IN osmtest_t * p_osmt)
{
    ib_api_status_t status;
    uint32_t num_ports = GUID_ARRAY_SIZE;
    ib_port_attr_t attr_array[GUID_ARRAY_SIZE];
    int i;

    /*
       Call the transport layer for a list of local port
       GUID values.
     */
    status =
        osm_vendor_get_all_port_attr(p_osmt->p_vendor, attr_array,
                                     &num_ports);
    if (status != IB_SUCCESS) {
        printf("\nError from osm_vendor_get_all_port_attr (%x)\n",
               status);
        return;
    }

    printf("\nListing GUIDs:\n");
    for (i = 0; i < num_ports; i++)
        printf("Port %i: 0x%" PRIx64 "\n", i,
               cl_hton64(attr_array[i].port_guid));
}
示例#3
0
static int update_id(void *cxt, uint64_t guid, char *p)
{
	osm_opensm_t *osm = cxt;
	osm_switch_t *sw;
	uint64_t id;
	char *e;

	sw = osm_get_switch_by_guid(&osm->subn, cl_hton64(guid));
	if (!sw) {
		OSM_LOG(&osm->log, OSM_LOG_VERBOSE,
			"switch with guid 0x%" PRIx64 " is not found\n", guid);
		return 0;
	}

	id = strtoull(p, &e, 0);
	if (*e && !isspace(*e)) {
		OSM_LOG(&osm->log, OSM_LOG_ERROR,
			"ERR AA05: cannot parse node id \'%s\'", p);
		return -1;
	}

	OSM_LOG(&osm->log, OSM_LOG_DEBUG,
		"update node 0x%" PRIx64 " id to 0x%" PRIx64 "\n", guid, id);

	((struct updn_node *)sw->priv)->id = id;

	return 0;
}
示例#4
0
static int mark_ignored_port(void *ctx, uint64_t guid, char *p)
{
	osm_ucast_mgr_t *m = ctx;
	osm_node_t *node = osm_get_node_by_guid(m->p_subn, cl_hton64(guid));
	osm_physp_t *physp;
	unsigned port;

	if (!node || !node->sw) {
		OSM_LOG(m->p_log, OSM_LOG_DEBUG,
			"switch with guid 0x%016" PRIx64 " is not found\n",
			guid);
		return 0;
	}

	if (!p || !*p || !(port = strtoul(p, NULL, 0)) ||
	    port >= node->sw->num_ports) {
		OSM_LOG(m->p_log, OSM_LOG_DEBUG,
			"bad port specified for guid 0x%016" PRIx64 "\n", guid);
		return 0;
	}

	physp = osm_node_get_physp_ptr(node, port);
	if (!physp)
		return 0;

	physp->is_prof_ignored = 1;

	return 0;
}
示例#5
0
ib_net64_t get_port_guid(IN osmtest_t * p_osmt, uint64_t port_guid)
{
    ib_api_status_t status;
    uint32_t num_ports = GUID_ARRAY_SIZE;
    ib_port_attr_t attr_array[GUID_ARRAY_SIZE];
    int i;

    /*
       Call the transport layer for a list of local port
       GUID values.
     */
    /* "local ports" is(?) phys, shouldn't this exclude port 0 then ? */
    status =
        osm_vendor_get_all_port_attr(p_osmt->p_vendor, attr_array,
                                     &num_ports);
    if (status != IB_SUCCESS) {
        printf("\nError from osm_vendor_get_all_port_attr (%x)\n",
               status);
        return (0);
    }

    if (num_ports == 1) {
        printf("using default guid 0x%" PRIx64 "\n",
               cl_hton64(attr_array[0].port_guid));
        return (attr_array[0].port_guid);
    }

    for (i = 0; i < num_ports; i++) {
        if (attr_array[i].port_guid == port_guid ||
                (!port_guid && attr_array[i].link_state > IB_LINK_DOWN))
            return attr_array[i].port_guid;
    }

    return 0;
}
示例#6
0
static void build_trap145(ib_mad_notice_attr_t * n, ib_portid_t * port)
{
	n->generic_type = 0x80 | IB_NOTICE_TYPE_INFO;
	n->g_or_v.generic.prod_type_lsb = cl_hton16(get_node_type(port));
	n->g_or_v.generic.trap_num = cl_hton16(145);
	n->issuer_lid = cl_hton16((uint16_t) port->lid);
	n->data_details.ntc_145.new_sys_guid = cl_hton64(0x1234567812345678);
}
示例#7
0
ib_api_status_t
osmv_simple_send_madw(IN osm_bind_handle_t h_bind,
		      IN osm_madw_t * const p_madw,
		      IN osmv_txn_ctx_t * p_txn, IN boolean_t is_retry)
{
	ib_api_status_t ret;
	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
	osm_mad_addr_t *p_mad_addr = osm_madw_get_mad_addr_ptr(p_madw);
	uint8_t mad_buf[MAD_BLOCK_SIZE];
	ib_mad_t *p_mad = (ib_mad_t *) mad_buf;
	uint64_t key = 0;

	OSM_LOG_ENTER(p_bo->p_vendor->p_log);

	CL_ASSERT(p_madw->mad_size <= MAD_BLOCK_SIZE);

	memset(p_mad, 0, MAD_BLOCK_SIZE);
	memcpy(p_mad, osm_madw_get_mad_ptr(p_madw), p_madw->mad_size);

	if (NULL != p_txn) {
		/* Push a fake txn id to the MAD */
		key = osmv_txn_get_key(p_txn);
		p_mad->trans_id = cl_hton64(key);
	}

	/*
	   Add call for packet drop randomizer.
	   This is a testing feature. If run_randomizer flag is set to TRUE,
	   the randomizer will be called, and randomally will drop
	   a packet. This is used for simulating unstable fabric.
	 */
	if (p_bo->p_vendor->run_randomizer == TRUE) {
		/* Try the randomizer */
		if (osm_pkt_randomizer_mad_drop(p_bo->p_vendor->p_log,
						p_bo->p_vendor->
						p_pkt_randomizer,
						p_mad) == TRUE) {
			osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
				"The MAD will not be sent. \n");
			ret = IB_SUCCESS;
		} else {
			ret =
			    osmv_transport_mad_send(h_bind, p_mad, p_mad_addr);
		}
	} else {
		ret = osmv_transport_mad_send(h_bind, p_mad, p_mad_addr);
	}

	if ((IB_SUCCESS == ret) && (NULL != p_txn) && (!is_retry)) {
		/* Set the timeout for receiving the response MAD */
		ret = osmv_txn_set_timeout_ev(h_bind, key,
					      p_bo->p_vendor->resp_timeout);
	}

	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
	return ret;
}
static void
__osmv_dispatch_simple_mad(IN osm_bind_handle_t h_bind,
			   IN const ib_mad_t * p_mad,
			   IN osmv_txn_ctx_t * p_txn,
			   IN const osm_mad_addr_t * p_mad_addr)
{
	osm_madw_t *p_madw;
	ib_mad_t *p_mad_buf;
	osm_madw_t *p_req_madw = NULL;
	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;

	OSM_LOG_ENTER(p_bo->p_vendor->p_log);

	/* Build the MAD wrapper to be returned to the user.
	 * The actual storage for the MAD is allocated there.
	 */
	p_madw =
	    osm_mad_pool_get(p_bo->p_osm_pool, h_bind, MAD_BLOCK_SIZE,
			     p_mad_addr);

	if (NULL == p_madw) {
		osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
			"__osmv_dispatch_simple_mad: ERR 6501: "
			"Out Of Memory - could not allocate a buffer of size %d\n",
			MAD_BLOCK_SIZE);

		goto dispatch_simple_mad_done;
	}

	p_mad_buf = osm_madw_get_mad_ptr(p_madw);
	/* Copy the payload to the MAD buffer */
	memcpy((void *)p_mad_buf, (void *)p_mad, MAD_BLOCK_SIZE);

	if (NULL != p_txn) {
		/* This is a RESPONSE MAD. Pair it with the REQUEST MAD, pass upstream */
		p_req_madw = p_txn->p_madw;
		CL_ASSERT(NULL != p_req_madw);

		p_mad_buf->trans_id = cl_hton64(osmv_txn_get_tid(p_txn));
		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
			"Restoring the original TID to 0x%" PRIx64 "\n",
			cl_ntoh64(p_mad_buf->trans_id));

		/* Reply matched, transaction complete */
		osmv_txn_done(h_bind, osmv_txn_get_key(p_txn), FALSE);
	} else {
		/* This is a REQUEST  MAD. Don't create a context, pass upstream */
	}

	/* Do the job ! */
	p_bo->recv_cb(p_madw, p_bo->cb_context, p_req_madw);

dispatch_simple_mad_done:
	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
}
示例#9
0
static int partition_add_port(unsigned lineno, struct part_conf *conf,
			      char *name, char *flag)
{
	osm_prtn_t *p = conf->p_prtn;
	ib_net64_t guid;
	boolean_t full = conf->full;

	if (!name || !*name || !strncmp(name, "NONE", strlen(name)))
		return 0;

	if (flag) {
		/* reset default membership to limited */
		full = FALSE;
		if (!strncmp(flag, "full", strlen(flag)))
			full = TRUE;
		else if (strncmp(flag, "limited", strlen(flag))) {
			OSM_LOG(conf->p_log, OSM_LOG_VERBOSE,
				"PARSE WARN: line %d: "
				"unrecognized port flag \'%s\'."
				" Assume \'limited\'\n", lineno, flag);
		}
	}

	if (!strncmp(name, "ALL", strlen(name))) {
		return osm_prtn_add_all(conf->p_log, conf->p_subn, p,
					0, full) == IB_SUCCESS ? 0 : -1;
	} else if (!strncmp(name, "ALL_CAS", strlen(name))) {
		return osm_prtn_add_all(conf->p_log, conf->p_subn, p,
					IB_NODE_TYPE_CA, full) == IB_SUCCESS ? 0 : -1;
	} else if (!strncmp(name, "ALL_SWITCHES", strlen(name))) {
		return osm_prtn_add_all(conf->p_log, conf->p_subn, p,
					IB_NODE_TYPE_SWITCH, full) == IB_SUCCESS ? 0 : -1;
	} else if (!strncmp(name, "ALL_ROUTERS", strlen(name))) {
		return osm_prtn_add_all(conf->p_log, conf->p_subn, p,
					IB_NODE_TYPE_ROUTER, full) == IB_SUCCESS ? 0 : -1;
	} else if (!strncmp(name, "SELF", strlen(name))) {
		guid = cl_ntoh64(conf->p_subn->sm_port_guid);
	} else {
		char *end;
		guid = strtoull(name, &end, 0);
		if (!guid || *end)
			return -1;
	}

	if (osm_prtn_add_port(conf->p_log, conf->p_subn, p,
			      cl_hton64(guid), full) != IB_SUCCESS)
		return -1;

	return 0;
}
示例#10
0
static int rank_root_node(void *cxt, uint64_t guid, char *p)
{
	updn_t *updn = cxt;
	osm_switch_t *sw;

	sw = osm_get_switch_by_guid(&updn->p_osm->subn, cl_hton64(guid));
	if (!sw) {
		OSM_LOG(&updn->p_osm->log, OSM_LOG_VERBOSE,
			"switch with guid 0x%" PRIx64 " is not found\n", guid);
		return 0;
	}

	OSM_LOG(&updn->p_osm->log, OSM_LOG_DEBUG,
		"Ranking root port GUID 0x%" PRIx64 "\n", guid);

	((struct updn_node *)sw->priv)->rank = 0;
	updn->num_roots++;

	return 0;
}
示例#11
0
static int set_hop_wf(void *ctx, uint64_t guid, char *p)
{
	osm_ucast_mgr_t *m = ctx;
	osm_node_t *node = osm_get_node_by_guid(m->p_subn, cl_hton64(guid));
	osm_physp_t *physp;
	unsigned port, hop_wf;
	char *e;

	if (!node || !node->sw) {
		OSM_LOG(m->p_log, OSM_LOG_DEBUG,
			"switch with guid 0x%016" PRIx64 " is not found\n",
			guid);
		return 0;
	}

	if (!p || !*p || !(port = strtoul(p, &e, 0)) || (p == e) ||
	    port >= node->sw->num_ports) {
		OSM_LOG(m->p_log, OSM_LOG_DEBUG,
			"bad port specified for guid 0x%016" PRIx64 "\n", guid);
		return 0;
	}

	p = e + 1;

	if (!*p || !(hop_wf = strtoul(p, &e, 0)) || p == e || hop_wf >= 0x100) {
		OSM_LOG(m->p_log, OSM_LOG_DEBUG,
			"bad hop weight factor specified for guid 0x%016" PRIx64
			"port %u\n", guid, port);
		return 0;
	}

	physp = osm_node_get_physp_ptr(node, port);
	if (!physp)
		return 0;

	physp->hop_wf = hop_wf;

	return 0;
}
示例#12
0
static int add_guid_to_order_list(void *ctx, uint64_t guid, char *p)
{
	osm_ucast_mgr_t *m = ctx;
	osm_port_t *port = osm_get_port_by_guid(m->p_subn, cl_hton64(guid));

	if (!port) {
		OSM_LOG(m->p_log, OSM_LOG_DEBUG,
			"port guid not found: 0x%016" PRIx64 "\n", guid);
		return 0;
	}

	if (port->flag) {
		OSM_LOG(m->p_log, OSM_LOG_DEBUG,
			"port guid specified multiple times 0x%016" PRIx64 "\n",
			guid);
		return 0;
	}

	cl_qlist_insert_tail(&m->port_order_list, &port->list_item);
	port->flag = 1;

	return 0;
}
示例#13
0
int osm_send_trap144(osm_sm_t * sm, ib_net16_t local)
{
	osm_madw_t *madw;
	ib_smp_t *smp;
	ib_mad_notice_attr_t *ntc;
	osm_port_t *port, *smport;
	ib_port_info_t *pi;

	port = osm_get_port_by_guid(sm->p_subn, sm->p_subn->sm_port_guid);
	if (!port) {
		OSM_LOG(sm->p_log, OSM_LOG_ERROR,
			"ERR 1104: cannot find SM port by guid 0x%" PRIx64 "\n",
			cl_ntoh64(sm->p_subn->sm_port_guid));
		return -1;
	}

	pi = &port->p_physp->port_info;

	/* don't bother with sending trap when SMA supports this */
	if (!local &&
	    pi->capability_mask&(IB_PORT_CAP_HAS_TRAP|IB_PORT_CAP_HAS_CAP_NTC))
		return 0;

	smport = osm_get_port_by_guid(sm->p_subn, sm->master_sm_guid);
	if (!smport) {
		OSM_LOG(sm->p_log, OSM_LOG_ERROR,
			"ERR 1106: cannot find master SM port by guid 0x%" PRIx64 "\n",
			cl_ntoh64(sm->master_sm_guid));
		return -1;
	}

	madw = osm_mad_pool_get(sm->p_mad_pool,
				osm_sm_mad_ctrl_get_bind_handle(&sm->mad_ctrl),
				MAD_BLOCK_SIZE, NULL);
	if (madw == NULL) {
		OSM_LOG(sm->p_log, OSM_LOG_ERROR,
			"ERR 1105: Unable to acquire MAD\n");
		return -1;
	}

	madw->mad_addr.dest_lid = smport->p_physp->port_info.base_lid;
	madw->mad_addr.addr_type.smi.source_lid = pi->base_lid;
	madw->resp_expected = TRUE;
	madw->fail_msg = CL_DISP_MSGID_NONE;

	smp = osm_madw_get_smp_ptr(madw);
	memset(smp, 0, sizeof(*smp));

	smp->base_ver = 1;
	smp->mgmt_class = IB_MCLASS_SUBN_LID;
	smp->class_ver = 1;
	smp->method = IB_MAD_METHOD_TRAP;
	smp->trans_id = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id)
							   & (uint64_t)(0xFFFFFFFF));
	if (smp->trans_id == 0)
		smp->trans_id = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id)
								   & (uint64_t)(0xFFFFFFFF));

	smp->attr_id = IB_MAD_ATTR_NOTICE;

	ntc = (ib_mad_notice_attr_t *) smp->data;

	ntc->generic_type = 0x80 | IB_NOTICE_TYPE_INFO;
	ib_notice_set_prod_type_ho(ntc, osm_node_get_type(port->p_node));
	ntc->g_or_v.generic.trap_num = cl_hton16(SM_LOCAL_CHANGES_TRAP); /* 144 */
	ntc->issuer_lid = pi->base_lid;
	ntc->data_details.ntc_144.lid = pi->base_lid;
	ntc->data_details.ntc_144.local_changes = local ?
	    TRAP_144_MASK_OTHER_LOCAL_CHANGES : 0;
	ntc->data_details.ntc_144.new_cap_mask = pi->capability_mask;
	ntc->data_details.ntc_144.change_flgs = local;

	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
		"Sending Trap 144, TID 0x%" PRIx64 " to SM lid %u\n",
		cl_ntoh64(smp->trans_id), cl_ntoh16(madw->mad_addr.dest_lid));

	osm_vl15_post(sm->p_vl15, madw);

	return 0;
}
示例#14
0
static int set_search_ordering_ports(void *ctx, uint64_t guid, char *p)
{
	osm_subn_t *p_subn = ctx;
	osm_node_t *node = osm_get_node_by_guid(p_subn, cl_hton64(guid));
	osm_switch_t *sw;
	uint8_t *search_ordering_ports = NULL;
	uint8_t port;
	unsigned int *ports = NULL;
	const int bpw = sizeof(*ports)*8;
	int words;
	int i = 1; /* port 0 maps to port 0 */

	if (!node || !(sw = node->sw)) {
		OSM_LOG(&p_subn->p_osm->log, OSM_LOG_VERBOSE,
			"switch with guid 0x%016" PRIx64 " is not found\n",
			guid);
		return 0;
	}

	if (sw->search_ordering_ports) {
		OSM_LOG(&p_subn->p_osm->log, OSM_LOG_VERBOSE,
			"switch with guid 0x%016" PRIx64 " already listed\n",
			guid);
		return 0;
	}

	search_ordering_ports = malloc(sizeof(*search_ordering_ports)*sw->num_ports);
	if (!search_ordering_ports) {
		OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR,
			"ERR 3A07: cannot allocate memory for search_ordering_ports\n");
		return -1;
	}
	memset(search_ordering_ports, 0, sizeof(*search_ordering_ports)*sw->num_ports);

	/* the ports array is for record keeping of which ports have
	 * been seen */
	words = (sw->num_ports + bpw - 1)/bpw;
	ports = malloc(words*sizeof(*ports));
	if (!ports) {
		OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR,
			"ERR 3A08: cannot allocate memory for ports\n");
		free(search_ordering_ports);
		return -1;
	}
	memset(ports, 0, words*sizeof(*ports));

	while ((*p != '\0') && (*p != '#')) {
		char *e;

		port = strtoul(p, &e, 0);
		if ((p == e) || (port == 0) || (port >= sw->num_ports) ||
		    !osm_node_get_physp_ptr(node, port)) {
			OSM_LOG(&p_subn->p_osm->log, OSM_LOG_VERBOSE,
				"bad port %d specified for guid 0x%016" PRIx64 "\n",
				port, guid);
			free(search_ordering_ports);
			free(ports);
			return 0;
		}

		if (ports[port/bpw] & (1u << (port%bpw))) {
			OSM_LOG(&p_subn->p_osm->log, OSM_LOG_VERBOSE,
				"port %d already specified for guid 0x%016" PRIx64 "\n",
				port, guid);
			free(search_ordering_ports);
			free(ports);
			return 0;
		}

		ports[port/bpw] |= (1u << (port%bpw));
		search_ordering_ports[i++] = port;

		p = e;
		while (isspace(*p)) {
			p++;
		}
	}

	if (i > 1) {
		for (port = 1; port < sw->num_ports; port++) {
			/* fill out the rest of the search_ordering_ports array
			 * in sequence using the remaining unspecified
			 * ports.
			 */
			if (!(ports[port/bpw] & (1u << (port%bpw)))) {
				search_ordering_ports[i++] = port;
			}
		}
		sw->search_ordering_ports = search_ordering_ports;
	} else {
		free(search_ordering_ports);
	}

	free(ports);
	return 0;
}
ib_api_status_t
osm_vendor_get_guid_ca_and_port(IN osm_vendor_t * const p_vend,
				IN ib_net64_t const guid,
				OUT uint32_t * p_hca_hndl,
				OUT char *p_hca_id,
				OUT uint8_t * p_hca_idx,
				OUT uint32_t * p_port_num)
{
	uint32_t caIdx;
	uint32_t ca_count = 0;
	uint8_t port_num;
	ib_api_status_t status = IB_ERROR;

	OSM_LOG_ENTER(p_vend->p_log);

	CL_ASSERT(p_vend);

	/* determine the number of CA's */
	ca_count = __hca_pfs_get_num_cas();
	if (!ca_count) {
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
			"osm_vendor_get_guid_ca_and_port: ERR 5231: "
			"Fail to get Any CA Ids.\n");
		goto Exit;
	}

	/*
	 * For each CA, retrieve the CA info attributes
	 */
	for (caIdx = 1; caIdx <= ca_count; caIdx++) {
		pfs_ca_info_t pfs_ca_info;
		if (__parse_ca_info_file(p_vend, caIdx, &pfs_ca_info) ==
		    IB_SUCCESS) {
			/* get all the ports info */
			for (port_num = 1; port_num <= pfs_ca_info.num_ports;
			     port_num++) {
				uint64_t port_guid;
				if (!__get_port_guid_from_port_gid_tbl
				    (p_vend, caIdx, port_num, &port_guid)) {
					if (cl_hton64(port_guid) == guid) {
						osm_log(p_vend->p_log,
							OSM_LOG_DEBUG,
							"osm_vendor_get_guid_ca_and_port: "
							"Found Matching guid on HCA:%d Port:%d.\n",
							caIdx, port_num);
						strcpy(p_hca_id,
						       pfs_ca_info.name);
						*p_port_num = port_num;
						*p_hca_idx = caIdx - 1;
						*p_hca_hndl = 0;
						status = IB_SUCCESS;
						goto Exit;
					}
				}
			}
		}
	}

	osm_log(p_vend->p_log, OSM_LOG_ERROR,
		"osm_vendor_get_guid_ca_and_port: ERR 5232: "
		"Fail to find HCA and Port for Port Guid 0x%" PRIx64 "\n",
		cl_ntoh64(guid));
	status = IB_INVALID_GUID;

Exit:

	OSM_LOG_EXIT(p_vend->p_log);
	return (status);
}
/**********************************************************************
 * Initialize an Info Struct for the Given HCA by its index 1..N
 **********************************************************************/
static ib_api_status_t
__osm_ca_info_init(IN osm_vendor_t * const p_vend,
		   IN uint32_t const idx, OUT osm_ca_info_t * const p_ca_info)
{
	ib_api_status_t status = IB_ERROR;
	uint8_t port_num;
	uint64_t port_guid;

	pfs_ca_info_t pfs_ca_info;

	OSM_LOG_ENTER(p_vend->p_log);

	/* parse the CA info file */
	if (__parse_ca_info_file(p_vend, idx, &pfs_ca_info) != IB_SUCCESS)
		goto Exit;

	p_ca_info->guid = cl_hton64(pfs_ca_info.guid);

	/* set size of attributes and allocate them */
	p_ca_info->attr_size = 1;
	p_ca_info->p_attr = (ib_ca_attr_t *) malloc(sizeof(ib_ca_attr_t));

	p_ca_info->p_attr->ca_guid = p_ca_info->guid;
	p_ca_info->p_attr->num_ports = pfs_ca_info.num_ports;

	/* now obtain the attributes of the ports */
	p_ca_info->p_attr->p_port_attr =
	    (ib_port_attr_t *) malloc(pfs_ca_info.num_ports *
				      sizeof(ib_port_attr_t));

	/* get all the ports info */
	for (port_num = 1; port_num <= pfs_ca_info.num_ports; port_num++) {
		pfs_port_info_t pfs_port_info;
		/* query the port attributes */
		if (__parse_port_info_file
		    (p_vend, idx, port_num, &pfs_port_info)) {
			osm_log(p_vend->p_log, OSM_LOG_ERROR,
				"__osm_ca_info_init: ERR 5226: "
				"Fail to get HCA:%d Port:%d Attributes.\n", idx,
				port_num);
			goto Exit;
		}

		/* HACK: the lids should have been converted to network but the rest of the code
		   is wrong and provdes them as is (host order) - so we stick with it. */
		p_ca_info->p_attr->p_port_attr[port_num - 1].lid =
		    pfs_port_info.lid;
		p_ca_info->p_attr->p_port_attr[port_num - 1].link_state =
		    pfs_port_info.state;
		p_ca_info->p_attr->p_port_attr[port_num - 1].sm_lid =
		    pfs_port_info.sm_lid;

		/* get the port guid */
		if (__get_port_guid_from_port_gid_tbl
		    (p_vend, idx, port_num, &port_guid)) {
			osm_log(p_vend->p_log, OSM_LOG_ERROR,
				"__osm_ca_info_init: ERR 5227: "
				"Fail to get HCA:%d Port:%d Guid.\n", idx,
				port_num);
			goto Exit;
		}
		p_ca_info->p_attr->p_port_attr[port_num - 1].port_guid =
		    cl_hton64(port_guid);
	}

	status = IB_SUCCESS;
Exit:
	OSM_LOG_EXIT(p_vend->p_log);
	return (status);
}
示例#17
0
/**********************************************************************
  The plock must be held before calling this function.
**********************************************************************/
static ib_net64_t req_determine_mkey(IN osm_sm_t * sm,
				     IN const osm_dr_path_t * p_path)
{
	osm_node_t *p_node;
	osm_port_t *p_sm_port;
	osm_physp_t *p_physp;
	ib_net64_t dest_port_guid = 0, m_key;
	uint8_t hop;

	OSM_LOG_ENTER(sm->p_log);

	p_physp = NULL;

	p_sm_port = osm_get_port_by_guid(sm->p_subn, sm->p_subn->sm_port_guid);

	/* hop_count == 0: destination port guid is SM */
	if (p_path->hop_count == 0) {
		dest_port_guid = sm->p_subn->sm_port_guid;
		goto Remote_Guid;
	}

	if (p_sm_port) {
		p_node = p_sm_port->p_node;
		if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH)
			p_physp = osm_node_get_physp_ptr(p_node, p_path->path[1]);
		else
			p_physp = p_sm_port->p_physp;
	}

	/* hop_count == 1: outgoing physp is SM physp */
	for (hop = 2; p_physp && hop <= p_path->hop_count; hop++) {
		p_physp = p_physp->p_remote_physp;
		if (!p_physp)
			break;
		p_node = p_physp->p_node;
		p_physp = osm_node_get_physp_ptr(p_node, p_path->path[hop]);
	}

	/* At this point, p_physp points at the outgoing physp on the
	   last hop, or NULL if we don't know it.
	*/
	if (!p_physp) {
		OSM_LOG(sm->p_log, OSM_LOG_ERROR,
			"ERR 1107: Outgoing physp is null on non-hop_0!\n");
		osm_dump_dr_path_v2(sm->p_log, p_path, FILE_ID, OSM_LOG_ERROR);
		dest_port_guid = 0;
		goto Remote_Guid;
	}

	if (p_physp->p_remote_physp) {
		dest_port_guid = p_physp->p_remote_physp->port_guid;
		goto Remote_Guid;
	}

	OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Target port guid unknown, "
		"using persistent DB\n");
	if (!osm_db_neighbor_get(sm->p_subn->p_neighbor,
				 cl_ntoh64(p_physp->port_guid),
				 p_physp->port_num,
				 &dest_port_guid, NULL)) {
		dest_port_guid = cl_hton64(dest_port_guid);
	}

Remote_Guid:
	if (dest_port_guid) {
		if (!osm_db_guid2mkey_get(sm->p_subn->p_g2m,
					  cl_ntoh64(dest_port_guid), &m_key)) {
			m_key = cl_hton64(m_key);
			OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
				"Found mkey for guid 0x%"
				PRIx64 "\n", cl_ntoh64(dest_port_guid));
		} else {
			OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
				"Target port mkey unknown, using default\n");
			m_key = sm->p_subn->opt.m_key;
		}
	} else {
		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
			"Target port guid unknown, using default\n");
		m_key = sm->p_subn->opt.m_key;
	}

	OSM_LOG_EXIT(sm->p_log);

	return m_key;
}
示例#18
0
/**********************************************************************
  The plock must be held before calling this function.
**********************************************************************/
osm_madw_t *osm_prepare_req_set(IN osm_sm_t * sm, IN const osm_dr_path_t * p_path,
				IN const uint8_t * p_payload,
				IN size_t payload_size,
				IN ib_net16_t attr_id, IN ib_net32_t attr_mod,
				IN boolean_t find_mkey, IN ib_net64_t m_key,
				IN cl_disp_msgid_t err_msg,
				IN const osm_madw_context_t * p_context)
{
	osm_madw_t *p_madw = NULL;
	ib_net64_t m_key_calc;
	ib_net64_t tid;

	CL_ASSERT(sm);

	OSM_LOG_ENTER(sm->p_log);

	CL_ASSERT(p_path);
	CL_ASSERT(attr_id);
	CL_ASSERT(p_payload);

	/* do nothing if we are exiting ... */
	if (osm_exit_flag)
		goto Exit;

	/* p_context may be NULL. */

	p_madw = osm_mad_pool_get(sm->p_mad_pool, sm->mad_ctrl.h_bind,
				  MAD_BLOCK_SIZE, NULL);
	if (p_madw == NULL) {
		OSM_LOG(sm->p_log, OSM_LOG_ERROR,
			"ERR 1102: Unable to acquire MAD\n");
		goto Exit;
	}

	tid = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id)
						 & (uint64_t)(0xFFFFFFFF));
	if (tid == 0)
		tid = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id)
							 & (uint64_t)(0xFFFFFFFF));

	if (sm->p_subn->opt.m_key_lookup == TRUE) {
		if (find_mkey == TRUE)
			m_key_calc = req_determine_mkey(sm, p_path);
		else
			m_key_calc = m_key;
	} else
		m_key_calc = sm->p_subn->opt.m_key;

	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
		"Setting %s (0x%X), modifier 0x%X, TID 0x%" PRIx64
		", MKey 0x%016" PRIx64 "\n",
		ib_get_sm_attr_str(attr_id), cl_ntoh16(attr_id),
		cl_ntoh32(attr_mod), cl_ntoh64(tid), cl_ntoh64(m_key_calc));

	ib_smp_init_new(osm_madw_get_smp_ptr(p_madw), IB_MAD_METHOD_SET,
			tid, attr_id, attr_mod, p_path->hop_count,
			m_key_calc, p_path->path,
			IB_LID_PERMISSIVE, IB_LID_PERMISSIVE);

	p_madw->mad_addr.dest_lid = IB_LID_PERMISSIVE;
	p_madw->mad_addr.addr_type.smi.source_lid = IB_LID_PERMISSIVE;
	p_madw->resp_expected = TRUE;
	p_madw->fail_msg = err_msg;

	/*
	   Fill in the mad wrapper context for the recipient.
	   In this case, the only thing the recipient needs is the
	   guid value.
	 */

	if (p_context)
		p_madw->context = *p_context;

	memcpy(osm_madw_get_smp_ptr(p_madw)->data, p_payload, payload_size);

Exit:
	OSM_LOG_EXIT(sm->p_log);
	return p_madw;
}
示例#19
0
/* //////////////////////////////////////////////////////////////////////// */
ib_api_status_t
osm_vendor_get_ports(IN osm_vendor_t * const p_vend,
		     IN ib_net64_t * const p_guids,
		     IN uint32_t * const p_num_guids)
{
	char *error = NULL;
	PIBT_GET_INTERFACE pfnIbtGetInterface;
	PIBT_INIT pfnIbtInitFunc;

	FSTATUS Status;
	uint32_t caCount, caGuidCount;
	IB_CA_ATTRIBUTES caAttributes;
	IB_HANDLE caHandle;
	uint32_t i;
	IB_PORT_ATTRIBUTES *pPortAttributesList;
	EUI64 CaGuidArray[8];
	void *context;
	uint64_t *p_port_guid;
	uint32_t free_guids;

	umadt_obj_t *p_umadt_obj = (umadt_obj_t *) p_vend;

	OSM_LOG_ENTER(p_umadt_obj->p_log);

	CL_ASSERT(p_guids);
	CL_ASSERT(p_num_guids);

	pfnIbtInitFunc =
	    (PIBT_INIT) dlsym(p_umadt_obj->umadt_handle, "IbtInit");

	if (!pfnIbtInitFunc) {
		printf("Error getting IbtInit function address.\n");
		return IB_ERROR;
	}

	(*pfnIbtInitFunc) ();

	pfnIbtGetInterface =
	    (PIBT_GET_INTERFACE) dlsym(p_umadt_obj->umadt_handle,
				       "IbtGetInterface");

	if (!pfnIbtGetInterface || (error = dlerror()) != NULL) {
		printf("Error getting IbtGetInterface function address.<%s>\n",
		       error);
		return FALSE;
	}
	(*pfnIbtGetInterface) (&p_umadt_obj->IbtInterface);

	caGuidCount = 8;
	Status =
	    p_umadt_obj->IbtInterface.GetCaGuidArray(&caGuidCount,
						     &CaGuidArray[0]);

	if ((Status != FSUCCESS) || (caGuidCount == 0)) {
		return FALSE;
	}

	free_guids = *p_num_guids;
	p_port_guid = p_guids;

	/* query each ca & copy its info into callers buffer */
	for (caCount = 0; caCount < caGuidCount; caCount++) {
		memset(&caAttributes, 0, sizeof(IB_CA_ATTRIBUTES));

		/* Open the CA */
		Status = p_umadt_obj->IbtInterface.Vpi.OpenCA(CaGuidArray[caCount], NULL,	/*  CACompletionCallback */
							      NULL,	/*  AsyncEventCallback */
							      NULL, &caHandle);
		if (Status != FSUCCESS) {
			return IB_ERROR;
		}

		Status = p_umadt_obj->IbtInterface.Vpi.QueryCA(caHandle,
							       &caAttributes,
							       &context);

		if (Status != FSUCCESS) {
			p_umadt_obj->IbtInterface.Vpi.CloseCA(caHandle);
			return IB_ERROR;
		}

		if (caAttributes.Ports > free_guids) {
			*p_num_guids = 0;
			memset(p_guids, 0, (*p_num_guids) * sizeof(uint64_t));
			return IB_INSUFFICIENT_MEMORY;
		}

		pPortAttributesList =
		    (IB_PORT_ATTRIBUTES *) malloc(caAttributes.
						  PortAttributesListSize);

		if (pPortAttributesList == NULL) {
			p_umadt_obj->IbtInterface.Vpi.CloseCA(caHandle);
			*p_num_guids = 0;
			memset(p_guids, 0, (*p_num_guids) * sizeof(uint64_t));
			return IB_INSUFFICIENT_MEMORY;
		}

		memset(pPortAttributesList, 0,
		       caAttributes.PortAttributesListSize);

		caAttributes.PortAttributesList = pPortAttributesList;

		Status = p_umadt_obj->IbtInterface.Vpi.QueryCA(caHandle,
							       &caAttributes,
							       &context);

		if (Status != FSUCCESS) {
			p_umadt_obj->IbtInterface.Vpi.CloseCA(caHandle);
			*p_num_guids = 0;
			memset(p_guids, 0, (*p_num_guids) * sizeof(uint64_t));
			return IB_ERROR;
		}

		pPortAttributesList = caAttributes.PortAttributesList;

		for (i = 0; i < caAttributes.Ports; i++) {
			*(p_port_guid) =
			    cl_hton64((uint64_t) pPortAttributesList->GUID);
			pPortAttributesList = pPortAttributesList->Next;
			p_port_guid++;
		}
		free(caAttributes.PortAttributesList);
		p_umadt_obj->IbtInterface.Vpi.CloseCA(caHandle);

		free_guids = free_guids - caAttributes.Ports;

	}
	*p_num_guids = *p_num_guids - free_guids;
	return IB_SUCCESS;
}
示例#20
0
static int do_lid_matrix_file_load(void *context)
{
	char line[1024];
	uint8_t hops[256];
	char *file_name;
	FILE *file;
	ib_net64_t guid;
	osm_opensm_t *p_osm = context;
	osm_switch_t *p_sw;
	unsigned lineno;
	uint16_t lid;

	file_name = p_osm->subn.opt.lid_matrix_dump_file;
	if (!file_name) {
		OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
			"lid matrix file name is not given; "
			"using default lid matrix generation algorithm\n");
		return 1;
	}

	file = fopen(file_name, "r");
	if (!file) {
		OSM_LOG(&p_osm->log, OSM_LOG_ERROR | OSM_LOG_SYS, "ERR 6305: "
			"cannot open lid matrix file \'%s\': %m\n", file_name);
		return -1;
	}

	lineno = 0;
	p_sw = NULL;

	while (fgets(line, sizeof(line) - 1, file) != NULL) {
		char *p, *q;
		lineno++;

		p = line;
		while (isspace(*p))
			p++;

		if (*p == '#')
			continue;

		if (!strncmp(p, "Switch", 6)) {
			q = strstr(p, " guid 0x");
			if (!q) {
				OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
					"PARSE ERROR: %s:%u: "
					"cannot parse switch definition\n",
					file_name, lineno);
				return -1;
			}
			p = q + 8;
			guid = strtoull(p, &q, 16);
			if (q == p || !isspace(*q)) {
				OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
					"PARSE ERROR: %s:%u: "
					"cannot parse switch guid: \'%s\'\n",
					file_name, lineno, p);
				return -1;
			}
			guid = cl_hton64(guid);

			p_sw = osm_get_switch_by_guid(&p_osm->subn, guid);
			if (!p_sw) {
				OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
					"cannot find switch %016" PRIx64 "\n",
					cl_ntoh64(guid));
				continue;
			}
		} else if (p_sw && !strncmp(p, "0x", 2)) {
			unsigned long num;
			unsigned len = 0;

			memset(hops, 0xff, sizeof(hops));

			p += 2;
			num = strtoul(p, &q, 16);
			if (num > 0xffff || q == p ||
			    (*q != ':' && !isspace(*q))) {
				OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
					"PARSE ERROR: %s:%u: "
					"cannot parse lid: \'%s\'\n",
					file_name, lineno, p);
				return -1;
			}
			/* Just checked the range, so casting is safe */
			lid = (uint16_t) num;
			p = q;
			while (isspace(*p) || *p == ':')
				p++;
			while (len < 256 && *p && *p != '#') {
				num = strtoul(p, &q, 16);
				if (num > 0xff || q == p) {
					OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
						"PARSE ERROR: %s:%u: "
						"cannot parse hops number: \'%s\'\n",
						file_name, lineno, p);
					return -1;
				}
				/* Just checked the range, so casting is safe */
				hops[len++] = (uint8_t) num;
				p = q;
				while (isspace(*p))
					p++;
			}
			/* additionally try to extract guid */
			q = strstr(p, " portguid 0x");
			if (!q) {
				OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
					"PARSE WARNING: %s:%u: "
					"cannot find port guid "
					"(maybe broken dump): \'%s\'\n",
					file_name, lineno, p);
				guid = 0;
			} else {
				p = q + 12;
				guid = strtoull(p, &q, 16);
				if (q == p || !isspace(*q)) {
					OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
						"PARSE WARNING: %s:%u: "
						"cannot parse port guid "
						"(maybe broken dump): \'%s\'\n",
						file_name, lineno, p);
					guid = 0;
				}
			}
			guid = cl_hton64(guid);
			add_lid_hops(p_osm, p_sw, lid, guid, hops, len);
		}
	}

	fclose(file);
	return 0;
}
示例#21
0
static int do_ucast_file_load(void *context)
{
	char line[1024];
	char *file_name;
	FILE *file;
	ib_net64_t sw_guid, port_guid;
	osm_opensm_t *p_osm = context;
	osm_switch_t *p_sw;
	uint16_t lid;
	uint8_t port_num;
	unsigned lineno;

	file_name = p_osm->subn.opt.lfts_file;
	if (!file_name) {
		OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
			"LFTs file name is not given; "
			"using default routing algorithm\n");
		return 1;
	}

	file = fopen(file_name, "r");
	if (!file) {
		OSM_LOG(&p_osm->log, OSM_LOG_ERROR | OSM_LOG_SYS, "ERR 6302: "
			"cannot open ucast dump file \'%s\': %m\n", file_name);
		return -1;
	}

	lineno = 0;
	p_sw = NULL;

	while (fgets(line, sizeof(line) - 1, file) != NULL) {
		char *p, *q;
		lineno++;

		p = line;
		while (isspace(*p))
			p++;

		if (*p == '#')
			continue;

		if (!strncmp(p, "Multicast mlids", 15)) {
			OSM_LOG(&p_osm->log, OSM_LOG_ERROR | OSM_LOG_SYS,
				"ERR 6303: "
				"Multicast dump file detected; "
				"skipping parsing. Using default "
				"routing algorithm\n");
		} else if (!strncmp(p, "Unicast lids", 12)) {
			if (p_sw)
				osm_ucast_mgr_set_fwd_table(&p_osm->sm.
							    ucast_mgr, p_sw);
			q = strstr(p, " guid 0x");
			if (!q) {
				OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
					"PARSE ERROR: %s:%u: "
					"cannot parse switch definition\n",
					file_name, lineno);
				return -1;
			}
			p = q + 8;
			sw_guid = strtoull(p, &q, 16);
			if (q == p || !isspace(*q)) {
				OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
					"PARSE ERROR: %s:%u: "
					"cannot parse switch guid: \'%s\'\n",
					file_name, lineno, p);
				return -1;
			}
			sw_guid = cl_hton64(sw_guid);

			p_sw = osm_get_switch_by_guid(&p_osm->subn, sw_guid);
			if (!p_sw) {
				OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
					"cannot find switch %016" PRIx64 "\n",
					cl_ntoh64(sw_guid));
				continue;
			}
			memset(p_sw->new_lft, OSM_NO_PATH,
			       IB_LID_UCAST_END_HO + 1);
		} else if (p_sw && !strncmp(p, "0x", 2)) {
			p += 2;
			lid = (uint16_t) strtoul(p, &q, 16);
			if (q == p || !isspace(*q)) {
				OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
					"PARSE ERROR: %s:%u: "
					"cannot parse lid: \'%s\'\n",
					file_name, lineno, p);
				return -1;
			}
			p = q;
			while (isspace(*p))
				p++;
			port_num = (uint8_t) strtoul(p, &q, 10);
			if (q == p || !isspace(*q)) {
				OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
					"PARSE ERROR: %s:%u: "
					"cannot parse port: \'%s\'\n",
					file_name, lineno, p);
				return -1;
			}
			p = q;
			/* additionally try to exract guid */
			q = strstr(p, " portguid 0x");
			if (!q) {
				OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
					"PARSE WARNING: %s:%u: "
					"cannot find port guid "
					"(maybe broken dump): \'%s\'\n",
					file_name, lineno, p);
				port_guid = 0;
			} else {
				p = q + 12;
				port_guid = strtoull(p, &q, 16);
				if (q == p || (!isspace(*q) && *q != ':')) {
					OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
						"PARSE WARNING: %s:%u: "
						"cannot parse port guid "
						"(maybe broken dump): \'%s\'\n",
						file_name, lineno, p);
					port_guid = 0;
				}
			}
			port_guid = cl_hton64(port_guid);
			add_path(p_osm, p_sw, lid, port_num, port_guid);
		}
	}

	if (p_sw)
		osm_ucast_mgr_set_fwd_table(&p_osm->sm.ucast_mgr, p_sw);

	fclose(file);
	return 0;
}
示例#22
0
/*
 * Send a trap (Subn LID Route) Trap(Notice) through the regular
 * connection QP connection (targeted at QP0)
 *
 * Wait for the trap repress
 */
ib_api_status_t
osmt_send_trap_wait_for_forward(IN osmtest_t * const p_osmt,
				IN osmt_qp_ctx_t * p_qp_ctx)
{
	ib_smp_t *p_smp = (ib_smp_t *) (p_qp_ctx->p_send_buf);
	ib_mad_notice_attr_t *p_ntc = ib_smp_get_payload_ptr(p_smp);
	ib_sa_mad_t *p_sa_mad;
	IB_MGT_ret_t mgt_res;
	VAPI_ret_t vapi_ret;
	VAPI_wc_desc_t wc_desc;
	VAPI_ud_av_hndl_t avh;
	IB_ud_av_t av;
	static VAPI_wr_id_t wrid = 2222;
	osm_log_t *p_log = &p_osmt->log;
	ib_api_status_t status = IB_SUCCESS;

	OSM_LOG_ENTER(p_log);

	OSM_LOG(p_log, OSM_LOG_INFO,
		"Sending Traps to QP0 of SA LID:0x%X\n",
		p_osmt->local_port.sm_lid);

	/* init the MAD */
	memset(p_smp, 0, sizeof(ib_smp_t));
	ib_mad_init_new((ib_mad_t *) p_smp,
			IB_MCLASS_SUBN_LID,
			(uint8_t) 2,
			IB_MAD_METHOD_TRAP, cl_hton64(wrid), (ib_net16_t) 0, 0);

	wrid++;
	p_smp->attr_id = IB_MAD_ATTR_NOTICE;

	/* prepare the notice */
	p_ntc->generic_type = 0x82;	/*  generic, type = 2 */
	ib_notice_set_prod_type_ho(p_ntc, 1);
	p_ntc->g_or_v.generic.trap_num = cl_hton16(0x26);
	p_ntc->issuer_lid = cl_hton16(2);

	/* --------------------- PREP ------------------------- */
	if (osmt_mtl_mad_post_recv_bufs(&p_qp_ctx->qp_bind_hndl, p_qp_ctx->p_recv_buf, 1,	/*  we need to receive both trap repress and report */
					GRH_LEN + MAD_BLOCK_SIZE, wrid) != 1) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0127: "
			"Error posting recv bufs\n");
		status = IB_ERROR;
		goto Exit;
	}
	OSM_LOG(p_log, OSM_LOG_DEBUG, "Posted recv bufs\n");

	av.dlid = p_osmt->local_port.sm_lid;
	av.grh_flag = FALSE;

	/*  EZ: returned in HACK: use constants */
	av.static_rate = 0;	/*  p_mad_addr->static_rate; */
	av.src_path_bits = 1;	/*  p_mad_addr->path_bits; */
	av.sl = 0;		/*  p_mad_addr->addr_type.gsi.service_level; */

	OSM_LOG(p_log, OSM_LOG_DEBUG,
		"av.dlid 0x%X, av.static_rate %d, av.path_bits %d\n",
		cl_ntoh16(av.dlid), av.static_rate, av.src_path_bits);

	/* send it */
	mgt_res = IB_MGT_send_mad(p_qp_ctx->ib_mgt_qp0_handle, p_smp,	/*  actual payload */
				  &av,	/*  address vector */
				  wrid,	/*  casting the mad wrapper pointer for err cb */
				  p_osmt->opt.transaction_timeout);
	if (mgt_res != IB_MGT_OK) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0128: "
			"Error sending mad (%d)\n", mgt_res);
		status = IB_ERROR;
		goto Exit;
	}

	vapi_ret =
	    osmt_mtl_create_av(&p_qp_ctx->qp_bind_hndl,
			       p_osmt->local_port.sm_lid, &avh);
	if (vapi_ret != VAPI_OK) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0129: "
			"Error Preparing AVH (%s)\n",
			VAPI_strerror_sym(vapi_ret));
		status = IB_ERROR;
		goto Exit;
	}
	OSM_LOG(p_log, OSM_LOG_DEBUG, "Prepared AVH\n");

	OSM_LOG(p_log, OSM_LOG_DEBUG, "Trap MAD Sent\n");

	/* --------------------- RECV ------------------------- */
	vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
					 p_qp_ctx->qp_bind_hndl.rq_cq_hndl,
					 &wc_desc, 200, 10000, &avh);
	if (vapi_ret != VAPI_SUCCESS) {
		if (vapi_ret == VAPI_CQ_EMPTY) {
			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0130: "
				"Timeout receiving mad (%s)\n",
				VAPI_strerror_sym(vapi_ret));
			status = IB_TIMEOUT;
		} else {
			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0131: "
				"Error receiving mad (%s)\n",
				VAPI_strerror_sym(vapi_ret));
			status = IB_ERROR;
		}
		goto Exit;
	}

	/* check to see if successful - by examination of the subscribe bit */
	p_sa_mad = (ib_sa_mad_t *) (p_qp_ctx->p_recv_buf + GRH_LEN);

	if (p_sa_mad->method == IB_MAD_METHOD_REPORT) {
		if (p_sa_mad->attr_id == IB_MAD_ATTR_NOTICE) {
			OSM_LOG(p_log, OSM_LOG_INFO, "Received the Report!\n");
			status = IB_SUCCESS;
		} else {
			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 1020"
				"Did not receive a Report(Notice) but attr:%d\n",
				cl_ntoh16(p_sa_mad->attr_id));
			status = IB_ERROR;
		}
	} else {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 1020"
			"Received an Unexpected Method:%d\n", p_smp->method);
		status = IB_ERROR;
	}

Exit:
	OSM_LOG_EXIT(p_log);
	return status;
}
示例#23
0
/* Send a MAD out on the GSI interface */
ib_api_status_t
__osmv_send_sa_req(IN osmv_sa_bind_info_t * p_bind,
		   IN const osmv_sa_mad_data_t * const p_sa_mad_data,
		   IN const osmv_query_req_t * const p_query_req)
{
	ib_api_status_t status;
	ib_mad_t *p_mad_hdr;
	ib_sa_mad_t *p_sa_mad;
	osm_madw_t *p_madw;
	osm_log_t *p_log = p_bind->p_log;
	static atomic32_t trans_id;
	boolean_t sync;
	osmv_query_req_t *p_query_req_copy;

	OSM_LOG_ENTER(p_log);

	/*
	   since the sm_lid might change we obtain it every send
	   (actually it is cached in the bind object and refreshed
	   every 30sec by this proc )
	 */
	status =
	    __osmv_get_lid_and_sm_lid_by_port_guid(p_bind->p_vendor,
						   p_bind->port_guid,
						   &p_bind->
						   last_lids_update_sec,
						   &p_bind->lid,
						   &p_bind->sm_lid);
	if (status != IB_SUCCESS) {
		osm_log(p_log, OSM_LOG_ERROR,
			"__osmv_send_sa_req: ERR 0509: "
			"Fail to obtain the sm lid.\n");
		goto Exit;
	}

	/* Get a MAD wrapper for the send */
	p_madw = osm_mad_pool_get(p_bind->p_mad_pool,
				  p_bind->h_bind, MAD_BLOCK_SIZE, NULL);

	if (p_madw == NULL) {
		osm_log(p_log, OSM_LOG_ERROR,
			"__osmv_send_sa_req: ERR 0510: "
			"Unable to acquire MAD.\n");
		status = IB_INSUFFICIENT_RESOURCES;
		goto Exit;
	}

	/* Initialize the Sent MAD: */

	/* Initialize the MAD buffer for the send operation. */
	p_mad_hdr = osm_madw_get_mad_ptr(p_madw);
	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);

	/* Get a new transaction Id */
	cl_atomic_inc(&trans_id);

	/* Cleanup the MAD from any residue */
	memset(p_sa_mad, 0, MAD_BLOCK_SIZE);

	/* Initialize the standard MAD header. */
	ib_mad_init_new(p_mad_hdr,	/* mad pointer */
			IB_MCLASS_SUBN_ADM,	/* class */
			(uint8_t) 2,	/* version */
			p_sa_mad_data->method,	/* method */
			cl_hton64((uint64_t) trans_id),	/* tid */
			p_sa_mad_data->attr_id,	/* attr id */
			p_sa_mad_data->attr_mod	/* attr mod */
	    );

	/* Set the query information. */
	p_sa_mad->sm_key = p_query_req->sm_key;
	p_sa_mad->attr_offset = 0;
	p_sa_mad->comp_mask = p_sa_mad_data->comp_mask;
	if (p_sa_mad->comp_mask) {
		memcpy(p_sa_mad->data, p_sa_mad_data->p_attr,
		       ib_get_attr_size(p_sa_mad_data->attr_offset));
	}

	/*
	   Provide the address to send to
	 */
	/* Patch to handle IBAL - host order , where it should take destination lid in network order */
#ifdef OSM_VENDOR_INTF_AL
	p_madw->mad_addr.dest_lid = p_bind->sm_lid;
#else
	p_madw->mad_addr.dest_lid = cl_hton16(p_bind->sm_lid);
#endif
	p_madw->mad_addr.addr_type.smi.source_lid = cl_hton16(p_bind->lid);
	p_madw->mad_addr.addr_type.gsi.remote_qp = CL_HTON32(1);
	p_madw->mad_addr.addr_type.gsi.remote_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
	p_madw->mad_addr.addr_type.gsi.pkey_ix = 0;
	p_madw->resp_expected = TRUE;
	p_madw->fail_msg = CL_DISP_MSGID_NONE;

	/*
	   Provide MAD context such that the call back will know what to do.
	   We have to keep the entire request structure so we know the CB.
	   Since we can not rely on the client to keep it arroud until
	   the response - we duplicate it and will later dispose it (in CB).
	   To store on the MADW we cast it into what opensm has:
	   p_madw->context.arb_context.context1
	 */
	p_query_req_copy = malloc(sizeof(*p_query_req_copy));
	*p_query_req_copy = *p_query_req;
	p_madw->context.arb_context.context1 = p_query_req_copy;

	/* we can support async as well as sync calls */
	sync = ((p_query_req->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC);

	/* send the mad asynchronously */
	status = osm_vendor_send(osm_madw_get_bind_handle(p_madw),
				 p_madw, p_madw->resp_expected);

	/* if synchronous - wait on the event */
	if (sync) {
		osm_log(p_log, OSM_LOG_DEBUG,
			"__osmv_send_sa_req: " "Waiting for async event.\n");
		cl_event_wait_on(&p_bind->sync_event, EVENT_NO_TIMEOUT, FALSE);
		cl_event_reset(&p_bind->sync_event);
		status = p_madw->status;
	}

Exit:
	OSM_LOG_EXIT(p_log);
	return status;
}
static ib_api_status_t
__osmv_dispatch_rmpp_rcv(IN osm_bind_handle_t h_bind,
			 IN const ib_mad_t * p_mad,
			 IN osmv_txn_ctx_t * p_txn,
			 IN const osm_mad_addr_t * p_mad_addr)
{
	ib_api_status_t status = IB_SUCCESS;
	osmv_rmpp_recv_ctx_t *p_recv_ctx = osmv_txn_get_rmpp_recv_ctx(p_txn);
	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
	boolean_t is_last1 = FALSE, is_last2 = FALSE;
	osm_madw_t *p_new_madw = NULL, *p_req_madw = NULL;
	ib_mad_t *p_mad_buf;
	uint32_t size = 0;
	uint64_t key = osmv_txn_get_key(p_txn);
	uint64_t tid = osmv_txn_get_tid(p_txn);

	OSM_LOG_ENTER(p_bo->p_vendor->p_log);

	if (TRUE == osmv_rmpp_is_ack(p_mad)) {
		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
			"Not supposed to receive ACK's --> dropping the MAD\n");

		goto dispatch_rmpp_rcv_done;
	}

	if (TRUE == osmv_rmpp_is_abort_stop(p_mad)) {
		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
			"__osmv_dispatch_rmpp_rcv: ERR 6504: "
			"The Remote Side stopped sending\n");

		status = IB_REMOTE_ERROR;
		goto dispatch_rmpp_rcv_done;
	}

	status = __osmv_dispatch_accept_seg(h_bind, p_txn, p_mad);
	switch (status) {

	case IB_SUCCESS:

		/* Check wheter this is the legal last MAD */
		/* Criteria #1: the received MAD is marked last */
		is_last1 = osmv_rmpp_is_last(p_mad);

		/* Criteria #2: the total accumulated length hits the advertised one */
		is_last2 = is_last1;

		size = osmv_rmpp_recv_ctx_get_byte_num_from_first(p_recv_ctx);
		if (size > 0) {
			is_last2 =
			    (osmv_rmpp_recv_ctx_get_cur_byte_num(p_recv_ctx) >=
			     size);
		}

		if (is_last1 != is_last2) {

			osmv_rmpp_send_nak(h_bind, p_mad, p_mad_addr,
					   IB_RMPP_TYPE_ABORT,
					   IB_RMPP_STATUS_BAD_LEN);

			status = IB_ERROR;
			goto dispatch_rmpp_rcv_done;
		}

		/* TBD Consider an optimization - sending an ACK
		 * only for the last segment in the window
		 */
		__osmv_dispatch_send_ack(h_bind, p_mad, p_txn, p_mad_addr);
		break;

	case IB_INSUFFICIENT_RESOURCES:
		/* An out-of-order segment received. Send the ACK anyway */
		__osmv_dispatch_send_ack(h_bind, p_mad, p_txn, p_mad_addr);
		status = IB_SUCCESS;
		goto dispatch_rmpp_rcv_done;

	case IB_INSUFFICIENT_MEMORY:
		osmv_rmpp_send_nak(h_bind, p_mad, p_mad_addr,
				   IB_RMPP_TYPE_STOP, IB_RMPP_STATUS_RESX);
		goto dispatch_rmpp_rcv_done;

	default:
		/* Illegal return code */
		CL_ASSERT(FALSE);
	}

	if (TRUE != is_last1) {
		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
			"RMPP MADW assembly continues, TID=0x%" PRIx64 "\n", tid);
		goto dispatch_rmpp_rcv_done;
	}

	/* This is the last packet. */
	if (0 == size) {
		/* The total size was not advertised in the first packet */
		size = osmv_rmpp_recv_ctx_get_byte_num_from_last(p_recv_ctx);
	}

	/*
	   NOTE: the received mad might not be >= 256 bytes.
	   some MADs might contain several SA records but still be
	   less then a full MAD.
	   We have to use RMPP to send them over since on a regular
	   "simple" MAD there is no way to know how many records were sent
	 */

	/* Build the MAD wrapper to be returned to the user.
	 * The actual storage for the MAD is allocated there.
	 */
	p_new_madw =
	    osm_mad_pool_get(p_bo->p_osm_pool, h_bind, size, p_mad_addr);
	if (NULL == p_new_madw) {
		osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
			"__osmv_dispatch_rmpp_rcv: ERR 6506: "
			"Out Of Memory - could not allocate %d bytes for the MADW\n",
			size);

		status = IB_INSUFFICIENT_MEMORY;
		goto dispatch_rmpp_rcv_done;
	}

	p_req_madw = osmv_txn_get_madw(p_txn);
	p_mad_buf = osm_madw_get_mad_ptr(p_new_madw);
	status = osmv_rmpp_recv_ctx_reassemble_arbt_mad(p_recv_ctx, size,
							(uint8_t *) p_mad_buf);
	if (IB_SUCCESS != status) {
		osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
			"__osmv_dispatch_rmpp_rcv: ERR 6507: "
			"Internal error - could not reassemble the result MAD\n");
		goto dispatch_rmpp_rcv_done;	/* What can happen here? */
	}

	/* The MAD is assembled, we are about to apply the callback.
	 * Delete the transaction context, unless the transaction is double sided */
	if (FALSE == osmv_txn_is_rmpp_init_by_peer(p_txn)
	    || FALSE == osmv_mad_is_multi_resp(p_mad)) {

		osmv_txn_done(h_bind, key, FALSE);
	}

	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
		"RMPP MADW %p assembly complete, TID=0x%" PRIx64 "\n", p_new_madw,
		tid);

	p_mad_buf->trans_id = cl_hton64(tid);
	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
		"Restoring the original TID to 0x%" PRIx64 "\n",
		cl_ntoh64(p_mad_buf->trans_id));

	/* Finally, do the job! */
	p_bo->recv_cb(p_new_madw, p_bo->cb_context, p_req_madw);

dispatch_rmpp_rcv_done:
	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
	return status;
}
示例#25
0
static ib_api_status_t
__osmv_rmpp_send_segment(IN osm_bind_handle_t h_bind,
			 IN osmv_txn_ctx_t * p_txn, IN uint32_t seg_num)
{
	ib_api_status_t ret;
	osmv_rmpp_send_ctx_t *p_send_ctx;
	uint8_t mad_buf[MAD_BLOCK_SIZE];
	ib_mad_t *p_mad = (ib_mad_t *) mad_buf;
	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
	osm_mad_addr_t *p_mad_addr =
	    osm_madw_get_mad_addr_ptr(osmv_txn_get_madw(p_txn));
	uint32_t timeout = p_bo->p_vendor->resp_timeout;
	uint64_t key;

	OSM_LOG_ENTER(p_bo->p_vendor->p_log);

#ifdef OSMV_RANDOM_DROP
	if (TRUE == osmv_random_drop()) {

		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
			"Error injection - simulating the RMPP segment drop\n");
		return IB_SUCCESS;
	}
#endif

	p_send_ctx = osmv_txn_get_rmpp_send_ctx(p_txn);
	key = osmv_txn_get_key(p_txn);

	if (0 != seg_num) {
		ret =
		    osmv_rmpp_send_ctx_get_seg(p_send_ctx, seg_num, timeout,
					       p_mad);
		CL_ASSERT(IB_SUCCESS == ret);

		/* Put the segment to the wire ! */
		p_mad->trans_id = cl_hton64(key);

		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
			"Sending RMPP segment #%d, on-wire TID=0x%llX\n",
			seg_num, p_mad->trans_id);

		/*
		   Add call for packet drop randomizer.
		   This is a testing feature. If run_randomizer flag is set to TRUE,
		   the randomizer will be called, and randomally will drop
		   a packet. This is used for simulating unstable fabric.
		 */
		if (p_bo->p_vendor->run_randomizer == TRUE) {
			/* Try the randomizer */
			if (osm_pkt_randomizer_mad_drop(p_bo->p_vendor->p_log,
							p_bo->p_vendor->
							p_pkt_randomizer,
							p_mad) == TRUE) {
				osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
					"The MAD will not be sent. \n");
				ret = IB_SUCCESS;
			} else {
				ret =
				    osmv_transport_mad_send((osm_bind_handle_t)
							    p_bo, p_mad,
							    p_mad_addr);
			}
		} else {
			ret =
			    osmv_transport_mad_send((osm_bind_handle_t) p_bo,
						    p_mad, p_mad_addr);
		}
	} else {
		/* This is an ACK for double-sided handshake. Give it a special treatment. */

		/* It doesn't really matter which data to put. Only the header matters. */
		ret = osmv_rmpp_send_ctx_get_seg(p_send_ctx, 1, timeout, p_mad);
		CL_ASSERT(IB_SUCCESS == ret);

		p_mad->trans_id = cl_hton64(key);
		ret =
		    osmv_rmpp_send_ack((osm_bind_handle_t) p_bo, p_mad,
				       0 /* segnum */ ,
				       OSMV_RMPP_RECV_WIN /* NWL */ ,
				       p_mad_addr);
	}

	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
	return ret;
}
示例#26
0
int main(int argc, char *argv[])
{
    static osmtest_t osm_test;
    osmtest_opt_t opt = { 0 };
    ib_net64_t guid = 0;
    uint16_t max_lid = 100;
    ib_api_status_t status;
    uint32_t log_flags = OSM_LOG_ERROR | OSM_LOG_INFO;
    int32_t vendor_debug = 0;
    char flow_name[64];
    uint32_t next_option;
    const char *const short_option = "f:l:m:M:d:g:s:t:i:pcvVh";

    /*
     * In the array below, the 2nd parameter specified the number
     * of arguments as follows:
     * 0: no arguments
     * 1: argument
     * 2: optional
     */
    const struct option long_option[] = {
        {"create", 0, NULL, 'c'},
        {"debug", 1, NULL, 'd'},
        {"flow", 1, NULL, 'f'},
        {"wait", 1, NULL, 'w'},
        {"inventory", 1, NULL, 'i'},
        {"max_lid", 1, NULL, 'm'},
        {"guid", 2, NULL, 'g'},
        {"port", 0, NULL, 'p'},
        {"help", 0, NULL, 'h'},
        {"stress", 1, NULL, 's'},
        {"Multicast_Mode", 1, NULL, 'M'},
        {"timeout", 1, NULL, 't'},
        {"verbose", 0, NULL, 'v'},
        {"log_file", 1, NULL, 'l'},
        {"vf", 1, NULL, 'x'},
        {"V", 0, NULL, 'V'},

        {NULL, 0, NULL, 0}	/* Required at end of array */
    };

    /* Make sure that the opensm, complib and osmtest were compiled using
       same modes (debug/free) */
    if (osm_is_debug() != cl_is_debug() || osm_is_debug() != osmt_is_debug()
            || osmt_is_debug() != cl_is_debug()) {
        fprintf(stderr,
                "-E- OpenSM, Complib and OsmTest were compiled using different modes\n");
        fprintf(stderr,
                "-E- OpenSM debug:%d Complib debug:%d OsmTest debug:%d \n",
                osm_is_debug(), cl_is_debug(), osmt_is_debug());
        exit(1);
    }

    opt.transaction_timeout = OSMT_DEFAULT_TRANS_TIMEOUT_MILLISEC;
    opt.wait_time = OSMT_DEFAULT_TRAP_WAIT_TIMEOUT_SEC;
    opt.retry_count = OSMT_DEFAULT_RETRY_COUNT;
    opt.force_log_flush = FALSE;
    opt.stress = 0;
    opt.log_file = NULL;
    opt.create = FALSE;
    opt.mmode = 1;
    opt.ignore_path_records = FALSE;	/*  Do path Records too */
    opt.flow = OSMT_FLOW_ALL;	/*  run all validation tests */
    strcpy(flow_name, "All Validations");
    strcpy(opt.file_name, "osmtest.dat");

    printf("\nCommand Line Arguments\n");
    do {
        next_option = getopt_long_only(argc, argv, short_option,
                                       long_option, NULL);
        switch (next_option) {
        case 'c':
            /*
             * Create the inventory file.
             */
            opt.create = TRUE;
            printf("\tCreating inventory file\n");
            break;

        case 'i':
            /*
             * Specifies inventory file name.
             */
            if (strlen(optarg) > OSMTEST_FILE_PATH_MAX)
                printf
                ("\nError: path name too long (ignored)\n");
            else
                strcpy(opt.file_name, optarg);

            printf("\tFile = %s\n", opt.file_name);
            break;

        case 'f':
            /*
             * Specifies Flow .
             */
            if (strlen(optarg) > OSMTEST_FILE_PATH_MAX)
                printf
                ("\nError: path name too long (ignored)\n");
            else
                strcpy(flow_name, optarg);

            if (!strcmp("c", optarg)) {
                strcpy(flow_name, "Create Inventory");
                opt.flow = OSMT_FLOW_CREATE_INVENTORY;
            } else if (!strcmp("v", optarg)) {
                strcpy(flow_name, "Validate Inventory");
                opt.flow = OSMT_FLOW_VALIDATE_INVENTORY;
            } else if (!strcmp("s", optarg)) {
                strcpy(flow_name, "Services Registration");
                opt.flow = OSMT_FLOW_SERVICE_REGISTRATION;
            } else if (!strcmp("e", optarg)) {
                strcpy(flow_name, "Event Forwarding");
                opt.flow = OSMT_FLOW_EVENT_FORWARDING;
            } else if (!strcmp("f", optarg)) {
                strcpy(flow_name, "Stress SA");
                opt.flow = OSMT_FLOW_STRESS_SA;
            } else if (!strcmp("m", optarg)) {
                strcpy(flow_name, "Multicast");
                opt.flow = OSMT_FLOW_MULTICAST;
            } else if (!strcmp("q", optarg)) {
                strcpy(flow_name, "QoS: VLArb and SLtoVL");
                opt.flow = OSMT_FLOW_QOS;
            } else if (!strcmp("t", optarg)) {
                strcpy(flow_name, "Trap 64/65");
                opt.flow = OSMT_FLOW_TRAP;
            } else if (!strcmp("a", optarg)) {
                strcpy(flow_name, "All Validations");
                opt.flow = OSMT_FLOW_ALL;
            } else {
                printf("\nError: unknown flow %s\n", flow_name);
                exit(2);
            }
            break;

        case 'w':
            /*
             * Specifies trap 64/65 wait time
             */
            CL_ASSERT(strtol(optarg, NULL, 0) < 0x100);
            opt.wait_time = (uint8_t) strtol(optarg, NULL, 0);
            printf("\tTrap 64/65 wait time = %d\n", opt.wait_time);
            break;

        case 'm':
            /*
             * Specifies the max LID to search for during exploration.
             */
            max_lid = atoi(optarg);
            printf("\tMAX-LID %u\n", max_lid);
            break;

        case 'g':
            /*
             * Specifies port guid with which to bind.
             */
            guid = cl_hton64(strtoull(optarg, NULL, 16));
            printf(" Guid <0x%" PRIx64 ">\n", cl_hton64(guid));
            break;

        case 'p':
            /*
             * Display current port guids
             */
            guid = INVALID_GUID;
            break;

        case 't':
            /*
             * Specifies transaction timeout.
             */
            opt.transaction_timeout = strtol(optarg, NULL, 0);
            printf("\tTransaction timeout = %d\n",
                   opt.transaction_timeout);
            break;

        case 'l':
            opt.log_file = optarg;
            printf("\tLog File:%s\n", opt.log_file);
            break;

        case 'v':
            /*
             * Increases log verbosity.
             */
            log_flags = (log_flags << 1) | 1;
            printf("\tVerbose option -v (log flags = 0x%X)\n",
                   log_flags);
            break;

        case 'V':
            /*
             * Specifies maximum log verbosity.
             */
            log_flags = 0xFFFFFFFF;
            opt.force_log_flush = TRUE;
            printf("\tEnabling maximum log verbosity\n");
            break;

        case 's':
            /*
             * Perform stress test.
             */
            opt.stress = strtol(optarg, NULL, 0);
            printf("\tStress test enabled: ");
            switch (opt.stress) {
            case 1:
                printf("Small SA queries\n");
                break;
            case 2:
                printf("Large SA queries\n");
                break;
            case 3:
                printf("Large Path Record SA queries\n");
                break;
            default:
                printf("Unknown value %u (ignored)\n",
                       opt.stress);
                opt.stress = 0;
                break;
            }
            break;

        case 'M':
            /*
             * Perform multicast test.
             */
            opt.mmode = strtol(optarg, NULL, 0);
            printf("\tMulticast test enabled: ");
            switch (opt.mmode) {
            case 1:
                printf
                ("Short MC Flow - single mode (default)\n");
                break;
            case 2:
                printf("Short MC Flow - multiple mode\n");
                break;
            case 3:
                printf("Long MC Flow - single mode\n");
                break;
            case 4:
                printf("Long MC Flow - multiple mode\n");
                break;
            default:
                printf("Unknown value %u (ignored)\n",
                       opt.stress);
                opt.mmode = 0;
                break;
            }
            break;

        case 'd':
            /*
             * Debug Options
             */
            printf("\tDebug Option: ");
            switch (strtol(optarg, NULL, 0)) {
            case 1:
                printf("Ignore Path Records\n");
                opt.ignore_path_records = TRUE;
                break;
            case 2:
                printf("Force Log Flush\n");
                opt.force_log_flush = TRUE;
                break;
            case 3:
            /* Used to be memory tracking */
            default:
                printf("Unknown value %ld (ignored)\n",
                       strtol(optarg, NULL, 0));
                break;
            }
            break;

        case 'h':
            show_usage();
            return 0;

        case 'x':
            log_flags = strtol(optarg, NULL, 0);
            printf
            ("\t\t\t\tVerbose option -vf (log flags = 0x%X)\n",
             log_flags);
            break;

        case -1:
            printf("Done with args\n");
            break;

        default:
            show_usage();
            return 1;
        }

    }
    while (next_option != -1);

    printf("\tFlow = %s\n", flow_name);

    if (vendor_debug)
        osm_vendor_set_debug(osm_test.p_vendor, vendor_debug);

    complib_init();

    status = osmtest_init(&osm_test, &opt, (osm_log_level_t) log_flags);
    if (status != IB_SUCCESS) {
        printf("\nError from osmtest_init: %s\n",
               ib_get_err_str(status));
        goto Exit;
    }
    if (cl_hton64(guid) == cl_hton64(INVALID_GUID)) {
        print_all_guids(&osm_test);
        complib_exit();
        return (status);
    }

    /*
       If the user didn't specify a GUID on the command line,
       then get a port GUID value with which to bind.
     */
    if (guid == 0 && !(guid = get_port_guid(&osm_test, guid))) {
        printf("\nError: port guid 0x%" PRIx64 " not found\n", guid);
        goto Exit;
    }

    /*
     * Guid may be zero going into this function if the user
     * hasn't specified a binding port on the command line.
     */
    status = osmtest_bind(&osm_test, max_lid, guid);
    if (status != IB_SUCCESS)
        exit(status);

    status = osmtest_run(&osm_test);
    if (status != IB_SUCCESS) {
        printf("OSMTEST: TEST \"%s\" FAIL\n", flow_name);
    } else {
        printf("OSMTEST: TEST \"%s\" PASS\n", flow_name);
    }
    osmtest_destroy(&osm_test);

    complib_exit();

Exit:
    return (status);
}
/* Send a MAD out on the GSI interface */
static ib_api_status_t
__osmv_send_sa_req(IN osmv_sa_bind_info_t * p_bind,
		   IN const osmv_sa_mad_data_t * const p_sa_mad_data,
		   IN const osmv_query_req_t * const p_query_req)
{
	ib_api_status_t status;
	ib_mad_t *p_mad_hdr;
	ib_sa_mad_t *p_sa_mad;
	osm_madw_t *p_madw;
	osm_log_t *p_log = p_bind->p_log;
	static atomic32_t trans_id;
	boolean_t sync;
	osmv_query_req_t *p_query_req_copy;

	OSM_LOG_ENTER(p_log);

	/*
	   since the sm_lid might change we obtain it every send
	   (actually it is cached in the bind object and refreshed
	   every 30sec by this proc)
	 */
	if (time(NULL) > p_bind->last_lids_update_sec + 30) {
		status = update_umad_port(p_bind->p_vendor);
		if (status != IB_SUCCESS) {
			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5509: "
				"Failed to obtain the SM lid\n");
			goto Exit;
		}
		p_bind->last_lids_update_sec = time(NULL);
	}

	/* Get a MAD wrapper for the send */
	p_madw = osm_mad_pool_get(p_bind->p_mad_pool,
				  p_bind->h_bind, MAD_BLOCK_SIZE, NULL);

	if (p_madw == NULL) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5510: "
			"Unable to acquire MAD\n");
		status = IB_INSUFFICIENT_RESOURCES;
		goto Exit;
	}

	/* Initialize the Sent MAD: */

	/* Initialize the MAD buffer for the send operation. */
	p_mad_hdr = osm_madw_get_mad_ptr(p_madw);
	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);

	/* Get a new transaction Id */
	cl_atomic_inc(&trans_id);

	/* Cleanup the MAD from any residue */
	memset(p_sa_mad, 0, MAD_BLOCK_SIZE);

	/* Initialize the standard MAD header. */
	ib_mad_init_new(p_mad_hdr,	/* mad pointer */
			IB_MCLASS_SUBN_ADM,	/* class */
			(uint8_t) 2,	/* version */
			p_sa_mad_data->method,	/* method */
			cl_hton64((uint64_t) trans_id),	/* tid */
			p_sa_mad_data->attr_id,	/* attr id */
			p_sa_mad_data->attr_mod	/* attr mod */);

	/* Set the query information. */
	p_sa_mad->sm_key = p_query_req->sm_key;
	p_sa_mad->attr_offset = 0;
	p_sa_mad->comp_mask = p_sa_mad_data->comp_mask;
#ifdef DUAL_SIDED_RMPP
	if (p_sa_mad->method == IB_MAD_METHOD_GETMULTI)
		p_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
#endif
	if (p_sa_mad->comp_mask) {
		memcpy(p_sa_mad->data, p_sa_mad_data->p_attr,
		       ib_get_attr_size(p_sa_mad_data->attr_offset));
	}

	/*
	   Provide the address to send to
	 */
	p_madw->mad_addr.dest_lid =
	    cl_hton16(p_bind->p_vendor->umad_port.sm_lid);
	p_madw->mad_addr.addr_type.smi.source_lid =
	    cl_hton16(p_bind->p_vendor->umad_port.base_lid);
	p_madw->mad_addr.addr_type.gsi.remote_qp = CL_HTON32(1);
	p_madw->resp_expected = TRUE;
	p_madw->fail_msg = CL_DISP_MSGID_NONE;

	/*
	   Provide MAD context such that the call back will know what to do.
	   We have to keep the entire request structure so we know the CB.
	   Since we can not rely on the client to keep it around until
	   the response - we duplicate it and will later dispose it (in CB).
	   To store on the MADW we cast it into what opensm has:
	   p_madw->context.ni_context.node_guid
	 */
	p_query_req_copy = malloc(sizeof(*p_query_req_copy));
	*p_query_req_copy = *p_query_req;
	p_madw->context.ni_context.node_guid =
	    (ib_net64_t) (long)p_query_req_copy;

	/* we can support async as well as sync calls */
	sync = ((p_query_req->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC);

	/* send the mad asynchronously */
	status = osm_vendor_send(osm_madw_get_bind_handle(p_madw),
				 p_madw, p_madw->resp_expected);

	/* if synchronous - wait on the event */
	if (sync) {
		OSM_LOG(p_log, OSM_LOG_DEBUG, "Waiting for async event\n");
		cl_event_wait_on(&p_bind->sync_event, EVENT_NO_TIMEOUT, FALSE);
		cl_event_reset(&p_bind->sync_event);
		status = p_madw->status;
	}

Exit:
	OSM_LOG_EXIT(p_log);
	return status;
}
示例#28
0
/*
 * Register/Unregister to receive the given InformInfo
 *
 * Uses the qp context to send the inform info mad.
 * Wait for GetResp(InformInfoResp)
 *
 */
ib_api_status_t
osmt_reg_unreg_inform_info(IN osmtest_t * p_osmt,
			   IN osmt_qp_ctx_t * p_qp_ctx,
			   IN ib_inform_info_t * p_inform_info,
			   IN uint8_t reg_flag)
{
	ib_sa_mad_t *p_sa_mad = (ib_sa_mad_t *) (p_qp_ctx->p_send_buf);
	ib_inform_info_t *p_ii = ib_sa_mad_get_payload_ptr(p_sa_mad);	/*  SA Payload */
	VAPI_ret_t vapi_ret;
	VAPI_wc_desc_t wc_desc;
	VAPI_ud_av_hndl_t avh;
	static VAPI_wr_id_t wrid = 16198;
	osm_log_t *p_log = &p_osmt->log;
	ib_api_status_t status = IB_SUCCESS;

	OSM_LOG_ENTER(&p_osmt->log);

	/* init the MAD */
	ib_mad_init_new((ib_mad_t *) p_sa_mad,
			IB_MCLASS_SUBN_ADM,
			(uint8_t) 2,
			IB_MAD_METHOD_SET, cl_hton64(wrid), (ib_net16_t) 0, 0);
	wrid++;
	p_sa_mad->attr_id = IB_MAD_ATTR_INFORM_INFO;

	/* copy the reference inform info */
	memcpy(p_ii, p_inform_info, sizeof(ib_inform_info_t));

	if (reg_flag) {
		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
			"Subscribing InformInfo: Traps from lid:0x%X to 0x%X, trap num :0x%X\n",
			p_ii->lid_range_begin, p_ii->lid_range_end,
			p_ii->g_or_v.generic.trap_num);
	} else {
		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
			"UnSubscribing InformInfo: Traps from lid:0x%X to 0x%X\n",
			p_ii->lid_range_begin, p_ii->lid_range_end);
	}

	/* set the subscribe bit */
	if (reg_flag) {
		p_ii->subscribe = 1;
	} else {
		p_ii->subscribe = 0;
		/*
		 * we need to set the QPN on the mad if we unsubscribe:
		 * o13-2.1.1 - QPN Field need to be set when unsubscribing.
		 */
		ib_inform_info_set_qpn(p_ii,
				       cl_hton32(p_qp_ctx->qp_bind_hndl.qp_id.
						 qp_num));
	}

	osm_dump_inform_info(&p_osmt->log, p_ii, OSM_LOG_DEBUG);

	/* --------------------- PREP ------------------------- */
	if (osmt_mtl_mad_post_recv_bufs(&p_qp_ctx->qp_bind_hndl, p_qp_ctx->p_recv_buf, 1,	/*  but we need only one mad at a time */
					GRH_LEN + MAD_BLOCK_SIZE, wrid) != 1) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0120: "
			"Error posting recv bufs\n");
		status = IB_ERROR;
		goto Exit;
	}
	OSM_LOG(p_log, OSM_LOG_DEBUG, "Posted recv bufs\n");

	vapi_ret =
	    osmt_mtl_create_av(&p_qp_ctx->qp_bind_hndl,
			       p_osmt->local_port.sm_lid, &avh);
	if (vapi_ret != VAPI_OK) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0121: "
			"Error Preparing AVH (%s)\n",
			VAPI_strerror_sym(vapi_ret));
		status = IB_ERROR;
		goto Exit;
	}
	OSM_LOG(p_log, OSM_LOG_DEBUG, "Prepared AVH\n");

	if (osm_log_is_active(p_log, OSM_LOG_DEBUG)) {
		osm_dump_sa_mad(p_log, (ib_sa_mad_t *) (p_qp_ctx->p_send_buf),
				OSM_LOG_DEBUG);
#if 0
		for (i = 56; i < 253; i++) {
			if (i % 8 == 0) {
				printf("\n %d : ", i);
			}
			printf("0x%02X ", p_qp_ctx->p_send_buf[i]);
		}
#endif
		printf("\n");
	}

	/* --------------------- SEND ------------------------- */
	vapi_ret = osmt_mtl_mad_send(&p_qp_ctx->qp_bind_hndl, wrid, p_qp_ctx->p_send_buf, 1,	/*  SA is QP1 */
				     0,	/*  SL is 0 */
				     OSMT_MTL_REVERSE_QP1_WELL_KNOWN_Q_KEY,
				     avh);
	if (vapi_ret != VAPI_OK) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0122: "
			"Error sending mad (%s)\n",
			VAPI_strerror_sym(vapi_ret));
		status = IB_ERROR;
		goto Exit;
	}

	vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
					 p_qp_ctx->qp_bind_hndl.sq_cq_hndl,
					 &wc_desc, 20, 10000, NULL);
	if (vapi_ret != VAPI_OK) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0123: "
			"Error getting send completion (%s)\n",
			VAPI_strerror_sym(vapi_ret));
		status = IB_ERROR;
		goto Exit;
	}

	if (wc_desc.status != VAPI_SUCCESS) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0124: "
			"Error on send completion (%s) (%d)\n",
			VAPI_strerror_sym(wc_desc.status), wc_desc.status);
		status = IB_ERROR;
		goto Exit;
	}
	OSM_LOG(p_log, OSM_LOG_DEBUG, "Sent MAD\n");

	/* --------------------- RECV ------------------------- */
	vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
					 p_qp_ctx->qp_bind_hndl.rq_cq_hndl,
					 &wc_desc, 20, 10000, &avh);
	if (vapi_ret != VAPI_SUCCESS) {
		if (vapi_ret == VAPI_CQ_EMPTY) {
			status = IB_TIMEOUT;
		} else {
			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0125: "
				"Error receiving mad (%s)\n",
				VAPI_strerror_sym(vapi_ret));
			status = IB_ERROR;
		}
		goto Exit;
	}

	/* check to see if successful - by examination of the subscribe bit */
	p_sa_mad = (ib_sa_mad_t *) (p_qp_ctx->p_recv_buf + GRH_LEN);

	if (p_sa_mad->status != IB_SUCCESS) {
		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n",
			ib_get_mad_status_str((ib_mad_t *) p_sa_mad));
		status = IB_REMOTE_ERROR;
		goto Exit;
	}

	if (p_sa_mad->method != IB_MAD_METHOD_GET_RESP) {
		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
			"Expected IB_MAD_METHOD_GET_RESP but got:(%X)\n",
			p_sa_mad->method);
		status = IB_REMOTE_ERROR;
		goto Exit;
	}

	if (p_sa_mad->attr_id != IB_MAD_ATTR_INFORM_INFO) {
		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
			"Expected IB_MAD_ATTR_INFORM_INFO but got:(%X)\n",
			cl_ntoh16(p_sa_mad->attr_id));
		status = IB_REMOTE_ERROR;
		goto Exit;
	}

	p_ii = ib_sa_mad_get_payload_ptr(p_sa_mad);
	if (!p_ii->subscribe) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0126: "
			"Subscribe/Unsubscribe Failed\n");
		status = IB_REMOTE_ERROR;
	}

Exit:
	OSM_LOG_EXIT(&p_osmt->log);
	return status;
}