[openib-general] [PATCH] osm: partition manager force policy (and other fixes)

Eitan Zahavi eitan at mellanox.co.il
Mon Jun 12 06:59:14 PDT 2006


Hi Hal

As I started to test the partition manager code (using ibmgtsim pkey test),
I realized the implementation does not really enforces the partition policy
on the given fabric. This patch fixes that. It was verified using the 
simulation test. Several other corner cases were fixed too.

Eitan

Signed-off-by:  Eitan Zahavi <eitan at mellanox.co.il>

Index: include/opensm/osm_port.h
===================================================================
--- include/opensm/osm_port.h	(revision 7867)
+++ include/opensm/osm_port.h	(working copy)
@@ -586,6 +586,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 7867)
+++ include/opensm/osm_pkey.h	(working copy)
@@ -92,6 +92,8 @@ 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;
 } osm_pkey_tbl_t;
 /*
 * FIELDS
@@ -104,6 +106,13 @@ 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
+*
 * 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 +123,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
@@ -263,6 +305,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 1 if cound not find 
+*  it, 0 if OK
+*
+* SYNOPSIS
+*/
+int
+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
Index: opensm/osm_prtn.c
===================================================================
--- opensm/osm_prtn.c	(revision 7904)
+++ opensm/osm_prtn.c	(working copy)
@@ -140,6 +140,12 @@ ib_api_status_t osm_prtn_add_port(osm_lo
 
 	p_tbl = (full == TRUE) ? &p->full_guid_tbl : &p->part_guid_tbl ;
 
+   osm_log(p_log, OSM_LOG_VERBOSE, "osm_prtn_add_port: "
+           "Added port 0x%" PRIx64 " to "
+           "partition \'%s\' (0x%04x) As %s member\n",
+           cl_ntoh64(guid), p->name, cl_ntoh16(p->pkey),
+           full ? "full" : "partial" );
+
 	if (cl_map_insert(p_tbl, guid, p_physp) == NULL)
 		return IB_INSUFFICIENT_MEMORY;
 
Index: opensm/osm_pkey.c
===================================================================
--- opensm/osm_pkey.c	(revision 7904)
+++ opensm/osm_pkey.c	(working copy)
@@ -100,6 +100,8 @@ int osm_pkey_tbl_init( 
   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 );
+
   return(IB_SUCCESS);
 }
 
@@ -118,14 +120,28 @@ void osm_pkey_tbl_sync_new_blocks(
     p_block = cl_ptr_vector_get(&p_pkey_tbl->blocks, b);
     if ( b < new_blocks )
       p_new_block = cl_ptr_vector_get(&p_pkey_tbl->new_blocks, b);
-    else {
+		else 
+      {
       p_new_block = (ib_pkey_table_t *)malloc(sizeof(*p_new_block));
       if (!p_new_block)
         break;
-      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));
+
+		memset(p_new_block, 0, 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 );
   }
 }
 
@@ -202,6 +218,38 @@ int osm_pkey_tbl_set( 
 
 /**********************************************************************
  **********************************************************************/
+int
+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 0;
+		}
+	}
+	return 1;
+}
+
+/**********************************************************************
+ **********************************************************************/
 static boolean_t __osm_match_pkey (
   IN const ib_net16_t *pkey1,
   IN const ib_net16_t *pkey2 ) {
@@ -321,7 +369,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;
   }
@@ -329,7 +378,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 7904)
+++ opensm/osm_pkey_mgr.c	(working copy)
@@ -62,6 +62,138 @@
 
 /**********************************************************************
  **********************************************************************/
