Пример #1
0
/**********************************************************************
 Clear out all existing port lid assignments
**********************************************************************/
static ib_api_status_t state_mgr_clean_known_lids(IN osm_sm_t * sm)
{
	ib_api_status_t status = IB_SUCCESS;
	cl_ptr_vector_t *p_vec = &(sm->p_subn->port_lid_tbl);
	uint32_t i;

	OSM_LOG_ENTER(sm->p_log);

	/* we need a lock here! */
	CL_PLOCK_ACQUIRE(sm->p_lock);

	for (i = 0; i < cl_ptr_vector_get_size(p_vec); i++)
		cl_ptr_vector_set(p_vec, i, NULL);

	CL_PLOCK_RELEASE(sm->p_lock);

	OSM_LOG_EXIT(sm->p_log);
	return status;
}
Пример #2
0
/*
  Store the given pkey in the "new" blocks array.
  Also, make sure the regular block exists.
*/
ib_api_status_t osm_pkey_tbl_set_new_entry(IN osm_pkey_tbl_t * p_pkey_tbl,
					   IN uint16_t block_idx,
					   IN uint8_t pkey_idx,
					   IN uint16_t pkey)
{
	ib_pkey_table_t *p_block;

	if (!(p_block = osm_pkey_tbl_new_block_get(p_pkey_tbl, block_idx))) {
		p_block = (ib_pkey_table_t *) malloc(sizeof(ib_pkey_table_t));
		if (!p_block)
			return IB_ERROR;
		memset(p_block, 0, sizeof(ib_pkey_table_t));
		cl_ptr_vector_set(&p_pkey_tbl->new_blocks, block_idx, p_block);
	}

	p_block->pkey_entry[pkey_idx] = pkey;
	if (p_pkey_tbl->used_blocks <= block_idx)
		p_pkey_tbl->used_blocks = block_idx + 1;

	return IB_SUCCESS;
}
Пример #3
0
ib_api_status_t osm_pkey_tbl_set(IN osm_pkey_tbl_t * p_pkey_tbl,
				 IN uint16_t block, IN ib_pkey_table_t * p_tbl,
				 IN boolean_t allow_both_pkeys)
{
	uint16_t b, i;
	ib_pkey_table_t *p_pkey_block;
	uint16_t *p_prev_pkey;
	ib_net16_t pkey, pkey_base;

	/* make sure the block is allocated */
	if (cl_ptr_vector_get_size(&p_pkey_tbl->blocks) > block)
		p_pkey_block =
		    (ib_pkey_table_t *) cl_ptr_vector_get(&p_pkey_tbl->blocks,
							  block);
	else
		p_pkey_block = NULL;

	if (!p_pkey_block) {
		p_pkey_block =
		    (ib_pkey_table_t *) malloc(sizeof(ib_pkey_table_t));
		if (!p_pkey_block)
			return IB_ERROR;
		memset(p_pkey_block, 0, sizeof(ib_pkey_table_t));
		cl_ptr_vector_set(&p_pkey_tbl->blocks, block, p_pkey_block);
	}

	/* sets the block values */
	memcpy(p_pkey_block, p_tbl, sizeof(ib_pkey_table_t));

	/*
	   NOTE: as the spec does not require uniqueness of PKeys in
	   tables there is no other way but to refresh the entire keys map.

	   Moreover, if the same key exists but with full membership it should
	   have precedence over the key with limited membership !
	 */
	cl_map_remove_all(&p_pkey_tbl->keys);

	for (b = 0; b < cl_ptr_vector_get_size(&p_pkey_tbl->blocks); b++) {

		p_pkey_block = cl_ptr_vector_get(&p_pkey_tbl->blocks, b);
		if (!p_pkey_block)
			continue;

		for (i = 0; i < IB_NUM_PKEY_ELEMENTS_IN_BLOCK; i++) {
			pkey = p_pkey_block->pkey_entry[i];
			if (ib_pkey_is_invalid(pkey))
				continue;

			if (allow_both_pkeys)
				pkey_base = pkey;
			else
				pkey_base = ib_pkey_get_base(pkey);

			/*
			   If allow_both_pkeys is FALSE,
			   ignore the PKey Full Member bit in the key but store
			   the pointer to the table element as the map value
			 */
			p_prev_pkey = cl_map_get(&p_pkey_tbl->keys, pkey_base);

			/* we only insert if no previous or it is not full member and allow_both_pkeys is FALSE */
			if ((p_prev_pkey == NULL) ||
			    (allow_both_pkeys == FALSE &&
			     cl_ntoh16(*p_prev_pkey) < cl_ntoh16(pkey)))
				cl_map_insert(&p_pkey_tbl->keys, pkey_base,
					      &(p_pkey_block->pkey_entry[i])
				    );
		}
	}
	return IB_SUCCESS;
}
Пример #4
0
/**********************************************************************
 * Make sure that the lid_port_tbl of the subnet has only the ports
 * that are recognized, and in the correct lid place. There could be
 * errors if we wanted to assign a certain port with lid X, but that
 * request didn't reach the port. In this case port_lid_tbl will have
 * the port under lid X, though the port isn't updated with this lid.
 * We will run a new heavy sweep (since there were errors in the
 * initialization), but here we'll clean the database from incorrect
 * information.
 **********************************************************************/
