|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
|
|
Packit |
13e616 |
* Copyright (c) 2002-2012 Mellanox Technologies LTD. All rights reserved.
|
|
Packit |
13e616 |
* Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* This software is available to you under a choice of one of two
|
|
Packit |
13e616 |
* licenses. You may choose to be licensed under the terms of the GNU
|
|
Packit |
13e616 |
* General Public License (GPL) Version 2, available from the file
|
|
Packit |
13e616 |
* COPYING in the main directory of this source tree, or the
|
|
Packit |
13e616 |
* OpenIB.org BSD license below:
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* Redistribution and use in source and binary forms, with or
|
|
Packit |
13e616 |
* without modification, are permitted provided that the following
|
|
Packit |
13e616 |
* conditions are met:
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* - Redistributions of source code must retain the above
|
|
Packit |
13e616 |
* copyright notice, this list of conditions and the following
|
|
Packit |
13e616 |
* disclaimer.
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* - Redistributions in binary form must reproduce the above
|
|
Packit |
13e616 |
* copyright notice, this list of conditions and the following
|
|
Packit |
13e616 |
* disclaimer in the documentation and/or other materials
|
|
Packit |
13e616 |
* provided with the distribution.
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
Packit |
13e616 |
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
Packit |
13e616 |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
Packit |
13e616 |
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
Packit |
13e616 |
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
Packit |
13e616 |
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
Packit |
13e616 |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
Packit |
13e616 |
* SOFTWARE.
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Abstract:
|
|
Packit |
13e616 |
* Implementation of opensm pkey manipulation functions.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
#if HAVE_CONFIG_H
|
|
Packit |
13e616 |
# include <config.h>
|
|
Packit |
13e616 |
#endif /* HAVE_CONFIG_H */
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
#include <stdlib.h>
|
|
Packit |
13e616 |
#include <stdio.h>
|
|
Packit |
13e616 |
#include <string.h>
|
|
Packit |
13e616 |
#include <complib/cl_debug.h>
|
|
Packit |
13e616 |
#include <iba/ib_types.h>
|
|
Packit |
13e616 |
#include <opensm/osm_file_ids.h>
|
|
Packit |
13e616 |
#define FILE_ID OSM_FILE_PKEY_C
|
|
Packit |
13e616 |
#include <opensm/osm_pkey.h>
|
|
Packit |
13e616 |
#include <opensm/osm_log.h>
|
|
Packit |
13e616 |
#include <opensm/osm_port.h>
|
|
Packit |
13e616 |
#include <opensm/osm_node.h>
|
|
Packit |
13e616 |
#include <opensm/osm_switch.h>
|
|
Packit |
13e616 |
#include <opensm/osm_helper.h>
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
void osm_pkey_tbl_construct(IN osm_pkey_tbl_t * p_pkey_tbl)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
cl_map_construct(&p_pkey_tbl->accum_pkeys);
|
|
Packit |
13e616 |
cl_ptr_vector_construct(&p_pkey_tbl->blocks);
|
|
Packit |
13e616 |
cl_ptr_vector_construct(&p_pkey_tbl->new_blocks);
|
|
Packit |
13e616 |
cl_map_construct(&p_pkey_tbl->keys);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
void osm_pkey_tbl_destroy(IN osm_pkey_tbl_t * p_pkey_tbl)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
ib_pkey_table_t *p_block;
|
|
Packit |
13e616 |
uint16_t num_blocks, i;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
num_blocks = (uint16_t) (cl_ptr_vector_get_size(&p_pkey_tbl->blocks));
|
|
Packit |
13e616 |
for (i = 0; i < num_blocks; i++)
|
|
Packit |
13e616 |
if ((p_block = cl_ptr_vector_get(&p_pkey_tbl->blocks, i)))
|
|
Packit |
13e616 |
free(p_block);
|
|
Packit |
13e616 |
cl_ptr_vector_destroy(&p_pkey_tbl->blocks);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
num_blocks =
|
|
Packit |
13e616 |
(uint16_t) (cl_ptr_vector_get_size(&p_pkey_tbl->new_blocks));
|
|
Packit |
13e616 |
for (i = 0; i < num_blocks; i++)
|
|
Packit |
13e616 |
if ((p_block = cl_ptr_vector_get(&p_pkey_tbl->new_blocks, i)))
|
|
Packit |
13e616 |
free(p_block);
|
|
Packit |
13e616 |
cl_ptr_vector_destroy(&p_pkey_tbl->new_blocks);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
cl_map_remove_all(&p_pkey_tbl->accum_pkeys);
|
|
Packit |
13e616 |
cl_map_destroy(&p_pkey_tbl->accum_pkeys);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
cl_map_remove_all(&p_pkey_tbl->keys);
|
|
Packit |
13e616 |
cl_map_destroy(&p_pkey_tbl->keys);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
ib_api_status_t osm_pkey_tbl_init(IN osm_pkey_tbl_t * p_pkey_tbl)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
cl_map_init(&p_pkey_tbl->accum_pkeys, 1);
|
|
Packit |
13e616 |
cl_ptr_vector_init(&p_pkey_tbl->blocks, 0, 1);
|
|
Packit |
13e616 |
cl_ptr_vector_init(&p_pkey_tbl->new_blocks, 0, 1);
|
|
Packit |
13e616 |
cl_map_init(&p_pkey_tbl->keys, 1);
|
|
Packit |
13e616 |
cl_qlist_init(&p_pkey_tbl->pending);
|
|
Packit |
13e616 |
p_pkey_tbl->last_pkey_idx = 0;
|
|
Packit |
13e616 |
p_pkey_tbl->used_blocks = 0;
|
|
Packit |
13e616 |
p_pkey_tbl->max_blocks = 0;
|
|
Packit |
13e616 |
p_pkey_tbl->rcv_blocks_cnt = 0;
|
|
Packit |
13e616 |
p_pkey_tbl->indx0_pkey = 0;
|
|
Packit |
13e616 |
return IB_SUCCESS;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
void osm_pkey_tbl_init_new_blocks(IN const osm_pkey_tbl_t * p_pkey_tbl)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
ib_pkey_table_t *p_block;
|
|
Packit |
13e616 |
size_t b, num_blocks = cl_ptr_vector_get_size(&p_pkey_tbl->new_blocks);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (b = 0; b < num_blocks; b++)
|
|
Packit |
13e616 |
if ((p_block = cl_ptr_vector_get(&p_pkey_tbl->new_blocks, b)))
|
|
Packit |
13e616 |
memset(p_block, 0, sizeof(*p_block));
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
ib_api_status_t osm_pkey_tbl_set(IN osm_pkey_tbl_t * p_pkey_tbl,
|
|
Packit |
13e616 |
IN uint16_t block, IN ib_pkey_table_t * p_tbl,
|
|
Packit |
13e616 |
IN boolean_t allow_both_pkeys)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
uint16_t b, i;
|
|
Packit |
13e616 |
ib_pkey_table_t *p_pkey_block;
|
|
Packit |
13e616 |
uint16_t *p_prev_pkey;
|
|
Packit |
13e616 |
ib_net16_t pkey, pkey_base;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* make sure the block is allocated */
|
|
Packit |
13e616 |
if (cl_ptr_vector_get_size(&p_pkey_tbl->blocks) > block)
|
|
Packit |
13e616 |
p_pkey_block =
|
|
Packit |
13e616 |
(ib_pkey_table_t *) cl_ptr_vector_get(&p_pkey_tbl->blocks,
|
|
Packit |
13e616 |
block);
|
|
Packit |
13e616 |
else
|
|
Packit |
13e616 |
p_pkey_block = NULL;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!p_pkey_block) {
|
|
Packit |
13e616 |
p_pkey_block =
|
|
Packit |
13e616 |
(ib_pkey_table_t *) malloc(sizeof(ib_pkey_table_t));
|
|
Packit |
13e616 |
if (!p_pkey_block)
|
|
Packit |
13e616 |
return IB_ERROR;
|
|
Packit |
13e616 |
memset(p_pkey_block, 0, sizeof(ib_pkey_table_t));
|
|
Packit |
13e616 |
cl_ptr_vector_set(&p_pkey_tbl->blocks, block, p_pkey_block);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* sets the block values */
|
|
Packit |
13e616 |
memcpy(p_pkey_block, p_tbl, sizeof(ib_pkey_table_t));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
NOTE: as the spec does not require uniqueness of PKeys in
|
|
Packit |
13e616 |
tables there is no other way but to refresh the entire keys map.
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
Moreover, if the same key exists but with full membership it should
|
|
Packit |
13e616 |
have precedence over the key with limited membership !
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
cl_map_remove_all(&p_pkey_tbl->keys);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (b = 0; b < cl_ptr_vector_get_size(&p_pkey_tbl->blocks); b++) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_pkey_block = cl_ptr_vector_get(&p_pkey_tbl->blocks, b);
|
|
Packit |
13e616 |
if (!p_pkey_block)
|
|
Packit |
13e616 |
continue;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (i = 0; i < IB_NUM_PKEY_ELEMENTS_IN_BLOCK; i++) {
|
|
Packit |
13e616 |
pkey = p_pkey_block->pkey_entry[i];
|
|
Packit |
13e616 |
if (ib_pkey_is_invalid(pkey))
|
|
Packit |
13e616 |
continue;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (allow_both_pkeys)
|
|
Packit |
13e616 |
pkey_base = pkey;
|
|
Packit |
13e616 |
else
|
|
Packit |
13e616 |
pkey_base = ib_pkey_get_base(pkey);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
If allow_both_pkeys is FALSE,
|
|
Packit |
13e616 |
ignore the PKey Full Member bit in the key but store
|
|
Packit |
13e616 |
the pointer to the table element as the map value
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
p_prev_pkey = cl_map_get(&p_pkey_tbl->keys, pkey_base);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* we only insert if no previous or it is not full member and allow_both_pkeys is FALSE */
|
|
Packit |
13e616 |
if ((p_prev_pkey == NULL) ||
|
|
Packit |
13e616 |
(allow_both_pkeys == FALSE &&
|
|
Packit |
13e616 |
cl_ntoh16(*p_prev_pkey) < cl_ntoh16(pkey)))
|
|
Packit |
13e616 |
cl_map_insert(&p_pkey_tbl->keys, pkey_base,
|
|
Packit |
13e616 |
&(p_pkey_block->pkey_entry[i])
|
|
Packit |
13e616 |
);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
return IB_SUCCESS;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
Store the given pkey (along with it's overall index) in the accum_pkeys array.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
cl_status_t osm_pkey_tbl_set_accum_pkeys(IN osm_pkey_tbl_t * p_pkey_tbl,
|
|
Packit |
13e616 |
IN uint16_t pkey,
|
|
Packit |
13e616 |
IN uint16_t pkey_idx)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
uintptr_t ptr = pkey_idx + 1; /* 0 means not found so bias by 1 */
|
|
Packit |
13e616 |
uint16_t *p_prev_pkey_idx;
|
|
Packit |
13e616 |
cl_status_t status = CL_SUCCESS;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (pkey_idx >= p_pkey_tbl->last_pkey_idx)
|
|
Packit |
13e616 |
p_pkey_tbl->last_pkey_idx = pkey_idx + 1;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_prev_pkey_idx = (uint16_t *) cl_map_get(&p_pkey_tbl->accum_pkeys, pkey);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (p_prev_pkey_idx != NULL)
|
|
Packit |
13e616 |
cl_map_remove(&p_pkey_tbl->accum_pkeys, pkey);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (cl_map_insert(&p_pkey_tbl->accum_pkeys, pkey, (void *) ptr) == NULL)
|
|
Packit |
13e616 |
status = CL_INSUFFICIENT_MEMORY;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
return status;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
+ * Find the next last pkey index
|
|
Packit |
13e616 |
+*/
|
|
Packit |
13e616 |
void osm_pkey_find_last_accum_pkey_index(IN osm_pkey_tbl_t * p_pkey_tbl)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
void *ptr;
|
|
Packit |
13e616 |
uintptr_t pkey_idx_ptr;
|
|
Packit |
13e616 |
uint16_t pkey_idx, last_pkey_idx = 0;
|
|
Packit |
13e616 |
cl_map_iterator_t map_iter = cl_map_head(&p_pkey_tbl->accum_pkeys);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
while (map_iter != cl_map_end(&p_pkey_tbl->accum_pkeys)) {
|
|
Packit |
13e616 |
ptr = (uint16_t *) cl_map_obj(map_iter);
|
|
Packit |
13e616 |
CL_ASSERT(ptr);
|
|
Packit |
13e616 |
pkey_idx_ptr = (uintptr_t) ptr;
|
|
Packit |
13e616 |
pkey_idx = pkey_idx_ptr;
|
|
Packit |
13e616 |
if (pkey_idx > last_pkey_idx)
|
|
Packit |
13e616 |
last_pkey_idx = pkey_idx;
|
|
Packit |
13e616 |
map_iter = cl_map_next(map_iter);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
p_pkey_tbl->last_pkey_idx = last_pkey_idx;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
Store the given pkey in the "new" blocks array.
|
|
Packit |
13e616 |
Also, make sure the regular block exists.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
ib_api_status_t osm_pkey_tbl_set_new_entry(IN osm_pkey_tbl_t * p_pkey_tbl,
|
|
Packit |
13e616 |
IN uint16_t block_idx,
|
|
Packit |
13e616 |
IN uint8_t pkey_idx,
|
|
Packit |
13e616 |
IN uint16_t pkey)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
ib_pkey_table_t *p_block;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!(p_block = osm_pkey_tbl_new_block_get(p_pkey_tbl, block_idx))) {
|
|
Packit |
13e616 |
p_block = (ib_pkey_table_t *) malloc(sizeof(ib_pkey_table_t));
|
|
Packit |
13e616 |
if (!p_block)
|
|
Packit |
13e616 |
return IB_ERROR;
|
|
Packit |
13e616 |
memset(p_block, 0, sizeof(ib_pkey_table_t));
|
|
Packit |
13e616 |
cl_ptr_vector_set(&p_pkey_tbl->new_blocks, block_idx, p_block);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_block->pkey_entry[pkey_idx] = pkey;
|
|
Packit |
13e616 |
if (p_pkey_tbl->used_blocks <= block_idx)
|
|
Packit |
13e616 |
p_pkey_tbl->used_blocks = block_idx + 1;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
return IB_SUCCESS;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
boolean_t osm_pkey_find_next_free_entry(IN osm_pkey_tbl_t * p_pkey_tbl,
|
|
Packit |
13e616 |
OUT uint16_t * p_block_idx,
|
|
Packit |
13e616 |
OUT uint8_t * p_pkey_idx)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
ib_pkey_table_t *p_new_block;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(p_block_idx);
|
|
Packit |
13e616 |
CL_ASSERT(p_pkey_idx);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
while (*p_block_idx < p_pkey_tbl->max_blocks) {
|
|
Packit |
13e616 |
if (*p_pkey_idx > IB_NUM_PKEY_ELEMENTS_IN_BLOCK - 1) {
|
|
Packit |
13e616 |
*p_pkey_idx = 0;
|
|
Packit |
13e616 |
(*p_block_idx)++;
|
|
Packit |
13e616 |
if (*p_block_idx >= p_pkey_tbl->max_blocks)
|
|
Packit |
13e616 |
return FALSE;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_new_block =
|
|
Packit |
13e616 |
osm_pkey_tbl_new_block_get(p_pkey_tbl, *p_block_idx);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!p_new_block ||
|
|
Packit |
13e616 |
ib_pkey_is_invalid(p_new_block->pkey_entry[*p_pkey_idx]))
|
|
Packit |
13e616 |
return TRUE;
|
|
Packit |
13e616 |
else
|
|
Packit |
13e616 |
(*p_pkey_idx)++;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
return FALSE;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
ib_api_status_t osm_pkey_tbl_get_block_and_idx(IN osm_pkey_tbl_t * p_pkey_tbl,
|
|
Packit |
13e616 |
IN uint16_t * p_pkey,
|
|
Packit |
13e616 |
OUT uint16_t * p_block_idx,
|
|
Packit |
13e616 |
OUT uint8_t * p_pkey_idx)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
uint16_t num_of_blocks;
|
|
Packit |
13e616 |
uint16_t block_index;
|
|
Packit |
13e616 |
ib_pkey_table_t *block;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(p_block_idx != NULL);
|
|
Packit |
13e616 |
CL_ASSERT(p_pkey_idx != NULL);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
num_of_blocks = (uint16_t) cl_ptr_vector_get_size(&p_pkey_tbl->blocks);
|
|
Packit |
13e616 |
for (block_index = 0; block_index < num_of_blocks; block_index++) {
|
|
Packit |
13e616 |
block = osm_pkey_tbl_block_get(p_pkey_tbl, block_index);
|
|
Packit |
13e616 |
if ((block->pkey_entry <= p_pkey) &&
|
|
Packit |
13e616 |
(p_pkey <
|
|
Packit |
13e616 |
block->pkey_entry + IB_NUM_PKEY_ELEMENTS_IN_BLOCK)) {
|
|
Packit |
13e616 |
*p_block_idx = block_index;
|
|
Packit |
13e616 |
*p_pkey_idx = (uint8_t) (p_pkey - block->pkey_entry);
|
|
Packit |
13e616 |
return IB_SUCCESS;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
return IB_NOT_FOUND;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static boolean_t match_pkey(IN const ib_net16_t * pkey1,
|
|
Packit |
13e616 |
IN const ib_net16_t * pkey2)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* if neither pkey is full member - this is not a match */
|
|
Packit |
13e616 |
if (!(ib_pkey_is_full_member(*pkey1) || ib_pkey_is_full_member(*pkey2)))
|
|
Packit |
13e616 |
return FALSE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* compare if the bases are the same. if they are - then
|
|
Packit |
13e616 |
this is a match */
|
|
Packit |
13e616 |
if (ib_pkey_get_base(*pkey1) != ib_pkey_get_base(*pkey2))
|
|
Packit |
13e616 |
return FALSE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
return TRUE;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
boolean_t osm_physp_share_this_pkey(IN const osm_physp_t * p_physp1,
|
|
Packit |
13e616 |
IN const osm_physp_t * p_physp2,
|
|
Packit |
13e616 |
IN ib_net16_t pkey,
|
|
Packit |
13e616 |
IN boolean_t allow_both_pkeys)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
ib_net16_t *pkey1, *pkey2;
|
|
Packit |
13e616 |
ib_net16_t full_pkey, limited_pkey;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (allow_both_pkeys) {
|
|
Packit |
13e616 |
full_pkey = pkey | IB_PKEY_TYPE_MASK;
|
|
Packit |
13e616 |
limited_pkey = pkey & ~IB_PKEY_TYPE_MASK;
|
|
Packit |
13e616 |
pkey1 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp1))->keys,
|
|
Packit |
13e616 |
full_pkey);
|
|
Packit |
13e616 |
if (!pkey1)
|
|
Packit |
13e616 |
pkey1 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp1))->keys,
|
|
Packit |
13e616 |
limited_pkey);
|
|
Packit |
13e616 |
pkey2 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp2))->keys,
|
|
Packit |
13e616 |
full_pkey);
|
|
Packit |
13e616 |
if (!pkey2)
|
|
Packit |
13e616 |
pkey2 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp2))->keys,
|
|
Packit |
13e616 |
limited_pkey);
|
|
Packit |
13e616 |
} else {
|
|
Packit |
13e616 |
pkey1 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp1))->keys,
|
|
Packit |
13e616 |
ib_pkey_get_base(pkey));
|
|
Packit |
13e616 |
pkey2 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp2))->keys,
|
|
Packit |
13e616 |
ib_pkey_get_base(pkey));
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
return (pkey1 && pkey2 && match_pkey(pkey1, pkey2));
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
ib_net16_t osm_physp_find_common_pkey(IN const osm_physp_t * p_physp1,
|
|
Packit |
13e616 |
IN const osm_physp_t * p_physp2,
|
|
Packit |
13e616 |
IN boolean_t allow_both_pkeys)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
ib_net16_t *pkey1, *pkey2;
|
|
Packit |
13e616 |
uint64_t pkey1_base, pkey2_base;
|
|
Packit |
13e616 |
const osm_pkey_tbl_t *pkey_tbl1, *pkey_tbl2;
|
|
Packit |
13e616 |
cl_map_iterator_t map_iter1, map_iter2;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
pkey_tbl1 = osm_physp_get_pkey_tbl(p_physp1);
|
|
Packit |
13e616 |
pkey_tbl2 = osm_physp_get_pkey_tbl(p_physp2);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
map_iter1 = cl_map_head(&pkey_tbl1->keys);
|
|
Packit |
13e616 |
map_iter2 = cl_map_head(&pkey_tbl2->keys);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* we rely on the fact the map are sorted by pkey */
|
|
Packit |
13e616 |
while ((map_iter1 != cl_map_end(&pkey_tbl1->keys)) &&
|
|
Packit |
13e616 |
(map_iter2 != cl_map_end(&pkey_tbl2->keys))) {
|
|
Packit |
13e616 |
pkey1 = (ib_net16_t *) cl_map_obj(map_iter1);
|
|
Packit |
13e616 |
pkey2 = (ib_net16_t *) cl_map_obj(map_iter2);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (match_pkey(pkey1, pkey2))
|
|
Packit |
13e616 |
return *pkey1;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* advance the lower value if they are not equal */
|
|
Packit |
13e616 |
pkey1_base = cl_map_key(map_iter1);
|
|
Packit |
13e616 |
pkey2_base = cl_map_key(map_iter2);
|
|
Packit |
13e616 |
if (pkey2_base == pkey1_base) {
|
|
Packit |
13e616 |
map_iter1 = cl_map_next(map_iter1);
|
|
Packit |
13e616 |
map_iter2 = cl_map_next(map_iter2);
|
|
Packit |
13e616 |
} else if (pkey2_base < pkey1_base)
|
|
Packit |
13e616 |
map_iter2 = cl_map_next(map_iter2);
|
|
Packit |
13e616 |
else
|
|
Packit |
13e616 |
map_iter1 = cl_map_next(map_iter1);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!allow_both_pkeys)
|
|
Packit |
13e616 |
return 0;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
When using allow_both_pkeys, the keys in pkey tables are the
|
|
Packit |
13e616 |
pkey value including membership bit.
|
|
Packit |
13e616 |
Therefore, in order to complete the search, we also need to
|
|
Packit |
13e616 |
compare port\s 1 full pkeys with port 2 limited pkeys, and
|
|
Packit |
13e616 |
port 2 full pkeys with port 1 full pkeys.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
map_iter1 = cl_map_head(&pkey_tbl1->keys);
|
|
Packit |
13e616 |
map_iter2 = cl_map_head(&pkey_tbl2->keys);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* comparing pkey_tbl1 full with pkey_tbl2 limited */
|
|
Packit |
13e616 |
while ((map_iter1 != cl_map_end(&pkey_tbl1->keys)) &&
|
|
Packit |
13e616 |
(map_iter2 != cl_map_end(&pkey_tbl2->keys))) {
|
|
Packit |
13e616 |
pkey1 = (ib_net16_t *) cl_map_obj(map_iter1);
|
|
Packit |
13e616 |
pkey2 = (ib_net16_t *) cl_map_obj(map_iter2);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!ib_pkey_is_full_member(*pkey1)) {
|
|
Packit |
13e616 |
map_iter1 = cl_map_next(map_iter1);
|
|
Packit |
13e616 |
continue;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
if (ib_pkey_is_full_member(*pkey2)) {
|
|
Packit |
13e616 |
map_iter2 = cl_map_next(map_iter2);
|
|
Packit |
13e616 |
continue;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (match_pkey(pkey1, pkey2))
|
|
Packit |
13e616 |
return *pkey1;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* advance the lower value if they are not equal */
|
|
Packit |
13e616 |
pkey1_base = ib_pkey_get_base(cl_map_key(map_iter1));
|
|
Packit |
13e616 |
pkey2_base = ib_pkey_get_base(cl_map_key(map_iter2));
|
|
Packit |
13e616 |
if (pkey2_base == pkey1_base) {
|
|
Packit |
13e616 |
map_iter1 = cl_map_next(map_iter1);
|
|
Packit |
13e616 |
map_iter2 = cl_map_next(map_iter2);
|
|
Packit |
13e616 |
} else if (pkey2_base < pkey1_base)
|
|
Packit |
13e616 |
map_iter2 = cl_map_next(map_iter2);
|
|
Packit |
13e616 |
else
|
|
Packit |
13e616 |
map_iter1 = cl_map_next(map_iter1);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
map_iter1 = cl_map_head(&pkey_tbl1->keys);
|
|
Packit |
13e616 |
map_iter2 = cl_map_head(&pkey_tbl2->keys);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* comparing pkey_tbl1 limited with pkey_tbl2 full */
|
|
Packit |
13e616 |
while ((map_iter1 != cl_map_end(&pkey_tbl1->keys)) &&
|
|
Packit |
13e616 |
(map_iter2 != cl_map_end(&pkey_tbl2->keys))) {
|
|
Packit |
13e616 |
pkey1 = (ib_net16_t *) cl_map_obj(map_iter1);
|
|
Packit |
13e616 |
pkey2 = (ib_net16_t *) cl_map_obj(map_iter2);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (ib_pkey_is_full_member(*pkey1)) {
|
|
Packit |
13e616 |
map_iter1 = cl_map_next(map_iter1);
|
|
Packit |
13e616 |
continue;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
if (!ib_pkey_is_full_member(*pkey2)) {
|
|
Packit |
13e616 |
map_iter2 = cl_map_next(map_iter2);
|
|
Packit |
13e616 |
continue;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (match_pkey(pkey1, pkey2))
|
|
Packit |
13e616 |
return *pkey1;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* advance the lower value if they are not equal */
|
|
Packit |
13e616 |
pkey1_base = ib_pkey_get_base(cl_map_key(map_iter1));
|
|
Packit |
13e616 |
pkey2_base = ib_pkey_get_base(cl_map_key(map_iter2));
|
|
Packit |
13e616 |
if (pkey2_base == pkey1_base) {
|
|
Packit |
13e616 |
map_iter1 = cl_map_next(map_iter1);
|
|
Packit |
13e616 |
map_iter2 = cl_map_next(map_iter2);
|
|
Packit |
13e616 |
} else if (pkey2_base < pkey1_base)
|
|
Packit |
13e616 |
map_iter2 = cl_map_next(map_iter2);
|
|
Packit |
13e616 |
else
|
|
Packit |
13e616 |
map_iter1 = cl_map_next(map_iter1);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
return 0;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
boolean_t osm_physp_share_pkey(IN osm_log_t * p_log,
|
|
Packit |
13e616 |
IN const osm_physp_t * p_physp_1,
|
|
Packit |
13e616 |
IN const osm_physp_t * p_physp_2,
|
|
Packit |
13e616 |
IN boolean_t allow_both_pkeys)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
const osm_pkey_tbl_t *pkey_tbl1, *pkey_tbl2;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (p_physp_1 == p_physp_2)
|
|
Packit |
13e616 |
return TRUE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
pkey_tbl1 = osm_physp_get_pkey_tbl(p_physp_1);
|
|
Packit |
13e616 |
pkey_tbl2 = osm_physp_get_pkey_tbl(p_physp_2);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
The spec: 10.9.2 does not require each phys port to have PKey Table.
|
|
Packit |
13e616 |
So actually if it does not, we need to use the default port instead.
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
HACK: meanwhile we will ignore the check
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if (cl_is_map_empty(&pkey_tbl1->keys)
|
|
Packit |
13e616 |
|| cl_is_map_empty(&pkey_tbl2->keys))
|
|
Packit |
13e616 |
return TRUE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
return
|
|
Packit |
13e616 |
!ib_pkey_is_invalid(osm_physp_find_common_pkey
|
|
Packit |
13e616 |
(p_physp_1, p_physp_2, allow_both_pkeys));
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
boolean_t osm_port_share_pkey(IN osm_log_t * p_log,
|
|
Packit |
13e616 |
IN const osm_port_t * p_port_1,
|
|
Packit |
13e616 |
IN const osm_port_t * p_port_2,
|
|
Packit |
13e616 |
IN boolean_t allow_both_pkeys)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_physp_t *p_physp1, *p_physp2;
|
|
Packit |
13e616 |
boolean_t ret;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!p_port_1 || !p_port_2) {
|
|
Packit |
13e616 |
ret = FALSE;
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_physp1 = p_port_1->p_physp;
|
|
Packit |
13e616 |
p_physp2 = p_port_2->p_physp;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!p_physp1 || !p_physp2) {
|
|
Packit |
13e616 |
ret = FALSE;
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
ret = osm_physp_share_pkey(p_log, p_physp1, p_physp2, allow_both_pkeys);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
Exit:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(p_log);
|
|
Packit |
13e616 |
return ret;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
boolean_t osm_physp_has_pkey(IN osm_log_t * p_log, IN ib_net16_t pkey,
|
|
Packit |
13e616 |
IN const osm_physp_t * p_physp)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
ib_net16_t *p_pkey, pkey_base;
|
|
Packit |
13e616 |
const osm_pkey_tbl_t *pkey_tbl;
|
|
Packit |
13e616 |
boolean_t res = FALSE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Search for PKey: 0x%04x\n", cl_ntoh16(pkey));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* if the pkey given is an invalid pkey - return TRUE. */
|
|
Packit |
13e616 |
if (ib_pkey_is_invalid(pkey)) {
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Given invalid PKey - we treat it loosely and allow it\n");
|
|
Packit |
13e616 |
res = TRUE;
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
pkey_base = ib_pkey_get_base(pkey);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
pkey_tbl = osm_physp_get_pkey_tbl(p_physp);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_pkey = cl_map_get(&pkey_tbl->keys, pkey_base);
|
|
Packit |
13e616 |
if (p_pkey) {
|
|
Packit |
13e616 |
res = TRUE;
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"PKey 0x%04x was found\n", cl_ntoh16(pkey));
|
|
Packit |
13e616 |
} else
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"PKey 0x%04x was not found\n", cl_ntoh16(pkey));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
Exit:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(p_log);
|
|
Packit |
13e616 |
return res;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
void osm_pkey_tbl_set_indx0_pkey(IN osm_log_t * p_log, IN ib_net16_t pkey,
|
|
Packit |
13e616 |
IN boolean_t full,
|
|
Packit |
13e616 |
OUT osm_pkey_tbl_t * p_pkey_tbl)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
p_pkey_tbl->indx0_pkey = (full == TRUE) ?
|
|
Packit |
13e616 |
pkey | cl_hton16(0x8000) : pkey;
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_DEBUG, "pkey 0x%04x set at indx0\n",
|
|
Packit |
13e616 |
cl_ntoh16(p_pkey_tbl->indx0_pkey));
|
|
Packit |
13e616 |
}
|