+/*
+  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 );
+	if (! p_pkey_tbl)
+	{
+		osm_log( p_log, OSM_LOG_ERROR,
+					"pkey_mgr_process_physical_port: ERR 0501: "
+					"No pkey table found 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 = (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  || (ib_pkey_get_base(*p_orig_pkey) != ib_pkey_get_base(pkey) ))
+	{
+		p_pending->is_new = TRUE;
+		cl_qlist_insert_tail(&p_pkey_tbl->pending, (cl_list_item_t*)p_pending);
+		stat = "inserted";
+	}
+	else
+	{
+		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))
+		{
+			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_VERBOSE,
+				"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,
@@ -131,80 +263,153 @@ 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;
-   uint16_t block_index;
+	osm_physp_t *p_physp;
+	osm_node_t *p_node;
+	ib_pkey_table_t *block, *new_block, *p_old_block;
+	osm_pkey_tbl_t *p_pkey_tbl;
+	uint16_t block_index = 0;
+	uint16_t last_free_block_index = 0;
+	uint16_t last_free_entry_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 );
+	ib_api_status_t status;
+	boolean_t ret_val = FALSE;
+	osm_pending_pkey_t *p_pending;
+	boolean_t found;
+
+	p_physp = osm_port_get_default_phys_ptr( p_port );
+	if ( !osm_physp_is_valid( p_physp ) )
+		return FALSE;
+
+	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 );
 
-   p_orig_pkey = cl_map_get( &p_pkey_tbl->keys, ib_pkey_get_base( pkey ) );
+	osm_pkey_tbl_sync_new_blocks( p_pkey_tbl );
+	cl_map_remove_all( &p_pkey_tbl->keys );
+	p_pkey_tbl->used_blocks = 0;
 
-   if ( !p_orig_pkey )
-   {
-      for ( block_index = 0; block_index < num_of_blocks; block_index++ )
+	/* 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 ) )
       {
-         block = osm_pkey_tbl_new_block_get( p_pkey_tbl, block_index );
-         for ( i = 0; i < IB_NUM_PKEY_ELEMENTS_IN_BLOCK; i++ )
+		if (p_pending->is_new == FALSE)
          {
-            if ( ib_pkey_is_invalid( block->pkey_entry[i] ) )
+			block = osm_pkey_tbl_new_block_get( p_pkey_tbl, p_pending->block );
+			if (block == NULL)
             {
-               block->pkey_entry[i] = pkey;
-	       stat = "inserted";
-	       goto _done;
+				osm_log( p_log, OSM_LOG_ERROR,
+							"pkey_mgr_update_port: ERR 0504: "
+							"failed to get block %d for node 0x%016" PRIx64 " port %u\n",
+							p_pending->block,
+							cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+							osm_physp_get_port_num( p_physp ) );
             }
+			else
+			{
+				p_old_block = osm_pkey_tbl_block_get( p_pkey_tbl, p_pending->block );
+				CL_ASSERT( p_old_block != NULL );
+				cl_map_insert( &p_pkey_tbl->keys,
+									ib_pkey_get_base(p_pending->pkey),
+									&(p_old_block->pkey_entry[p_pending->index]));
+				block->pkey_entry[p_pending->index] = p_pending->pkey;
+				if (p_pkey_tbl->used_blocks < p_pending->index)
+					p_pending->index = p_pending->index;
          }
       }
+		else
+		{
+			/* need either an empty entry or next block */
+			block = osm_pkey_tbl_new_block_get( p_pkey_tbl, last_free_block_index );
+			found = FALSE;
+			while ( !found && (last_free_block_index < max_num_of_blocks))
+			{
+				if ( block->pkey_entry[last_free_entry_index] == 0)
+					found = TRUE;
+				else
+				{
+					if (last_free_entry_index == IB_NUM_PKEY_ELEMENTS_IN_BLOCK)
+					{
+						last_free_entry_index = 0;
+						last_free_block_index++;
+						block = osm_pkey_tbl_new_block_get( p_pkey_tbl, last_free_block_index );
+						if ((!block) && (last_free_block_index < max_num_of_blocks))
+						{
+							block = (ib_pkey_table_t *)malloc(sizeof(*block));
+							if (!block)
+							{
       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 0513: "
+											"failed to allocate new block %d for node 0x%016" PRIx64 " port %u\n",
+											last_free_block_index,
                cl_ntoh64( osm_node_get_node_guid( p_node ) ),
                osm_physp_get_port_num( p_physp ) );
+								continue;
+							}
+							cl_ptr_vector_set(&p_pkey_tbl->new_blocks, last_free_block_index, block);
    }
-   else if ( *p_orig_pkey != pkey )
+					}
+					else
    {
-      for ( block_index = 0; block_index < num_of_blocks; block_index++ )
+						last_free_entry_index++;
+					}
+				}
+			}
+
+			if ( !found )
       {
-         /* 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;
+				osm_log( p_log, OSM_LOG_ERROR,
+							"pkey_mgr_update_port: ERR 0505: "
+							"failed to empty space for new pkey 0x%04x for 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
+			{
+				p_old_block = osm_pkey_tbl_block_get( p_pkey_tbl, last_free_entry_index);
+				CL_ASSERT( p_old_block != NULL );
+				block->pkey_entry[last_free_entry_index] = p_pending->pkey;
+				cl_map_insert( &p_pkey_tbl->keys,
+									ib_pkey_get_base(p_pending->pkey),
+									&(p_old_block->pkey_entry[last_free_entry_index]));
+				if (p_pkey_tbl->used_blocks < last_free_entry_index)
+					p_pending->index = last_free_entry_index;
       }
    }
+		free( p_pending );
+		p_pending = (osm_pending_pkey_t *)cl_qlist_remove_head( &p_pkey_tbl->pending );
+	}
 
- _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,
+	/* now look for changes and store */
+	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_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 +422,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 );
@@ -245,7 +452,7 @@ pkey_mgr_update_peer_port(
    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 +462,36 @@ 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 );
+	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 );
-   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 );
+	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\n",
+					peer_max_blocks, num_of_blocks,
+					cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+					osm_physp_get_port_num( peer ) );
+		return FALSE;
+	}
 
-   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 ) ) )
       {
+			osm_pkey_tbl_set(p_peer_pkey_tbl, block_index, 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,7 +501,7 @@ pkey_mgr_update_peer_port(
       }
    }
 
-   if ( ret_val == TRUE &&
+	if ( (ret_val == TRUE) &&
         osm_log_is_active( p_log, OSM_LOG_VERBOSE ) )
    {
       osm_log( p_log, OSM_LOG_VERBOSE,
@@ -298,82 +517,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,7 +526,6 @@ 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;
 
    CL_ASSERT( p_osm );
 
@@ -394,22 +536,12 @@ 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 ) )
@@ -420,6 +552,7 @@ osm_pkey_mgr_process(
       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,7 +561,7 @@ 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 &&
+		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_osm->subn, p_port,
                                       !p_osm->subn.opt.no_partition_enforcement ) )





More information about the general mailing list