static void state_mgr_check_tbl_consistency(IN osm_sm_t * sm)
{
	cl_qmap_t *p_port_guid_tbl;
	osm_port_t *p_port;
	osm_port_t *p_next_port;
	cl_ptr_vector_t *p_port_lid_tbl;
	size_t max_lid, ref_size, curr_size, lid;
	osm_port_t *p_port_ref, *p_port_stored;
	cl_ptr_vector_t ref_port_lid_tbl;
	uint16_t min_lid_ho;
	uint16_t max_lid_ho;
	uint16_t lid_ho;

	OSM_LOG_ENTER(sm->p_log);

	cl_ptr_vector_construct(&ref_port_lid_tbl);
	cl_ptr_vector_init(&ref_port_lid_tbl,
			   cl_ptr_vector_get_size(&sm->p_subn->port_lid_tbl),
			   OSM_SUBNET_VECTOR_GROW_SIZE);

	p_port_guid_tbl = &sm->p_subn->port_guid_tbl;

	/* Let's go over all the ports according to port_guid_tbl,
	 * and add the port to a reference port_lid_tbl. */
	p_next_port = (osm_port_t *) cl_qmap_head(p_port_guid_tbl);
	while (p_next_port != (osm_port_t *) cl_qmap_end(p_port_guid_tbl)) {
		p_port = p_next_port;
		p_next_port =
		    (osm_port_t *) cl_qmap_next(&p_next_port->map_item);

		osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
		for (lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++)
			cl_ptr_vector_set(&ref_port_lid_tbl, lid_ho, p_port);
	}

	p_port_lid_tbl = &sm->p_subn->port_lid_tbl;

	ref_size = cl_ptr_vector_get_size(&ref_port_lid_tbl);
	curr_size = cl_ptr_vector_get_size(p_port_lid_tbl);
	/* They should be the same, but compare it anyway */
	max_lid = (ref_size > curr_size) ? ref_size : curr_size;

	for (lid = 1; lid < max_lid; lid++) {
		p_port_ref = NULL;
		p_port_stored = NULL;
		cl_ptr_vector_at(p_port_lid_tbl, lid, (void *)&p_port_stored);
		cl_ptr_vector_at(&ref_port_lid_tbl, lid, (void *)&p_port_ref);

		if (p_port_stored == p_port_ref)
			/* This is the "good" case - both entries are the
			 * same for this lid. Nothing to do. */
			continue;

		if (p_port_ref == NULL)
			/* There is an object in the subnet database for this
			 * lid, but no such object exists in the reference
			 * port_list_tbl. This can occur if we wanted to assign
			 * a certain port with some lid (different than the one
			 * pre-assigned to it), and the port didn't get the
			 * PortInfo Set request. Due to this, the port is
			 * updated with its original lid in our database, but
			 * with the new lid we wanted to give it in our
			 * port_lid_tbl. */
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3322: "
				"lid %zu is wrongly assigned to port 0x%016"
				PRIx64 " (\'%s\' port %u) in port_lid_tbl\n",
				lid,
				cl_ntoh64(osm_port_get_guid(p_port_stored)),
				p_port_stored->p_node->print_desc,
				p_port_stored->p_physp->port_num);
		else if (p_port_stored == NULL)
			/* There is an object in the new database, but no
			 * object in our subnet database. This is the matching
			 * case of the prior check - the port still has its
			 * original lid. */
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3323: "
				"port 0x%016" PRIx64 " (\'%s\' port %u)"
				" exists in new port_lid_tbl under lid %zu,"
				" but missing in subnet port_lid_tbl db\n",
				cl_ntoh64(osm_port_get_guid(p_port_ref)),
				p_port_ref->p_node->print_desc,
				p_port_ref->p_physp->port_num, lid);
		else
			/* if we reached here then p_port_stored != p_port_ref.
			 * We were trying to set a lid to p_port_stored, but
			 * it didn't reach it, and p_port_ref also didn't get
			 * the lid update. */
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3324: "
				"lid %zu has port 0x%016" PRIx64
				" (\'%s\' port %u) in new port_lid_tbl db, "
				"and port 0x%016" PRIx64 " (\'%s\' port %u)"
				" in subnet port_lid_tbl db\n", lid,
				cl_ntoh64(osm_port_get_guid(p_port_ref)),
				p_port_ref->p_node->print_desc,
				p_port_ref->p_physp->port_num,
				cl_ntoh64(osm_port_get_guid(p_port_stored)),
				p_port_ref->p_node->print_desc,
				p_port_ref->p_physp->port_num);

		/* In any of these cases we want to set NULL in the
		 * port_lid_tbl, since this entry is invalid. Also, make sure
		 * we'll do another heavy sweep. */
		cl_ptr_vector_set(p_port_lid_tbl, lid, NULL);
		sm->p_subn->subnet_initialization_error = TRUE;
	}

	cl_ptr_vector_destroy(&ref_port_lid_tbl);
	OSM_LOG_EXIT(sm->p_log);
}