Hi Hal This is a 5th take after incorporating Sasha's last reported bug on bad assignment of the used_blocks.
This code was run again through my verification flow and also Sasha had run some tests too. Eitan Signed-off-by: Eitan Zahavi <[EMAIL PROTECTED]> Index: include/opensm/osm_port.h =================================================================== --- include/opensm/osm_port.h (revision 8113) +++ include/opensm/osm_port.h (working copy) @@ -591,6 +591,39 @@ osm_physp_get_pkey_tbl( IN const osm_phy * Port, Physical Port *********/ +/****f* OpenSM: Physical Port/osm_physp_get_mod_pkey_tbl +* NAME +* osm_physp_get_mod_pkey_tbl +* +* DESCRIPTION +* Returns a NON CONST pointer to the P_Key table object of the Physical Port object. +* +* SYNOPSIS +*/ +static inline osm_pkey_tbl_t * +osm_physp_get_mod_pkey_tbl( IN osm_physp_t* const p_physp ) +{ + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + /* + (14.2.5.7) - the block number valid values are 0-2047, and are further + limited by the size of the P_Key table specified by the PartitionCap on the node. + */ + return( &p_physp->pkeys ); +}; +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* RETURN VALUES +* The pointer to the P_Key table object. +* +* NOTES +* +* SEE ALSO +* Port, Physical Port +*********/ + /****f* OpenSM: Physical Port/osm_physp_set_slvl_tbl * NAME * osm_physp_set_slvl_tbl Index: include/opensm/osm_pkey.h =================================================================== --- include/opensm/osm_pkey.h (revision 8113) +++ include/opensm/osm_pkey.h (working copy) @@ -92,6 +92,9 @@ typedef struct _osm_pkey_tbl cl_ptr_vector_t blocks; cl_ptr_vector_t new_blocks; cl_map_t keys; + cl_qlist_t pending; + uint16_t used_blocks; + uint16_t max_blocks; } osm_pkey_tbl_t; /* * FIELDS @@ -104,6 +107,18 @@ typedef struct _osm_pkey_tbl * keys * A set holding all keys * +* pending +* A list osm_pending_pkey structs that is temporarily set by the +* pkey mgr and used during pkey mgr algorithm only +* +* used_blocks +* Tracks the number of blocks having non-zero pkeys +* +* max_blocks +* The maximal number of blocks this partition table might hold +* this value is based on node_info (for port 0 or CA) or switch_info +* updated on receiving the node_info or switch_info GetResp +* * NOTES * 'blocks' vector should be used to store pkey values obtained from * the port and SM pkey manager should not change it directly, for this @@ -114,6 +129,39 @@ typedef struct _osm_pkey_tbl * *********/ +/****s* OpenSM: osm_pending_pkey_t +* NAME +* osm_pending_pkey_t +* +* DESCRIPTION +* This objects stores temporary information on pkeys their target block and index +* during the pkey manager operation +* +* SYNOPSIS +*/ +typedef struct _osm_pending_pkey { + cl_list_item_t list_item; + uint16_t pkey; + uint32_t block; + uint8_t index; + boolean_t is_new; +} osm_pending_pkey_t; +/* +* FIELDS +* pkey +* The actual P_Key +* +* block +* The block index based on the previous table extracted from the device +* +* index +* The index of the pky within the block +* +* is_new +* TRUE for new P_Keys such that the block and index are invalid in that case +* +*********/ + /****f* OpenSM: osm_pkey_tbl_construct * NAME * osm_pkey_tbl_construct @@ -142,7 +190,8 @@ void osm_pkey_tbl_construct( * * SYNOPSIS */ -int osm_pkey_tbl_init( +ib_api_status_t +osm_pkey_tbl_init( IN osm_pkey_tbl_t *p_pkey_tbl); /* * p_pkey_tbl @@ -209,8 +258,8 @@ osm_pkey_tbl_get_num_blocks( static inline ib_pkey_table_t *osm_pkey_tbl_block_get( const osm_pkey_tbl_t *p_pkey_tbl, uint16_t block) { - CL_ASSERT(block < cl_ptr_vector_get_size(&p_pkey_tbl->blocks)); - return(cl_ptr_vector_get(&p_pkey_tbl->blocks, block)); + return( (block < cl_ptr_vector_get_size(&p_pkey_tbl->blocks)) ? + cl_ptr_vector_get(&p_pkey_tbl->blocks, block) : NULL); }; /* * p_pkey_tbl @@ -244,16 +293,117 @@ static inline ib_pkey_table_t *osm_pkey_ /* *********/ -/****f* OpenSM: osm_pkey_tbl_sync_new_blocks + +/****f* OpenSM: osm_pkey_tbl_make_block_pair +* NAME +* osm_pkey_tbl_make_block_pair +* +* DESCRIPTION +* Find or create a pair of "old" and "new" blocks for the +* given block index +* +* SYNOPSIS +*/ +ib_api_status_t +osm_pkey_tbl_make_block_pair( + osm_pkey_tbl_t *p_pkey_tbl, + uint16_t block_idx, + ib_pkey_table_t **pp_old_block, + ib_pkey_table_t **pp_new_block); +/* +* p_pkey_tbl +* [in] Pointer to the PKey table +* +* block_idx +* [in] The block index to use +* +* pp_old_block +* [out] Pointer to the old block pointer arg +* +* pp_new_block +* [out] Pointer to the new block pointer arg +* +* RETURN VALUES +* IB_SUCCESS if OK IB_ERROR if failed +* +*********/ + +/****f* OpenSM: osm_pkey_tbl_set_new_entry * NAME -* osm_pkey_tbl_sync_new_blocks +* osm_pkey_tbl_set_new_entry * * DESCRIPTION -* Syncs new_blocks vector content with current pkey table blocks +* stores the given pkey in the "new" blocks array and update +* the "map" to show that on the "old" blocks * * SYNOPSIS */ -void osm_pkey_tbl_sync_new_blocks( +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); +/* +* p_pkey_tbl +* [in] Pointer to the PKey table +* +* block_idx +* [in] The block index to use +* +* pkey_idx +* [in] The index within the block +* +* pkey +* [in] PKey to store +* +* RETURN VALUES +* IB_SUCCESS if OK IB_ERROR if failed +* +*********/ + +/****f* OpenSM: osm_pkey_find_next_free_entry +* NAME +* osm_pkey_find_next_free_entry +* +* DESCRIPTION +* Find the next free entry in the PKey table. Starting at the given +* index and block number. The user should increment pkey_idx before +* next call +* Inspect the "new" blocks array for empty space. +* +* SYNOPSIS +*/ +boolean_t +osm_pkey_find_next_free_entry( + IN osm_pkey_tbl_t *p_pkey_tbl, + OUT uint16_t *p_block_idx, + OUT uint8_t *p_pkey_idx); +/* +* p_pkey_tbl +* [in] Pointer to the PKey table +* +* p_block_idx +* [out] The block index to use +* +* p_pkey_idx +* [out] The index within the block to use +* +* RETURN VALUES +* TRUE if found FALSE if did not find +* +*********/ + +/****f* OpenSM: osm_pkey_tbl_init_new_blocks +* NAME +* osm_pkey_tbl_init_new_blocks +* +* DESCRIPTION +* Initializes new_blocks vector content (clear and allocate) +* +* SYNOPSIS +*/ +void osm_pkey_tbl_init_new_blocks( const osm_pkey_tbl_t *p_pkey_tbl); /* * p_pkey_tbl @@ -263,6 +413,41 @@ void osm_pkey_tbl_sync_new_blocks( * *********/ +/****f* OpenSM: osm_pkey_tbl_get_block_and_idx +* NAME +* osm_pkey_tbl_get_block_and_idx +* +* DESCRIPTION +* set the block index and pkey index the given +* pkey is found in. return IB_NOT_FOUND if cound not find +* it, IB_SUCCESS if OK +* +* SYNOPSIS +*/ +ib_api_status_t +osm_pkey_tbl_get_block_and_idx( + IN osm_pkey_tbl_t *p_pkey_tbl, + IN uint16_t *p_pkey, + OUT uint32_t *block_idx, + OUT uint8_t *pkey_index); +/* +* p_pkey_tbl +* [in] Pointer to osm_pkey_tbl_t object. +* +* p_pkey +* [in] Pointer to the P_Key entry searched +* +* p_block_idx +* [out] Pointer to the block index to be updated +* +* p_pkey_idx +* [out] Pointer to the pkey index (in the block) to be updated +* +* +* NOTES +* +*********/ + /****f* OpenSM: osm_pkey_tbl_set * NAME * osm_pkey_tbl_set @@ -272,7 +457,8 @@ void osm_pkey_tbl_sync_new_blocks( * * SYNOPSIS */ -int osm_pkey_tbl_set( +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); Index: opensm/osm_pkey.c =================================================================== --- opensm/osm_pkey.c (revision 8113) +++ opensm/osm_pkey.c (working copy) @@ -94,18 +94,22 @@ void osm_pkey_tbl_destroy( /********************************************************************** **********************************************************************/ -int osm_pkey_tbl_init( +ib_api_status_t +osm_pkey_tbl_init( IN osm_pkey_tbl_t *p_pkey_tbl) { cl_ptr_vector_init( &p_pkey_tbl->blocks, 0, 1); cl_ptr_vector_init( &p_pkey_tbl->new_blocks, 0, 1); cl_map_init( &p_pkey_tbl->keys, 1 ); + cl_qlist_init( &p_pkey_tbl->pending ); + p_pkey_tbl->used_blocks = 0; + p_pkey_tbl->max_blocks = 0; return(IB_SUCCESS); } /********************************************************************** **********************************************************************/ -void osm_pkey_tbl_sync_new_blocks( +void osm_pkey_tbl_init_new_blocks( IN const osm_pkey_tbl_t *p_pkey_tbl) { ib_pkey_table_t *p_block, *p_new_block; @@ -123,16 +127,31 @@ void osm_pkey_tbl_sync_new_blocks( p_new_block = (ib_pkey_table_t *)malloc(sizeof(*p_new_block)); if (!p_new_block) break; + cl_ptr_vector_set(&((osm_pkey_tbl_t *)p_pkey_tbl)->new_blocks, + b, p_new_block); + } + memset(p_new_block, 0, sizeof(*p_new_block)); - cl_ptr_vector_set(&((osm_pkey_tbl_t *)p_pkey_tbl)->new_blocks, b, p_new_block); } - memcpy(p_new_block, p_block, sizeof(*p_new_block)); +} + +/********************************************************************** + **********************************************************************/ +void osm_pkey_tbl_cleanup_pending( + IN osm_pkey_tbl_t *p_pkey_tbl) +{ + cl_list_item_t *p_item; + p_item = cl_qlist_remove_head( &p_pkey_tbl->pending ); + while (p_item != cl_qlist_end( &p_pkey_tbl->pending ) ) + { + free( (osm_pending_pkey_t *)p_item ); } } /********************************************************************** **********************************************************************/ -int osm_pkey_tbl_set( +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) @@ -203,7 +222,138 @@ int osm_pkey_tbl_set( /********************************************************************** **********************************************************************/ -static boolean_t __osm_match_pkey ( +ib_api_status_t +osm_pkey_tbl_make_block_pair( + osm_pkey_tbl_t *p_pkey_tbl, + uint16_t block_idx, + ib_pkey_table_t **pp_old_block, + ib_pkey_table_t **pp_new_block) +{ + if (block_idx >= p_pkey_tbl->max_blocks) return(IB_ERROR); + + if (pp_old_block) + { + *pp_old_block = osm_pkey_tbl_block_get( p_pkey_tbl, block_idx ); + if (! *pp_old_block) + { + *pp_old_block = (ib_pkey_table_t *)malloc(sizeof(ib_pkey_table_t)); + if (!*pp_old_block) return(IB_ERROR); + memset(*pp_old_block, 0, sizeof(ib_pkey_table_t)); + cl_ptr_vector_set(&p_pkey_tbl->blocks, block_idx, *pp_old_block); + } + } + + if (pp_new_block) + { + *pp_new_block = osm_pkey_tbl_new_block_get( p_pkey_tbl, block_idx ); + if (! *pp_new_block) + { + *pp_new_block = (ib_pkey_table_t *)malloc(sizeof(ib_pkey_table_t)); + if (!*pp_new_block) return(IB_ERROR); + memset(*pp_new_block, 0, sizeof(ib_pkey_table_t)); + cl_ptr_vector_set(&p_pkey_tbl->new_blocks, block_idx, *pp_new_block); + } + } + return( IB_SUCCESS ); +} + +/********************************************************************** + **********************************************************************/ +/* + store the given pkey in the "new" blocks array + also makes 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_old_block; + ib_pkey_table_t *p_new_block; + + if (osm_pkey_tbl_make_block_pair( + p_pkey_tbl, block_idx, &p_old_block, &p_new_block)) + return( IB_ERROR ); + + p_new_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 ); +} + +/********************************************************************** + **********************************************************************/ +boolean_t +osm_pkey_find_next_free_entry( + IN osm_pkey_tbl_t *p_pkey_tbl, + OUT uint16_t *p_block_idx, + OUT uint8_t *p_pkey_idx) +{ + ib_pkey_table_t *p_new_block; + + CL_ASSERT(p_block_idx); + CL_ASSERT(p_pkey_idx); + + while ( *p_block_idx < p_pkey_tbl->max_blocks) + { + if (*p_pkey_idx > IB_NUM_PKEY_ELEMENTS_IN_BLOCK - 1) + { + *p_pkey_idx = 0; + (*p_block_idx)++; + if (*p_block_idx >= p_pkey_tbl->max_blocks) + return FALSE; + } + + p_new_block = osm_pkey_tbl_new_block_get( p_pkey_tbl, *p_block_idx); + + if ( !p_new_block || + ib_pkey_is_invalid(p_new_block->pkey_entry[*p_pkey_idx])) + return TRUE; + else + (*p_pkey_idx)++; + } + return FALSE; +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_pkey_tbl_get_block_and_idx( + IN osm_pkey_tbl_t *p_pkey_tbl, + IN uint16_t *p_pkey, + OUT uint32_t *p_block_idx, + OUT uint8_t *p_pkey_index) +{ + uint32_t num_of_blocks; + uint32_t block_index; + ib_pkey_table_t *block; + + CL_ASSERT( p_pkey_tbl ); + CL_ASSERT( p_block_idx != NULL ); + CL_ASSERT( p_pkey_idx != NULL ); + + num_of_blocks = cl_ptr_vector_get_size( &p_pkey_tbl->blocks); + for ( block_index = 0; block_index < num_of_blocks; block_index++ ) + { + block = osm_pkey_tbl_block_get( p_pkey_tbl, block_index ); + if ( ( block->pkey_entry <= p_pkey ) && + ( p_pkey < block->pkey_entry + IB_NUM_PKEY_ELEMENTS_IN_BLOCK)) + { + *p_block_idx = block_index; + *p_pkey_index = p_pkey - block->pkey_entry; + return( IB_SUCCESS ); + } + } + return( IB_NOT_FOUND ); +} + +/********************************************************************** + **********************************************************************/ +static boolean_t +__osm_match_pkey ( IN const ib_net16_t *pkey1, IN const ib_net16_t *pkey2 ) { @@ -306,7 +456,8 @@ osm_physp_share_pkey( if (cl_is_map_empty(&pkey_tbl1->keys) || cl_is_map_empty(&pkey_tbl2->keys)) return TRUE; - return !ib_pkey_is_invalid(osm_physp_find_common_pkey(p_physp_1, p_physp_2)); + return + !ib_pkey_is_invalid(osm_physp_find_common_pkey(p_physp_1, p_physp_2)); } /********************************************************************** @@ -322,7 +473,8 @@ osm_port_share_pkey( OSM_LOG_ENTER( p_log, osm_port_share_pkey ); - if (!p_port_1 || !p_port_2) { + if (!p_port_1 || !p_port_2) + { ret = FALSE; goto Exit; } @@ -330,7 +482,8 @@ osm_port_share_pkey( p_physp1 = osm_port_get_default_phys_ptr(p_port_1); p_physp2 = osm_port_get_default_phys_ptr(p_port_2); - if (!p_physp1 || !p_physp2) { + if (!p_physp1 || !p_physp2) + { ret = FALSE; goto Exit; } Index: opensm/osm_pkey_mgr.c =================================================================== --- opensm/osm_pkey_mgr.c (revision 8113) +++ opensm/osm_pkey_mgr.c (working copy) @@ -62,6 +62,131 @@ /********************************************************************** **********************************************************************/ +/* + the max number of pkey blocks for a physical port is located in + different place for switch external ports (SwitchInfo) and the + rest of the ports (NodeInfo) +*/ +static int +pkey_mgr_get_physp_max_blocks( + IN const osm_subn_t *p_subn, + IN const osm_physp_t *p_physp) +{ + osm_node_t *p_node = osm_physp_get_node_ptr(p_physp); + osm_switch_t *p_sw; + uint16_t num_pkeys = 0; + + if ( (osm_node_get_type(p_node) != IB_NODE_TYPE_SWITCH) || + (osm_physp_get_port_num( p_physp ) == 0)) + num_pkeys = cl_ntoh16( p_node->node_info.partition_cap ); + else + { + p_sw = osm_get_switch_by_guid(p_subn, p_node->node_info.node_guid); + if (p_sw) + num_pkeys = cl_ntoh16( p_sw->switch_info.enforce_cap ); + } + return( (num_pkeys + 31) / 32 ); +} + +/********************************************************************** + **********************************************************************/ +/* + * Insert the new pending pkey entry to the specific port pkey table + * pending pkeys. new entries are inserted at the back. + */ +static void +pkey_mgr_process_physical_port( + IN osm_log_t *p_log, + IN const osm_req_t *p_req, + IN const ib_net16_t pkey, + IN osm_physp_t *p_physp ) +{ + osm_node_t *p_node = osm_physp_get_node_ptr( p_physp ); + osm_pkey_tbl_t *p_pkey_tbl; + ib_net16_t *p_orig_pkey; + char *stat = NULL; + osm_pending_pkey_t *p_pending; + + p_pkey_tbl = osm_physp_get_mod_pkey_tbl( p_physp ); + p_pending = (osm_pending_pkey_t *)malloc(sizeof(osm_pending_pkey_t)); + if (! p_pending) + { + osm_log( p_log, OSM_LOG_ERROR, + "pkey_mgr_process_physical_port: ERR 0502: " + "Fail to allocate new pending pkey entry for node " + "0x%016" PRIx64 " port %u\n", + cl_ntoh64( osm_node_get_node_guid( p_node ) ), + osm_physp_get_port_num( p_physp ) ); + return; + } + p_pending->pkey = pkey; + p_orig_pkey = cl_map_get( &p_pkey_tbl->keys, ib_pkey_get_base( pkey ) ); + if ( !p_orig_pkey ) + { + p_pending->is_new = TRUE; + cl_qlist_insert_tail(&p_pkey_tbl->pending, (cl_list_item_t*)p_pending); + stat = "inserted"; + } + else + { + CL_ASSERT( ib_pkey_get_base(*p_orig_pkey) == ib_pkey_get_base(pkey) ); + p_pending->is_new = FALSE; + if (osm_pkey_tbl_get_block_and_idx( + p_pkey_tbl, p_orig_pkey, + &p_pending->block, &p_pending->index) != IB_SUCCESS) + { + osm_log( p_log, OSM_LOG_ERROR, + "pkey_mgr_process_physical_port: ERR 0503: " + "Fail to obtain P_Key 0x%04x block and index for node " + "0x%016" PRIx64 " port %u\n", + cl_ntoh64( osm_node_get_node_guid( p_node ) ), + osm_physp_get_port_num( p_physp ) ); + return; + } + cl_qlist_insert_head(&p_pkey_tbl->pending, (cl_list_item_t*)p_pending); + stat = "updated"; + } + + osm_log( p_log, OSM_LOG_DEBUG, + "pkey_mgr_process_physical_port: " + "pkey 0x%04x was %s for node 0x%016" PRIx64 + " port %u\n", + cl_ntoh16( pkey ), stat, + cl_ntoh64( osm_node_get_node_guid( p_node ) ), + osm_physp_get_port_num( p_physp ) ); +} + +/********************************************************************** + **********************************************************************/ +static void +pkey_mgr_process_partition_table( + osm_log_t *p_log, + const osm_req_t *p_req, + const osm_prtn_t *p_prtn, + const boolean_t full ) +{ + const cl_map_t *p_tbl = + full ? &p_prtn->full_guid_tbl : &p_prtn->part_guid_tbl; + cl_map_iterator_t i, i_next; + ib_net16_t pkey = p_prtn->pkey; + osm_physp_t *p_physp; + + if ( full ) + pkey = cl_hton16( cl_ntoh16( pkey ) | 0x8000 ); + + i_next = cl_map_head( p_tbl ); + while ( i_next != cl_map_end( p_tbl ) ) + { + i = i_next; + i_next = cl_map_next( i ); + p_physp = cl_map_obj( i ); + if ( p_physp && osm_physp_is_valid( p_physp ) ) + pkey_mgr_process_physical_port( p_log, p_req, pkey, p_physp ); + } +} + +/********************************************************************** + **********************************************************************/ static ib_api_status_t pkey_mgr_update_pkey_entry( IN const osm_req_t *p_req, @@ -114,7 +239,8 @@ pkey_mgr_enforce_partition( p_pi->state_info2 = 0; ib_port_info_set_port_state( p_pi, IB_LINK_NO_CHANGE ); - context.pi_context.node_guid = osm_node_get_node_guid( osm_physp_get_node_ptr( p_physp ) ); + context.pi_context.node_guid = + osm_node_get_node_guid( osm_physp_get_node_ptr( p_physp ) ); context.pi_context.port_guid = osm_physp_get_port_guid( p_physp ); context.pi_context.set_method = TRUE; context.pi_context.update_master_sm_base_lid = FALSE; @@ -131,80 +257,132 @@ pkey_mgr_enforce_partition( /********************************************************************** **********************************************************************/ -/* - * Prepare a new entry for the pkey table for this port when this pkey - * does not exist. Update existed entry when membership was changed. - */ -static void pkey_mgr_process_physical_port( - IN osm_log_t *p_log, - IN const osm_req_t *p_req, - IN const ib_net16_t pkey, - IN osm_physp_t *p_physp ) +static boolean_t pkey_mgr_update_port( + osm_log_t *p_log, + osm_req_t *p_req, + const osm_port_t * const p_port ) { - osm_node_t *p_node = osm_physp_get_node_ptr( p_physp ); - ib_pkey_table_t *block; + osm_physp_t *p_physp; + osm_node_t *p_node; + ib_pkey_table_t *block, *new_block; + osm_pkey_tbl_t *p_pkey_tbl; uint16_t block_index; + uint8_t pkey_index; + uint16_t last_free_block_index = 0; + uint8_t last_free_pkey_index = 0; uint16_t num_of_blocks; - const osm_pkey_tbl_t *p_pkey_tbl; - ib_net16_t *p_orig_pkey; - char *stat = NULL; - uint32_t i; + uint16_t max_num_of_blocks; - p_pkey_tbl = osm_physp_get_pkey_tbl( p_physp ); - num_of_blocks = osm_pkey_tbl_get_num_blocks( p_pkey_tbl ); + ib_api_status_t status; + boolean_t ret_val = FALSE; + osm_pending_pkey_t *p_pending; + boolean_t found; - p_orig_pkey = cl_map_get( &p_pkey_tbl->keys, ib_pkey_get_base( pkey ) ); + p_physp = osm_port_get_default_phys_ptr( p_port ); + if ( !osm_physp_is_valid( p_physp ) ) + return FALSE; - if ( !p_orig_pkey ) - { - for ( block_index = 0; block_index < num_of_blocks; block_index++ ) + p_node = osm_physp_get_node_ptr( p_physp ); + p_pkey_tbl = osm_physp_get_mod_pkey_tbl( p_physp ); + num_of_blocks = osm_pkey_tbl_get_num_blocks( p_pkey_tbl ); + max_num_of_blocks = pkey_mgr_get_physp_max_blocks( p_req->p_subn, p_physp ); + if ( p_pkey_tbl->max_blocks > max_num_of_blocks ) { - block = osm_pkey_tbl_new_block_get( p_pkey_tbl, block_index ); - for ( i = 0; i < IB_NUM_PKEY_ELEMENTS_IN_BLOCK; i++ ) + osm_log( p_log, OSM_LOG_INFO, + "pkey_mgr_update_port: " + "Max number of blocks reduced from %u to %u " + "for node 0x%016" PRIx64 " port %u\n", + p_pkey_tbl->max_blocks, max_num_of_blocks, + cl_ntoh64( osm_node_get_node_guid( p_node ) ), + osm_physp_get_port_num( p_physp ) ); + } + p_pkey_tbl->max_blocks = max_num_of_blocks; + + osm_pkey_tbl_init_new_blocks( p_pkey_tbl ); + p_pkey_tbl->used_blocks = 0; + + /* + process every pending pkey in order - + first must be "updated" last are "new" + */ + p_pending = + (osm_pending_pkey_t *)cl_qlist_remove_head( &p_pkey_tbl->pending ); + while (p_pending != + (osm_pending_pkey_t *)cl_qlist_end( &p_pkey_tbl->pending ) ) + { + if (p_pending->is_new == FALSE) + { + block_index = p_pending->block; + pkey_index = p_pending->index; + found = TRUE; + } + else { - if ( ib_pkey_is_invalid( block->pkey_entry[i] ) ) + found = osm_pkey_find_next_free_entry(p_pkey_tbl, + &last_free_block_index, + &last_free_pkey_index); + if ( !found ) { - block->pkey_entry[i] = pkey; - stat = "inserted"; - goto _done; + osm_log( p_log, OSM_LOG_ERROR, + "pkey_mgr_update_port: ERR 0504: " + "failed to find empty space for new pkey 0x%04x " + "of node 0x%016" PRIx64 " port %u\n", + cl_ntoh16(p_pending->pkey), + cl_ntoh64( osm_node_get_node_guid( p_node ) ), + osm_physp_get_port_num( p_physp ) ); } + else + { + block_index = last_free_block_index; + pkey_index = last_free_pkey_index++; } } + + if (found) + { + if ( IB_SUCCESS != osm_pkey_tbl_set_new_entry( + p_pkey_tbl, block_index, pkey_index, p_pending->pkey) ) + { osm_log( p_log, OSM_LOG_ERROR, - "pkey_mgr_process_physical_port: ERR 0501: " - "No empty pkey entry was found to insert 0x%04x for node " - "0x%016" PRIx64 " port %u\n", - cl_ntoh16( pkey ), + "pkey_mgr_update_port: ERR 0505: " + "failed to set PKey 0x%04x in block %u idx %u " + "of node 0x%016" PRIx64 " port %u\n", + p_pending->pkey, block_index, pkey_index, cl_ntoh64( osm_node_get_node_guid( p_node ) ), osm_physp_get_port_num( p_physp ) ); } - else if ( *p_orig_pkey != pkey ) - { + } + + free( p_pending ); + p_pending = + (osm_pending_pkey_t *)cl_qlist_remove_head( &p_pkey_tbl->pending ); + } + + /* now look for changes and store */ for ( block_index = 0; block_index < num_of_blocks; block_index++ ) { - /* we need real block (not just new_block) in order - * to resolve block/pkey indices */ block = osm_pkey_tbl_block_get( p_pkey_tbl, block_index ); - i = p_orig_pkey - block->pkey_entry; - if (i < IB_NUM_PKEY_ELEMENTS_IN_BLOCK) { - block = osm_pkey_tbl_new_block_get( p_pkey_tbl, block_index ); - block->pkey_entry[i] = pkey; - stat = "updated"; - goto _done; - } - } - } + new_block = osm_pkey_tbl_new_block_get( p_pkey_tbl, block_index ); - _done: - if (stat) { - osm_log( p_log, OSM_LOG_VERBOSE, - "pkey_mgr_process_physical_port: " - "pkey 0x%04x was %s for node 0x%016" PRIx64 - " port %u\n", - cl_ntoh16( pkey ), stat, + if (block && + (!new_block || !memcmp( new_block, block, sizeof( *block ) )) ) + continue; + + status = pkey_mgr_update_pkey_entry( + p_req, p_physp , new_block, block_index ); + if (status == IB_SUCCESS) + ret_val = TRUE; + else + osm_log( p_log, OSM_LOG_ERROR, + "pkey_mgr_update_port: ERR 0506: " + "pkey_mgr_update_pkey_entry() failed to update " + "pkey table block %d for node 0x%016" PRIx64 " port %u\n", + block_index, cl_ntoh64( osm_node_get_node_guid( p_node ) ), osm_physp_get_port_num( p_physp ) ); } + + return ret_val; } /********************************************************************** @@ -217,21 +395,23 @@ pkey_mgr_update_peer_port( const osm_port_t * const p_port, boolean_t enforce ) { - osm_physp_t *p, *peer; + osm_physp_t *p_physp, *peer; osm_node_t *p_node; ib_pkey_table_t *block, *peer_block; - const osm_pkey_tbl_t *p_pkey_tbl, *p_peer_pkey_tbl; + const osm_pkey_tbl_t *p_pkey_tbl; + osm_pkey_tbl_t *p_peer_pkey_tbl; osm_switch_t *p_sw; ib_switch_info_t *p_si; uint16_t block_index; uint16_t num_of_blocks; + uint16_t peer_max_blocks; ib_api_status_t status = IB_SUCCESS; boolean_t ret_val = FALSE; - p = osm_port_get_default_phys_ptr( p_port ); - if ( !osm_physp_is_valid( p ) ) + p_physp = osm_port_get_default_phys_ptr( p_port ); + if ( !osm_physp_is_valid( p_physp ) ) return FALSE; - peer = osm_physp_get_remote( p ); + peer = osm_physp_get_remote( p_physp ); if ( !peer || !osm_physp_is_valid( peer ) ) return FALSE; p_node = osm_physp_get_node_ptr( peer ); @@ -242,10 +422,26 @@ pkey_mgr_update_peer_port( if (!p_sw || !(p_si = osm_switch_get_si_ptr( p_sw )) || !p_si->enforce_cap) return FALSE; + p_pkey_tbl = osm_physp_get_pkey_tbl( p_physp ); + p_peer_pkey_tbl = osm_physp_get_mod_pkey_tbl( peer ); + num_of_blocks = osm_pkey_tbl_get_num_blocks( p_pkey_tbl ); + peer_max_blocks = pkey_mgr_get_physp_max_blocks( p_subn, peer ); + if (peer_max_blocks < p_pkey_tbl->used_blocks) + { + osm_log( p_log, OSM_LOG_ERROR, + "pkey_mgr_update_peer_port: ERR 0508: " + "not enough entries (%u < %u) on switch 0x%016" PRIx64 + " port %u. Clearing Enforcement bit.\n", + peer_max_blocks, num_of_blocks, + cl_ntoh64( osm_node_get_node_guid( p_node ) ), + osm_physp_get_port_num( peer ) ); + enforce = FALSE; + } + if (pkey_mgr_enforce_partition( p_req, peer, enforce ) != IB_SUCCESS) { osm_log( p_log, OSM_LOG_ERROR, - "pkey_mgr_update_peer_port: ERR 0502: " + "pkey_mgr_update_peer_port: ERR 0507: " "pkey_mgr_enforce_partition() failed to update " "node 0x%016" PRIx64 " port %u\n", cl_ntoh64( osm_node_get_node_guid( p_node ) ), @@ -255,24 +451,19 @@ pkey_mgr_update_peer_port( if (enforce == FALSE) return FALSE; - p_pkey_tbl = osm_physp_get_pkey_tbl( p ); - p_peer_pkey_tbl = osm_physp_get_pkey_tbl( peer ); - num_of_blocks = osm_pkey_tbl_get_num_blocks( p_pkey_tbl ); - if ( num_of_blocks > osm_pkey_tbl_get_num_blocks( p_peer_pkey_tbl ) ) - num_of_blocks = osm_pkey_tbl_get_num_blocks( p_peer_pkey_tbl ); - - for ( block_index = 0; block_index < num_of_blocks; block_index++ ) + p_peer_pkey_tbl->used_blocks = p_pkey_tbl->used_blocks; + for ( block_index = 0; block_index < p_pkey_tbl->used_blocks; block_index++) { block = osm_pkey_tbl_new_block_get( p_pkey_tbl, block_index ); peer_block = osm_pkey_tbl_block_get( p_peer_pkey_tbl, block_index ); - if ( memcmp( peer_block, block, sizeof( *peer_block ) ) ) + if ( !peer_block || memcmp( peer_block, block, sizeof( *peer_block ) ) ) { status = pkey_mgr_update_pkey_entry( p_req, peer, block, block_index ); if ( status == IB_SUCCESS ) ret_val = TRUE; else osm_log( p_log, OSM_LOG_ERROR, - "pkey_mgr_update_peer_port: ERR 0503: " + "pkey_mgr_update_peer_port: ERR 0509: " "pkey_mgr_update_pkey_entry() failed to update " "pkey table block %d for node 0x%016" PRIx64 " port %u\n", @@ -282,10 +473,10 @@ pkey_mgr_update_peer_port( } } - if ( ret_val == TRUE && - osm_log_is_active( p_log, OSM_LOG_VERBOSE ) ) + if ( (ret_val == TRUE) && + osm_log_is_active( p_log, OSM_LOG_DEBUG ) ) { - osm_log( p_log, OSM_LOG_VERBOSE, + osm_log( p_log, OSM_LOG_DEBUG, "pkey_mgr_update_peer_port: " "pkey table was updated for node 0x%016" PRIx64 " port %u\n", @@ -298,82 +489,6 @@ pkey_mgr_update_peer_port( /********************************************************************** **********************************************************************/ -static boolean_t pkey_mgr_update_port( - osm_log_t *p_log, - osm_req_t *p_req, - const osm_port_t * const p_port ) -{ - osm_physp_t *p; - osm_node_t *p_node; - ib_pkey_table_t *block, *new_block; - const osm_pkey_tbl_t *p_pkey_tbl; - uint16_t block_index; - uint16_t num_of_blocks; - ib_api_status_t status; - boolean_t ret_val = FALSE; - - p = osm_port_get_default_phys_ptr( p_port ); - if ( !osm_physp_is_valid( p ) ) - return FALSE; - - p_pkey_tbl = osm_physp_get_pkey_tbl(p); - num_of_blocks = osm_pkey_tbl_get_num_blocks( p_pkey_tbl ); - - for ( block_index = 0; block_index < num_of_blocks; block_index++ ) - { - block = osm_pkey_tbl_block_get( p_pkey_tbl, block_index ); - new_block = osm_pkey_tbl_new_block_get( p_pkey_tbl, block_index ); - - if (!new_block || !memcmp( new_block, block, sizeof( *block ) ) ) - continue; - - status = pkey_mgr_update_pkey_entry( p_req, p, new_block, block_index ); - if (status == IB_SUCCESS) - ret_val = TRUE; - else - osm_log( p_log, OSM_LOG_ERROR, - "pkey_mgr_update_port: ERR 0504: " - "pkey_mgr_update_pkey_entry() failed to update " - "pkey table block %d for node 0x%016" PRIx64 " port %u\n", - block_index, - cl_ntoh64( osm_node_get_node_guid( p_node ) ), - osm_physp_get_port_num( p ) ); - } - - return ret_val; -} - -/********************************************************************** - **********************************************************************/ -static void -pkey_mgr_process_partition_table( - osm_log_t *p_log, - const osm_req_t *p_req, - const osm_prtn_t *p_prtn, - const boolean_t full ) -{ - const cl_map_t *p_tbl = full ? - &p_prtn->full_guid_tbl : &p_prtn->part_guid_tbl; - cl_map_iterator_t i, i_next; - ib_net16_t pkey = p_prtn->pkey; - osm_physp_t *p_physp; - - if ( full ) - pkey = cl_hton16( cl_ntoh16( pkey ) | 0x8000 ); - - i_next = cl_map_head( p_tbl ); - while ( i_next != cl_map_end( p_tbl ) ) - { - i = i_next; - i_next = cl_map_next( i ); - p_physp = cl_map_obj( i ); - if ( p_physp && osm_physp_is_valid( p_physp ) ) - pkey_mgr_process_physical_port( p_log, p_req, pkey, p_physp ); - } -} - -/********************************************************************** - **********************************************************************/ osm_signal_t osm_pkey_mgr_process( IN osm_opensm_t *p_osm ) @@ -383,8 +498,7 @@ osm_pkey_mgr_process( osm_prtn_t *p_prtn; osm_port_t *p_port; osm_signal_t signal = OSM_SIGNAL_DONE; - osm_physp_t *p_physp; - + osm_node_t *p_node; CL_ASSERT( p_osm ); OSM_LOG_ENTER( &p_osm->log, osm_pkey_mgr_process ); @@ -394,32 +508,25 @@ osm_pkey_mgr_process( if ( osm_prtn_make_partitions( &p_osm->log, &p_osm->subn ) != IB_SUCCESS ) { osm_log( &p_osm->log, OSM_LOG_ERROR, - "osm_pkey_mgr_process: ERR 0505: " + "osm_pkey_mgr_process: ERR 0510: " "osm_prtn_make_partitions() failed\n" ); goto _err; } - p_tbl = &p_osm->subn.port_guid_tbl; - p_next = cl_qmap_head( p_tbl ); - while ( p_next != cl_qmap_end( p_tbl ) ) - { - p_port = ( osm_port_t * ) p_next; - p_next = cl_qmap_next( p_next ); - p_physp = osm_port_get_default_phys_ptr( p_port ); - if ( osm_physp_is_valid( p_physp ) ) - osm_pkey_tbl_sync_new_blocks( osm_physp_get_pkey_tbl( p_physp ) ); - } - + /* populate the pending pkey entries by scanning all partitions */ p_tbl = &p_osm->subn.prtn_pkey_tbl; p_next = cl_qmap_head( p_tbl ); while ( p_next != cl_qmap_end( p_tbl ) ) { p_prtn = ( osm_prtn_t * ) p_next; p_next = cl_qmap_next( p_next ); - pkey_mgr_process_partition_table( &p_osm->log, &p_osm->sm.req, p_prtn, FALSE ); - pkey_mgr_process_partition_table( &p_osm->log, &p_osm->sm.req, p_prtn, TRUE ); + pkey_mgr_process_partition_table( + &p_osm->log, &p_osm->sm.req, p_prtn, FALSE ); + pkey_mgr_process_partition_table( + &p_osm->log, &p_osm->sm.req, p_prtn, TRUE ); } + /* calculate new pkey tables and set */ p_tbl = &p_osm->subn.port_guid_tbl; p_next = cl_qmap_head( p_tbl ); while ( p_next != cl_qmap_end( p_tbl ) ) @@ -428,8 +535,10 @@ osm_pkey_mgr_process( p_next = cl_qmap_next( p_next ); if ( pkey_mgr_update_port( &p_osm->log, &p_osm->sm.req, p_port ) ) signal = OSM_SIGNAL_DONE_PENDING; - if ( osm_node_get_type( osm_port_get_parent_node( p_port ) ) != IB_NODE_TYPE_SWITCH && - pkey_mgr_update_peer_port( &p_osm->log, &p_osm->sm.req, + p_node = osm_port_get_parent_node( p_port ); + if ( ( osm_node_get_type( p_node ) != IB_NODE_TYPE_SWITCH ) && + pkey_mgr_update_peer_port( + &p_osm->log, &p_osm->sm.req, &p_osm->subn, p_port, !p_osm->subn.opt.no_partition_enforcement ) ) signal = OSM_SIGNAL_DONE_PENDING; _______________________________________________ openib-general mailing list openib-general@openib.org http://openib.org/mailman/listinfo/openib-general To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general