[openib-general] [RFC] [PATCH] OpenSM: Add functional partition manager support
Sasha Khapyorsky
sashak at voltaire.com
Thu Mar 9 15:33:49 PST 2006
On 19:23 Wed 01 Mar , Sasha Khapyorsky wrote:
> > >
> > > There is phase 1 of partiton manager for OpenSM. Please review.
>
> There is partition patch which includes all last changes and is updated
> against recent SVN tree.
Updated patch. Changes are:
- clean perror() (osm_log() instead)
- creates "dummy" MC group for non ipoib partitions
- formatting changes
- update against recent SVN
Sasha.
This patch implements partition management for OpenSM (Phase 1) as
described in osm/doc/OpenSM_PKey_Mgr.txt.
Basically at each heavy resweep this will:
- recreate partition configuration
- update pkey tables for endports
- update switch's ports connected to endports
- for partitions marked for IPoIB support this will also create
appropriate multicast group, desired rate and mtu values may
be specified
Signed-off-by: Sasha Khapyorsky <sashak at voltaire.com>
---
osm/doc/partition-config.txt | 98 ++++++
osm/include/opensm/osm_base.h | 16 +
osm/include/opensm/osm_partition.h | 151 ++++------
osm/include/opensm/osm_sa_mcmember_record.h | 38 ++
osm/include/opensm/osm_subnet.h | 7
osm/opensm/Makefile.am | 1
osm/opensm/main.c | 11 +
osm/opensm/osm_opensm.c | 2
osm/opensm/osm_pkey_mgr.c | 359 ++++++++++++++++-------
osm/opensm/osm_prtn.c | 325 +++++++++++++++++++++
osm/opensm/osm_prtn_config.c | 417 +++++++++++++++++++++++++++
osm/opensm/osm_sa_mcmember_record.c | 20 +
osm/opensm/osm_subnet.c | 17 +
13 files changed, 1256 insertions(+), 206 deletions(-)
diff --git a/osm/doc/partition-config.txt b/osm/doc/partition-config.txt
new file mode 100644
index 0000000..a5d0fd0
--- /dev/null
+++ b/osm/doc/partition-config.txt
@@ -0,0 +1,98 @@
+OpenSM Partitions configuration.
+===============================
+
+The default name of OpenSM partitions configuration file is
+'/etc/osm-partitions.txt'. The default may be changed by using
+--Pconfig (-P) option with OpenSM.
+
+The default partition will be created by OpenSM unconditionally even
+when partition configuration file does not exist or cannot be accessed.
+
+The default partition has P_Key value 0x7fff. OpenSM's port will have
+full membership in default partition. all other end ports will have
+partial membership.
+
+
+File Format.
+===========
+
+Comments:
+--------
+
+Line content followed after '#' character is comment and ignored by
+parser.
+
+
+General file format:
+-------------------
+
+<Partition Definition>:<PortGUIDs list> ;
+
+
+Partition Definition:
+--------------------
+
+[PartitionName][=PKey][,flag[=value]]
+
+PartitionName - free string, will be used with logging. When omitted
+ empty string will be used.
+PKey - P_Key value for this partition. Only low 15 bits will
+ be used. When omitted will be autogenerated.
+flag - used to indicate IPoIB capability of this partition.
+
+Currently recognized flags are:
+
+ipoib - indicates that this partition may be used for IPoIB, as
+ result IPoIB capable MC group will be created.
+rate=<val> - specifies rate for this IPoIB MC group (default is 3 (10Bps))
+mtu=<val> - specifies MTU for this IPoIB MC group (default is 4 (2048))
+
+Note that values for 'rate' and 'mtu' should be specified as defined in
+IBTA specification (for example mtu=4 for 2048).
+
+
+PortGUIDs list:
+--------------
+
+[PortGUID[=full|=part]] [,PortGUID[=full|=part]] [,PortGUID] ...
+
+PortGUID - GUID of partition member EndPort. Hexadecimal numbers
+ should start from 0x, decimal numbers are accepted too.
+full or part - indicates full or partial membership for this port. When
+ omitted (or unrecognized) partial membership is assumed.
+
+There are two useful keywords for PortGUID definition:
+
+- 'ALL' means all end ports in this subnet
+- 'SELF' means subnet manager's port.
+
+Empty list means no ports in this partition.
+
+
+Notes:
+-----
+
+White spaces are permitted between delimiters ('=', ',',':',';').
+
+The Line can be wrapped after ':' followed after Partition Definition and
+between.
+
+PartitionName does not need to be unique, PKey does need to be unique.
+If PKey is repeated then those partition configurations will be merged
+and first PartitionName will be used (see also next note).
+
+It is possible to split partition configuration in more than one
+definition, but then PKey should be explicitly specified (overwise
+different PKey values will be generated for those definitions).
+
+
+Examples:
+--------
+
+Default=0x7fff : ALL, SELF=full ;
+
+NewPartition , ipoib : 0x123456=full, 0x3456789034=part, 0x2134af2306 ;
+
+YetAnotherOne = 0x300 : SELF=full ;
+YetAnotherOne = 0x300 : ALL=part ;
+
diff --git a/osm/include/opensm/osm_base.h b/osm/include/opensm/osm_base.h
index 660771f..3da39a6 100644
--- a/osm/include/opensm/osm_base.h
+++ b/osm/include/opensm/osm_base.h
@@ -222,6 +222,22 @@ BEGIN_C_DECLS
#endif
/***********/
+/****d* OpenSM: Base/OSM_DEFAULT_PARTITION_CONFIG_FILE
+* NAME
+* OSM_DEFAULT_PARTITION_CONFIG_FILE
+*
+* DESCRIPTION
+* Specifies the default partition config file name
+*
+* SYNOPSIS
+*/
+#ifdef __WIN__
+#define OSM_DEFAULT_PARTITION_CONFIG_FILE strcat(GetOsmPath(), "osm-partitions.conf")
+#else
+#define OSM_DEFAULT_PARTITION_CONFIG_FILE "/etc/osm-partitions.conf"
+#endif
+/***********/
+
/****d* OpenSM: Base/OSM_DEFAULT_SWEEP_INTERVAL_SECS
* NAME
* OSM_DEFAULT_SWEEP_INTERVAL_SECS
diff --git a/osm/include/opensm/osm_partition.h b/osm/include/opensm/osm_partition.h
index 27678c2..369cf8a 100644
--- a/osm/include/opensm/osm_partition.h
+++ b/osm/include/opensm/osm_partition.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
* Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
* Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
*
@@ -50,6 +50,12 @@
#ifndef _OSM_PARTITION_H_
#define _OSM_PARTITION_H_
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_map.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_subnet.h>
+
#ifdef __cplusplus
# define BEGIN_C_DECLS extern "C" {
# define END_C_DECLS }
@@ -94,12 +100,17 @@ BEGIN_C_DECLS
*/
typedef struct _osm_prtn
{
- uint16_t pkey;
- cl_map port_guid_tbl;
-
+ cl_map_item_t map_item;
+ uint16_t pkey;
+ cl_map_t full_guid_tbl;
+ cl_map_t part_guid_tbl;
+ char name[32];
} osm_prtn_t;
/*
* FIELDS
+* map_item
+* Linkage structure for cl_qmap. MUST BE FIRST MEMBER!
+*
* pkey
* The IBA defined P_KEY of this Partition.
*
@@ -111,118 +122,61 @@ typedef struct _osm_prtn
* Partition
*********/
-/****f* OpenSM: Partition/osm_prtn_construct
+/****f* OpenSM: Partition/osm_prtn_delete
* NAME
-* osm_prtn_construct
+* osm_prtn_delete
*
* DESCRIPTION
-* This function constructs a Partition.
+* This function destroys and deallocates a Partition object.
*
* SYNOPSIS
*/
-void osm_prtn_construct(
- IN osm_prtn_t* const p_prtn );
+void osm_prtn_delete(
+ IN OUT osm_prtn_t** const pp_prtn );
/*
* PARAMETERS
-* p_prtn
-* [in] Pointer to a Partition to construct.
+* pp_prtn
+* [in][out] Pointer to a pointer to a Partition oject to
+* delete. On return, this pointer is NULL.
*
* RETURN VALUE
* This function does not return a value.
*
* NOTES
-* Allows calling osm_prtn_init, osm_prtn_destroy, and osm_prtn_is_inited.
-*
-* Calling osm_prtn_construct is a prerequisite to calling any other
-* method except osm_prtn_init.
+* Performs any necessary cleanup of the specified Partition object.
*
* SEE ALSO
-* Partition, osm_prtn_init, osm_prtn_destroy, osm_prtn_is_inited
+* Partition, osm_prtn_new
*********/
-/****f* OpenSM: Partition/osm_prtn_destroy
+/****f* OpenSM: Partition/osm_prtn_new
* NAME
-* osm_prtn_destroy
+* osm_prtn_new
*
* DESCRIPTION
-* The osm_prtn_destroy function destroys a Partition, releasing
-* all resources.
+* This function allocates and initializes a Partition object.
*
* SYNOPSIS
*/
-void osm_prtn_destroy(
- IN osm_prtn_t* const p_prtn );
+osm_prtn_t* osm_prtn_new(
+ IN const char *name,
+ IN const uint16_t pkey );
/*
* PARAMETERS
-* p_prtn
-* [in] Pointer to a Partition to destroy.
-*
-* RETURN VALUE
-* This function does not return a value.
-*
-* NOTES
-* Performs any necessary cleanup of the specified Partition.
-* Further operations should not be attempted on the destroyed object.
-* This function should only be called after a call to osm_prtn_construct or
-* osm_prtn_init.
-*
-* SEE ALSO
-* Partition, osm_prtn_construct, osm_prtn_init
-*********/
-
-/****f* OpenSM: Partition/osm_prtn_init
-* NAME
-* osm_prtn_init
-*
-* DESCRIPTION
-* The osm_prtn_init function initializes a Partition for use.
-*
-* SYNOPSIS
-*/
-ib_api_status_t osm_prtn_init(
- IN osm_prtn_t* const p_prtn );
-/*
-* PARAMETERS
-* p_prtn
-* [in] Pointer to an osm_prtn_t object to initialize.
-*
-* RETURN VALUES
-* CL_SUCCESS if initialization was successful.
-*
-* NOTES
-* Allows calling other Partition methods.
+* name
+* [in] Partition name string
*
-* SEE ALSO
-* Partition, osm_prtn_construct, osm_prtn_destroy,
-* osm_prtn_is_inited
-*********/
-
-/****f* OpenSM: Partition/osm_prtn_is_inited
-* NAME
-* osm_prtn_is_inited
-*
-* DESCRIPTION
-* Indicates if the object has been initialized with osm_prtn_init.
-*
-* SYNOPSIS
-*/
-boolean_t osm_ptrn_is_inited(
- IN const osm_prtn_t* const p_prtn );
-/*
-* PARAMETERS
-* p_prtn
-* [in] Pointer to an osm_prtn_t object.
+* pkey
+* [in] Partition P_Key value
*
-* RETURN VALUES
-* TRUE if the object was initialized successfully,
-* FALSE otherwise.
+* RETURN VALUE
+* Pointer to the initialize Partition object.
*
* NOTES
-* The osm_prtn_construct or osm_prtn_init must be called before using
-* this function.
+* Allows calling other partition methods.
*
* SEE ALSO
-* Partition, osm_prtn_construct, osm_prtn_init
+* Partition
*********/
/****f* OpenSM: Partition/osm_prtn_is_guid
@@ -234,9 +188,14 @@ boolean_t osm_ptrn_is_inited(
*
* SYNOPSIS
*/
+static inline
boolean_t osm_prtn_is_guid(
IN const osm_prtn_t* const p_prtn,
- IN const uint64 guid );
+ IN const ib_net64_t guid )
+{
+ return (cl_map_get(&p_prtn->full_guid_tbl, guid) != NULL) ||
+ (cl_map_get(&p_prtn->part_guid_tbl, guid) != NULL);
+}
/*
* PARAMETERS
* p_prtn
@@ -254,24 +213,28 @@ boolean_t osm_prtn_is_guid(
* SEE ALSO
*********/
-/****f* OpenSM: Partition/osm_prtn_get_pkey
+/****f* OpenSM: Partition/osm_prtn_make_partitions
* NAME
-* osm_prtn_get_pkey
+* osm_prtn_make_partitions
*
* DESCRIPTION
-* Gets the IBA defined P_KEY value for this Partition.
+* Makes all partitions in subnet.
*
* SYNOPSIS
*/
-uint16_t osm_prtn_get_pkey(
- IN const osm_prtn_t* const p_prtn );
+ib_api_status_t osm_prtn_make_partitions(
+ IN osm_log_t * const p_log,
+ IN osm_subn_t * const p_subn);
/*
* PARAMETERS
-* p_prtn
-* [in] Pointer to an osm_prtn_t object.
+* p_log
+* [in] Pointer to a log object.
+*
+* p_subn
+* [in] Pointer to subnet object.
*
* RETURN VALUES
-* P_KEY value for this Partition.
+* IB_SUCCESS value on success.
*
* NOTES
*
diff --git a/osm/include/opensm/osm_sa_mcmember_record.h b/osm/include/opensm/osm_sa_mcmember_record.h
index 39a466c..92de861 100644
--- a/osm/include/opensm/osm_sa_mcmember_record.h
+++ b/osm/include/opensm/osm_sa_mcmember_record.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
* Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
* Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
*
@@ -320,6 +320,42 @@ osm_mcmr_rcv_create_new_mgrp(
*
*********/
+/****f* OpenSM: MC Member record Receiver/osm_mcmr_rcv_find_or_create_new_mgrp
+* NAME
+* osm_mcmr_rcv_find_or_create_new_mgrp
+*
+* DESCRIPTION
+* Create new Multicast group
+*
+* SYNOPSIS
+*/
+
+ib_api_status_t
+osm_mcmr_rcv_find_or_create_new_mgrp(
+ IN osm_mcmr_recv_t* const p_mcmr,
+ IN uint64_t comp_mask,
+ IN ib_member_rec_t* const p_recvd_mcmember_rec,
+ OUT osm_mgrp_t **pp_mgrp);
+/*
+* PARAMETERS
+* p_mcmr
+* [in] Pointer to an osm_mcmr_recv_t object.
+* p_recvd_mcmember_rec
+* [in] Received Multicast member record
+*
+* pp_mgrp
+* [out] pointer the osm_mgrp_t object
+*
+* RETURN VALUES
+* IB_SUCCESS, IB_ERROR
+*
+* NOTES
+*
+*
+* SEE ALSO
+*
+*********/
+
#define JOIN_MC_COMP_MASK (IB_MCR_COMPMASK_MGID | \
IB_MCR_COMPMASK_PORT_GID | \
IB_MCR_COMPMASK_JOIN_STATE)
diff --git a/osm/include/opensm/osm_subnet.h b/osm/include/opensm/osm_subnet.h
index 0aab874..7841c29 100644
--- a/osm/include/opensm/osm_subnet.h
+++ b/osm/include/opensm/osm_subnet.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
* Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
* Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
*
@@ -73,6 +73,8 @@ BEGIN_C_DECLS
#define OSM_SUBNET_VECTOR_CAPACITY 256
+struct _osm_opensm_t;
+
/****h* OpenSM/Subnet
* NAME
* Subnet
@@ -220,6 +222,7 @@ typedef struct _osm_subn_opt
uint8_t log_flags;
char * dump_files_dir;
char * log_file;
+ const char * partition_config_file;
boolean_t accum_log_file;
boolean_t console;
cl_map_t port_prof_ignore_guids;
@@ -399,6 +402,7 @@ typedef struct _osm_subn_opt
*/
typedef struct _osm_subn
{
+ struct _osm_opensm_t *p_osm;
cl_qmap_t sw_guid_tbl;
cl_qmap_t node_guid_tbl;
cl_qmap_t port_guid_tbl;
@@ -644,6 +648,7 @@ osm_subn_destroy(
ib_api_status_t
osm_subn_init(
IN osm_subn_t* const p_subn,
+ IN struct _osm_opensm_t * const p_osm,
IN const osm_subn_opt_t* const p_opt );
/*
* PARAMETERS
diff --git a/osm/opensm/Makefile.am b/osm/opensm/Makefile.am
index 1c63180..4014ea7 100644
--- a/osm/opensm/Makefile.am
+++ b/osm/opensm/Makefile.am
@@ -81,6 +81,7 @@ opensm_SOURCES = main.c osm_console.c os
osm_state_mgr_ctrl.c osm_subnet.c \
osm_sweep_fail_ctrl.c osm_sw_info_rcv.c \
osm_sw_info_rcv_ctrl.c osm_switch.c \
+ osm_prtn.c osm_prtn_config.c \
osm_trap_rcv.c osm_trap_rcv_ctrl.c \
osm_ucast_mgr.c osm_ucast_updn.c \
osm_vl15intf.c osm_vl_arb_rcv.c\
diff --git a/osm/opensm/main.c b/osm/opensm/main.c
index b8ecd52..efb278d 100644
--- a/osm/opensm/main.c
+++ b/osm/opensm/main.c
@@ -224,6 +224,10 @@ show_usage(void)
" This option will cause deletion of the log file\n"
" (if it previously exists). By default, the log file\n"
" is accumulative.\n\n");
+ printf( "-P\n"
+ "--Pconfig\n"
+ " This option defines the optional partition configurationi file.\n"
+ " The default name is \'" OSM_DEFAULT_PARTITION_CONFIG_FILE "\'.\n\n");
printf( "-y\n"
"--stay_on_fatal\n"
" This option will cause SM not to exit on fatal initialization\n"
@@ -511,7 +515,7 @@ main(
boolean_t cache_options = FALSE;
char *ignore_guids_file_name = NULL;
uint32_t val;
- const char * const short_option = "i:f:ed:g:l:s:t:a:uvVhorcy";
+ const char * const short_option = "i:f:ed:g:l:s:t:a:P:uvVhorcy";
/*
In the array below, the 2nd parameter specified the number
@@ -532,6 +536,7 @@ main(
{ "D", 1, NULL, 'D'},
{ "log_file", 1, NULL, 'f'},
{ "erase_log_file",0, NULL, 'e'},
+ { "Pconfig", 1, NULL, 'P'},
{ "maxsmps", 1, NULL, 'n'},
{ "console", 0, NULL, 'q'},
{ "V", 0, NULL, 'V'},
@@ -719,6 +724,10 @@ main(
printf(" Creating new log file\n");
break;
+ case 'P':
+ opt.partition_config_file = optarg;
+ break;
+
case 'y':
opt.exit_on_fatal = FALSE;
printf(" Staying on fatal initialization errors\n");
diff --git a/osm/opensm/osm_opensm.c b/osm/opensm/osm_opensm.c
index 54d0ae3..06a04e5 100644
--- a/osm/opensm/osm_opensm.c
+++ b/osm/opensm/osm_opensm.c
@@ -215,7 +215,7 @@ osm_opensm_init(
if( status != IB_SUCCESS )
goto Exit;
- status = osm_subn_init( &p_osm->subn, p_opt );
+ status = osm_subn_init( &p_osm->subn, p_osm, p_opt );
if( status != IB_SUCCESS )
goto Exit;
diff --git a/osm/opensm/osm_pkey_mgr.c b/osm/opensm/osm_pkey_mgr.c
index 14ed2db..3be7619 100644
--- a/osm/opensm/osm_pkey_mgr.c
+++ b/osm/opensm/osm_pkey_mgr.c
@@ -56,6 +56,7 @@
#include <complib/cl_debug.h>
#include <opensm/osm_node.h>
#include <opensm/osm_pkey_mgr.h>
+#include <opensm/osm_partition.h>
/**********************************************************************
**********************************************************************/
@@ -107,121 +108,262 @@ osm_pkey_mgr_init(
/**********************************************************************
**********************************************************************/
-boolean_t
+static ib_api_status_t
+osm_pkey_mgr_update_pkey_entry(
+ IN const osm_pkey_mgr_t * const p_mgr,
+ IN const osm_physp_t * p_physp,
+ IN const ib_pkey_table_t * block,
+ IN const uint16_t block_index )
+{
+ osm_madw_context_t context;
+ osm_node_t *p_node = osm_physp_get_node_ptr( p_physp );
+ uint32_t attr_mod;
+
+ context.pkey_context.node_guid = osm_node_get_node_guid( p_node );
+ context.pkey_context.port_guid = osm_physp_get_port_guid( p_physp );
+ context.pkey_context.set_method = TRUE;
+ attr_mod = block_index;
+ if ( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH )
+ attr_mod |= osm_physp_get_port_num( p_physp ) << 16;
+ return osm_req_set( p_mgr->p_req, osm_physp_get_dr_path_ptr( p_physp ),
+ ( uint8_t * ) block, sizeof( *block ),
+ IB_MAD_ATTR_P_KEY_TABLE,
+ cl_hton32( attr_mod ), CL_DISP_MSGID_NONE, &context );
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+/*
+ * Send a new entry for the pkey table for this port when this pkey
+ * does not exist. Update existed entry when membership was changed.
+ */
+
+static boolean_t
__osm_pkey_mgr_process_physical_port(
IN const osm_pkey_mgr_t * const p_mgr,
- IN osm_node_t * p_node,
- IN uint8_t port_num,
+ IN const ib_net16_t pkey,
IN osm_physp_t * p_physp )
{
- boolean_t return_val = FALSE; /* TRUE if IB_DEFAULT_PKEY was inserted */
- osm_madw_context_t context;
+ boolean_t return_val = FALSE; /* TRUE if pkey was inserted or updated */
+ ib_api_status_t status;
+ osm_node_t *p_node = osm_physp_get_node_ptr( p_physp );
ib_pkey_table_t *block = NULL;
uint16_t block_index;
uint16_t num_of_blocks;
const osm_pkey_tbl_t *p_pkey_tbl;
- uint32_t attr_mod;
+ ib_net16_t *p_orig_pkey;
uint32_t i;
- ib_net16_t pkey;
- ib_api_status_t status;
- boolean_t block_with_empty_entry_found;
+ boolean_t block_found = FALSE;
OSM_LOG_ENTER( p_mgr->p_log, __osm_pkey_mgr_process_physical_port );
- /*
- * Send a new entry for the pkey table for this node that includes
- * IB_DEFAULT_PKEY when IB_DEFAULT_PARTIAL_PKEY or IB_DEFAULT_PKEY
- * don't exist
- */
- if ( ( osm_physp_has_pkey( p_mgr->p_log,
- IB_DEFAULT_PKEY,
- p_physp ) == FALSE ) &&
- ( osm_physp_has_pkey( p_mgr->p_log,
- IB_DEFAULT_PARTIAL_PKEY, p_physp ) == FALSE ) )
- {
- context.pkey_context.node_guid = osm_node_get_node_guid( p_node );
- context.pkey_context.port_guid = osm_physp_get_port_guid( p_physp );
- context.pkey_context.set_method = TRUE;
-
- p_pkey_tbl = osm_physp_get_pkey_tbl( p_physp );
- num_of_blocks = osm_pkey_tbl_get_num_blocks( p_pkey_tbl );
- block_with_empty_entry_found = FALSE;
+ p_pkey_tbl = osm_physp_get_pkey_tbl( p_physp );
+ num_of_blocks = osm_pkey_tbl_get_num_blocks( p_pkey_tbl );
+ p_orig_pkey = cl_map_get( &p_pkey_tbl->keys, ib_pkey_get_base( pkey ) );
+
+ if ( p_orig_pkey && *p_orig_pkey == pkey )
+ {
+ if ( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_pkey_mgr_process_physical_port: "
+ "No need to insert %04x for node 0x%016" PRIx64
+ " port %u\n",
+ cl_ntoh16( pkey ),
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ osm_physp_get_port_num( p_physp ) );
+ }
+ goto _done;
+ }
+ else if ( !p_orig_pkey )
+ {
for ( block_index = 0; block_index < num_of_blocks; block_index++ )
{
block = osm_pkey_tbl_block_get( p_pkey_tbl, block_index );
for ( i = 0; i < IB_NUM_PKEY_ELEMENTS_IN_BLOCK; i++ )
{
- pkey = block->pkey_entry[i];
- if ( ib_pkey_is_invalid( pkey ) )
+ if ( ib_pkey_is_invalid( block->pkey_entry[i] ) )
{
- block->pkey_entry[i] = IB_DEFAULT_PKEY;
- block_with_empty_entry_found = TRUE;
+ block->pkey_entry[i] = pkey;
+ block_found = TRUE;
break;
}
}
- if ( block_with_empty_entry_found )
+ if ( block_found )
{
break;
}
}
-
- if ( block_with_empty_entry_found == FALSE )
- {
- osm_log( p_mgr->p_log, OSM_LOG_ERROR,
- "__osm_pkey_mgr_process_physical_port: ERR 0501: "
- "No empty entry was found to insert IB_DEFAULT_PKEY for node "
- "0x%016" PRIx64 " and port %u\n",
- cl_ntoh64( osm_node_get_node_guid( p_node ) ), port_num );
- }
- else
+ }
+ else
+ {
+ *p_orig_pkey = pkey;
+ for ( block_index = 0; block_index < num_of_blocks; block_index++ )
{
- /* Building the attribute modifier */
- if ( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH )
- {
- /* Port num | Block Index */
- attr_mod = port_num << 16 | block_index;
- }
- else
+ 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 )
{
- attr_mod = block_index;
+ block_found = TRUE;
+ break;
}
+ }
+ }
+
+ if ( block_found == FALSE )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_pkey_mgr_process_physical_port: ERR 0501: "
+ "No empty entry was found to insert %04x for node "
+ "0x%016" PRIx64 " and port %u\n",
+ cl_ntoh16( pkey ),
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ osm_physp_get_port_num( p_physp ) );
+ goto _done;
+ }
- status = osm_req_set( p_mgr->p_req,
- osm_physp_get_dr_path_ptr( p_physp ),
- ( uint8_t * ) block,
- sizeof( *block ),
- IB_MAD_ATTR_P_KEY_TABLE,
- cl_hton32( attr_mod ),
- CL_DISP_MSGID_NONE, &context );
- return_val = TRUE; /*IB_DEFAULT_PKEY was inserted */
+ status =
+ osm_pkey_mgr_update_pkey_entry( p_mgr, p_physp, block, block_index );
- if ( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
- {
- osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
- "__osm_pkey_mgr_process_physical_port: "
- "IB_DEFAULT_PKEY was inserted for node 0x%016" PRIx64
+ if ( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_pkey_mgr_process_physical_port: "
+ "osm_pkey_mgr_update_pkey_entry() failed to update "
+ "pkey table block %d for node 0x%016" PRIx64 " and port %u\n",
+ block_index,
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ osm_physp_get_port_num( p_physp ) );
+ goto _done;
+ }
+
+ return_val = TRUE; /* pkey was inserted/updated */
+
+ if ( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_pkey_mgr_process_physical_port: "
+ "%04x was inserted for node 0x%016" PRIx64
+ " and port %u\n",
+ cl_ntoh16( pkey ),
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ osm_physp_get_port_num( p_physp ) );
+ }
+
+ _done:
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return ( return_val );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+static void
+osm_pkey_mgr_update_peer_port(
+ const osm_pkey_mgr_t * const p_mgr,
+ const osm_port_t * const p_port )
+{
+ osm_physp_t *p, *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;
+ uint16_t block_index;
+ uint16_t num_of_blocks;
+ ib_api_status_t status = IB_SUCCESS;
+
+ p = osm_port_get_default_phys_ptr( p_port );
+ if ( !osm_physp_is_valid( p ) )
+ return;
+ peer = osm_physp_get_remote( p );
+ if ( !peer || !osm_physp_is_valid( peer ) )
+ return;
+ p_node = osm_physp_get_node_ptr( peer );
+ if ( osm_node_get_type( p_node ) == IB_NODE_TYPE_CA )
+ return;
+
+ 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++ )
+ {
+ block = osm_pkey_tbl_block_get( p_pkey_tbl, block_index );
+ peer_block = osm_pkey_tbl_block_get( p_peer_pkey_tbl, block_index );
+ if ( cl_memcmp( peer_block, block, sizeof( *block ) ) )
+ {
+ cl_memcpy( peer_block, block, sizeof( *block ) );
+ status =
+ osm_pkey_mgr_update_pkey_entry( p_mgr, peer, peer_block,
+ block_index );
+ if ( status != IB_SUCCESS )
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_pkey_mgr_update_peer_port: "
+ "osm_pkey_mgr_update_pkey_entry() failed to update "
+ "pkey table block %d for node 0x%016" PRIx64
" and port %u\n",
+ block_index,
cl_ntoh64( osm_node_get_node_guid( p_node ) ),
- port_num );
- }
+ osm_physp_get_port_num( peer ) );
}
}
- else
+
+ if ( num_of_blocks && status == IB_SUCCESS &&
+ osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
{
- /* default key or partial default key already exist */
- if ( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "osm_pkey_mgr_update_peer_port: "
+ "pkey table was updated for node 0x%016" PRIx64
+ " and port %u\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ osm_physp_get_port_num( peer ) );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t
+osm_pkey_mgr_process_partition_table(
+ const osm_pkey_mgr_t * const p_mgr,
+ const osm_prtn_t * const 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;
+ boolean_t result = FALSE;
+
+ 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 ) &&
+ __osm_pkey_mgr_process_physical_port( p_mgr, pkey, p_physp ) )
{
- osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
- "__osm_pkey_mgr_process_physical_port: "
- "No need to insert IB_DEFAULT_PKEY for node 0x%016" PRIx64
- " port %u\n",
- cl_ntoh64( osm_node_get_node_guid( p_node ) ), port_num );
+ result = TRUE;
+ if ( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "osm_pkey_mgr_process_partition_table: "
+ "Adding %04x for pkey table of node "
+ "0x%016" PRIx64 " port %u\n",
+ cl_ntoh16( pkey ),
+ cl_ntoh64( osm_node_get_node_guid
+ ( osm_physp_get_node_ptr( p_physp ) ) ),
+ osm_physp_get_port_num( p_physp ) );
}
}
- OSM_LOG_EXIT( p_mgr->p_log );
- return ( return_val );
+ return result;
}
/**********************************************************************
@@ -230,51 +372,56 @@ osm_signal_t
osm_pkey_mgr_process(
IN const osm_pkey_mgr_t * const p_mgr )
{
- cl_qmap_t *p_node_guid_tbl;
- osm_node_t *p_node;
- osm_node_t *p_next_node;
- uint8_t port_num;
- osm_physp_t *p_physp;
+ cl_qmap_t *p_tbl;
+ cl_map_item_t *p_next;
+ osm_prtn_t *p_prtn;
+ osm_port_t *p_port;
osm_signal_t result = OSM_SIGNAL_DONE;
CL_ASSERT( p_mgr );
OSM_LOG_ENTER( p_mgr->p_log, osm_pkey_mgr_process );
- p_node_guid_tbl = &p_mgr->p_subn->node_guid_tbl;
-
CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock );
- p_next_node = ( osm_node_t * ) cl_qmap_head( p_node_guid_tbl );
- while ( p_next_node != ( osm_node_t * ) cl_qmap_end( p_node_guid_tbl ) )
+ if ( osm_prtn_make_partitions( p_mgr->p_log, p_mgr->p_subn ) !=
+ IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR, "osm_pkey_mgr_process: "
+ "osm_prtn_make_partitions() is failed.\n" );
+ goto _err;
+ }
+
+ p_tbl = &p_mgr->p_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 );
+
+ if ( osm_pkey_mgr_process_partition_table( p_mgr, p_prtn, FALSE ) )
+ result = OSM_SIGNAL_DONE_PENDING;
+ if ( osm_pkey_mgr_process_partition_table( p_mgr, p_prtn, TRUE ) )
+ result = OSM_SIGNAL_DONE_PENDING;
+ }
+
+ p_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+ p_next = cl_qmap_head( p_tbl );
+ while ( p_next != cl_qmap_end( p_tbl ) )
{
- p_node = p_next_node;
- p_next_node = ( osm_node_t * ) cl_qmap_next( &p_next_node->map_item );
+ p_port = ( osm_port_t * ) p_next;
+ p_next = cl_qmap_next( p_next );
- for ( port_num = 0; port_num < osm_node_get_num_physp( p_node );
- port_num++ )
+ if ( osm_node_get_type( osm_port_get_parent_node( p_port ) ) !=
+ IB_NODE_TYPE_SWITCH )
{
- p_physp = osm_node_get_physp_ptr( p_node, port_num );
- if ( osm_physp_is_valid( p_physp ) )
- {
- if ( __osm_pkey_mgr_process_physical_port
- ( p_mgr, p_node, port_num, p_physp ) )
- {
- if ( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
- {
- osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
- "osm_pkey_mgr_process: "
- "Adding IB_DEFAULT_PKEY for pkey table of node "
- "0x%016" PRIx64 " port %u\n",
- cl_ntoh64( osm_node_get_node_guid( p_node ) ),
- port_num );
- }
- result = OSM_SIGNAL_DONE_PENDING;
- }
- }
+ osm_pkey_mgr_update_peer_port( p_mgr, p_port );
}
}
+ _err:
CL_PLOCK_RELEASE( p_mgr->p_lock );
OSM_LOG_EXIT( p_mgr->p_log );
return ( result );
diff --git a/osm/opensm/osm_prtn.c b/osm/opensm/osm_prtn.c
new file mode 100644
index 0000000..64fc1b4
--- /dev/null
+++ b/osm/opensm/osm_prtn.c
@@ -0,0 +1,325 @@
+/*
+ * Copyright (c) 2006 Voltaire, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_prtn_t.
+ * This object represents an IBA partition.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision$
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <stdio.h>
+
+#include <iba/ib_types.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_partition.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_sa.h>
+#include <opensm/osm_multicast.h>
+
+
+extern int osm_prtn_config_parse_file(osm_log_t * const p_log,
+ osm_subn_t * const p_subn,
+ const char *file_name);
+
+
+static uint16_t global_pkey_counter;
+
+/*
+ *
+ */
+
+osm_prtn_t* osm_prtn_new(
+ IN const char *name,
+ IN const uint16_t pkey )
+{
+ osm_prtn_t *p = cl_zalloc(sizeof(*p));
+ if (!p)
+ return NULL;
+ p->pkey = pkey;
+ cl_map_construct(&p->full_guid_tbl);
+ cl_map_init(&p->full_guid_tbl, 32);
+ cl_map_construct(&p->part_guid_tbl);
+ cl_map_init(&p->part_guid_tbl, 32);
+
+ if (name && *name)
+ strncpy(p->name, name, sizeof(p->name));
+ else
+ snprintf(p->name, sizeof(p->name), "%04x", cl_ntoh16(pkey));
+
+ return p;
+}
+
+void osm_prtn_delete(
+ IN OUT osm_prtn_t** const pp_prtn )
+{
+ osm_prtn_t *p = *pp_prtn;
+ cl_map_remove_all(&p->full_guid_tbl);
+ cl_map_destroy(&p->full_guid_tbl);
+ cl_map_remove_all(&p->part_guid_tbl);
+ cl_map_destroy(&p->part_guid_tbl);
+ cl_free(p);
+ *pp_prtn = NULL;
+}
+
+
+ib_api_status_t osm_prtn_add_port(osm_log_t *p_log, osm_subn_t *p_subn,
+ osm_prtn_t *p, ib_net64_t guid, boolean_t full)
+{
+ cl_qmap_t *p_port_tbl = &p_subn->port_guid_tbl;
+ ib_api_status_t status = IB_SUCCESS;
+ cl_map_t *p_tbl;
+ osm_port_t *p_port;
+ osm_physp_t *p_physp;
+
+ p_port = (osm_port_t *)cl_qmap_get(p_port_tbl, guid);
+ if (!p_port || p_port == (osm_port_t *)cl_qmap_end(p_port_tbl)) {
+ osm_log(p_log, OSM_LOG_VERBOSE, "osm_prtn_add_port: "
+ "port 0x%" PRIx64 " not found.\n",
+ cl_ntoh64(guid));
+ return status;
+ }
+
+ p_physp = osm_port_get_default_phys_ptr(p_port);
+ if (!p_physp) {
+ osm_log(p_log, OSM_LOG_VERBOSE, "osm_prtn_add_port: "
+ "no physical for port 0x%" PRIx64 "\n",
+ cl_ntoh64(guid));
+ return status;
+ }
+
+ if (osm_prtn_is_guid(p, guid)) {
+ osm_log(p_log, OSM_LOG_VERBOSE, "osm_prtn_add_port: "
+ "port 0x%" PRIx64 " already in "
+ "partition \'%s\' (%04x). Will overwrite.\n",
+ cl_ntoh64(guid), p->name, cl_ntoh16(p->pkey));
+ }
+
+ p_tbl = (full == TRUE) ? &p->full_guid_tbl : &p->part_guid_tbl ;
+
+ if (cl_map_insert(p_tbl, guid, p_physp) == NULL)
+ return IB_INSUFFICIENT_MEMORY;
+
+ return status;
+}
+
+
+ib_api_status_t osm_prtn_add_all(osm_log_t *p_log, osm_subn_t *p_subn,
+ osm_prtn_t *p, boolean_t full)
+{
+ cl_qmap_t *p_port_tbl = &p_subn->port_guid_tbl;
+ cl_map_item_t *p_item;
+ osm_port_t *p_port;
+ ib_api_status_t status = IB_SUCCESS;
+
+ p_item = cl_qmap_head(p_port_tbl);
+ while (p_item != cl_qmap_end(p_port_tbl)) {
+ p_port = (osm_port_t *)p_item;
+ p_item = cl_qmap_next(p_item);
+ status = osm_prtn_add_port(p_log, p_subn, p,
+ osm_port_get_guid(p_port), full);
+ if (status != IB_SUCCESS)
+ goto _err;
+ }
+
+ _err:
+ return status;
+}
+
+
+ib_api_status_t osm_prtn_add_mcgroup(osm_log_t *p_log,
+ osm_subn_t *p_subn, osm_prtn_t *p,
+ unsigned is_ipoib, uint8_t rate, uint8_t mtu)
+{
+ ib_member_rec_t mc_rec;
+ ib_net64_t comp_mask;
+ ib_net16_t pkey;
+ osm_mgrp_t *p_mgrp = NULL;
+ osm_sa_t *p_sa = &p_subn->p_osm->sa;
+ ib_api_status_t status = IB_SUCCESS;
+
+ pkey = is_ipoib ? cl_hton16(cl_ntoh16(p->pkey)|0x8000) : p->pkey;
+
+ cl_memclr(&mc_rec, sizeof(mc_rec));
+
+ mc_rec.mgid = osm_ipoib_mgid; /* this is ipv4 broadcast */
+ cl_memcpy(&mc_rec.mgid.raw[4], &pkey, sizeof(pkey));
+
+ mc_rec.qkey = CL_HTON32(0x0b1b);
+ mc_rec.mtu = mtu ? mtu : 4; /* 2048 Bytes */
+ mc_rec.tclass = 0;
+ mc_rec.pkey = pkey;
+ mc_rec.rate = rate ? rate : 0x3; /* 10Gb/sec */
+ mc_rec.pkt_life = OSM_DEFAULT_SUBNET_TIMEOUT;
+ mc_rec.sl_flow_hop = OSM_DEFAULT_SL << 28;
+ /* Note: scope needs to be consistent with MGID */
+ mc_rec.scope_state = 0x21;
+
+ /* don't update rate, mtu */
+ comp_mask = IB_MCR_COMPMASK_MTU | IB_MCR_COMPMASK_RATE;
+
+ status = osm_mcmr_rcv_find_or_create_new_mgrp(&p_sa->mcmr_rcv,
+ comp_mask, &mc_rec, &p_mgrp);
+
+ if (!p_mgrp || status != IB_SUCCESS)
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_prtn_add_mcgroup:"
+ " failed to create mc group with %04x pkey\n",
+ cl_ntoh16(pkey));
+
+ return status;
+}
+
+
+static uint16_t __generate_pkey(osm_subn_t *p_subn)
+{
+ uint16_t pkey;
+ cl_qmap_t *m = &p_subn->prtn_pkey_tbl;
+ while ( global_pkey_counter < cl_ntoh16(IB_DEFAULT_PARTIAL_PKEY) - 1) {
+ pkey = ++global_pkey_counter;
+ pkey = cl_hton16(pkey);
+ if (cl_qmap_get(m, pkey) == cl_qmap_end(m))
+ return pkey;
+ }
+ return 0;
+}
+
+osm_prtn_t *osm_prtn_make_new(osm_log_t *p_log, osm_subn_t *p_subn,
+ const char *name, uint16_t pkey)
+{
+ osm_prtn_t *p = NULL, *p_check;
+
+ if (pkey == 0 && !(pkey = __generate_pkey(p_subn)))
+ return NULL;
+
+ if (cl_ntoh16(pkey)&0x8000) {
+ pkey = cl_hton16(cl_ntoh16(pkey)&~0x8000);
+ osm_log(p_log, OSM_LOG_VERBOSE,
+ "osm_prtn_make_new: pkey was striped for"
+ " partition \'%s\' (%04x)\n",
+ name, cl_ntoh16(pkey));
+ }
+
+ p = osm_prtn_new(name, pkey);
+ if (!p) {
+ osm_log(p_log, OSM_LOG_ERROR,
+ "osm_prtn_make_new: Unable to create"
+ " partition \'%s\' (%04x)\n",
+ name, cl_ntoh16(pkey));
+ return NULL;
+ }
+
+ p_check = (osm_prtn_t *)cl_qmap_insert(&p_subn->prtn_pkey_tbl,
+ p->pkey, &p->map_item);
+ if (p != p_check) {
+ osm_log(p_log, OSM_LOG_VERBOSE,
+ "osm_prtn_make_new: Duplicated partition"
+ " definition: \'%s\' (%04x) prev name \'%s\'"
+ " - will use it.\n",
+ name, cl_ntoh16(pkey), p_check->name);
+ osm_prtn_delete(&p);
+ p = p_check;
+ }
+
+ return p;
+}
+
+
+static ib_api_status_t osm_prtn_make_default(osm_log_t * const p_log,
+ osm_subn_t * const p_subn)
+{
+ ib_api_status_t status = IB_UNKNOWN_ERROR;
+ osm_prtn_t *p;
+ p = osm_prtn_make_new(p_log, p_subn,
+ "Default", IB_DEFAULT_PARTIAL_PKEY);
+ if (!p)
+ goto _err;
+ status = osm_prtn_add_all(p_log, p_subn, p, FALSE);
+ if (status != IB_SUCCESS)
+ goto _err;;
+ cl_map_remove(&p->part_guid_tbl, p_subn->sm_port_guid);
+ status = osm_prtn_add_port(p_log, p_subn, p,
+ p_subn->sm_port_guid, TRUE);
+ _err:
+ return status;
+}
+
+
+ib_api_status_t osm_prtn_make_partitions(osm_log_t * const p_log,
+ osm_subn_t * const p_subn)
+{
+ const char *file_name;
+ ib_api_status_t status = IB_SUCCESS;
+ osm_prtn_t *p, *p_next;
+
+ file_name = p_subn->opt.partition_config_file ?
+ p_subn->opt.partition_config_file :
+ "/etc/osm-partitions.conf";
+
+ /* cl_qmap uses self addresses we cannot just save
+ qmap state and clean it later, so clean all now */
+ p_next = (osm_prtn_t *)cl_qmap_head(&p_subn->prtn_pkey_tbl);
+ while (p_next != (osm_prtn_t *)cl_qmap_end(&p_subn->prtn_pkey_tbl)) {
+ p = p_next;
+ p_next = (osm_prtn_t *)cl_qmap_next(&p->map_item);
+ osm_prtn_delete(&p);
+ }
+ cl_qmap_init(&p_subn->prtn_pkey_tbl);
+
+ global_pkey_counter = 0;
+
+ status = osm_prtn_make_default(p_log, p_subn);
+ if(status != IB_SUCCESS)
+ goto _err;
+
+ if (osm_prtn_config_parse_file(p_log, p_subn, file_name)) {
+ osm_log(p_log, OSM_LOG_VERBOSE,
+ "osm_prtn_make_partitions: Partition configuration "
+ "was not fully processed.\n");
+ }
+
+ _err:
+ return status;
+}
diff --git a/osm/opensm/osm_prtn_config.c b/osm/opensm/osm_prtn_config.c
new file mode 100644
index 0000000..8b8a945
--- /dev/null
+++ b/osm/opensm/osm_prtn_config.c
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 2006 Voltaire, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of opensm partition management configuration
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision$
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include <iba/ib_types.h>
+#include <opensm/osm_partition.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+
+
+#if __WORDSIZE == 64
+#define STRTO_IB_NET64(str, end, base) strtoul(str, end, base)
+#else
+#define STRTO_IB_NET64(str, end, base) strtoull(str, end, base)
+#endif
+
+#define PARSERR(log, lnum, fmt, arg...) { \
+ osm_log(log, OSM_LOG_ERROR, \
+ "\nPARSE ERROR: line %d: " fmt "\n", (lnum), ##arg ); \
+ fprintf(stderr, \
+ "\nPARSE ERROR: line %d: " fmt "\n", (lnum), ##arg ); \
+}
+
+#define PARSEWARN(log, lnum, fmt, arg...) \
+ osm_log(log, OSM_LOG_VERBOSE, \
+ "PARSE WARN: line %d: " fmt , (lnum), ##arg )
+
+/*
+ */
+
+
+struct part_conf {
+ osm_log_t *p_log;
+ osm_subn_t *p_subn;
+ osm_prtn_t *p_prtn;
+ unsigned is_ipoib, mtu, rate;
+};
+
+
+extern osm_prtn_t *osm_prtn_make_new(osm_log_t *p_log, osm_subn_t *p_subn,
+ const char *name, uint16_t pkey);
+extern ib_api_status_t osm_prtn_add_all(osm_log_t *p_log,
+ osm_subn_t *p_subn, osm_prtn_t *p, boolean_t full);
+extern ib_api_status_t osm_prtn_add_port(osm_log_t *p_log,
+ osm_subn_t *p_subn, osm_prtn_t *p, ib_net64_t guid,
+ boolean_t full);
+extern ib_api_status_t osm_prtn_add_mcgroup(osm_log_t *p_log,
+ osm_subn_t *p_subn, osm_prtn_t *p,
+ unsigned is_ipoib, uint8_t rate, uint8_t mtu);
+
+static int partition_create(unsigned lineno, struct part_conf *conf,
+ char *name, char *id, char *flag, char *flag_val)
+{
+ uint16_t pkey;
+
+ if (!id && name && isdigit(*name)) {
+ id = name;
+ name = NULL;
+ }
+
+ if (id) {
+ char *end;
+ pkey = strtoul(id, &end, 0);
+ if (end == id || *end)
+ return -1;
+ }
+ else
+ pkey = 0;
+
+ conf->p_prtn = osm_prtn_make_new(conf->p_log, conf->p_subn,
+ name, cl_hton16(pkey));
+ if (!conf->p_prtn)
+ return -1;
+
+ osm_prtn_add_mcgroup(conf->p_log, conf->p_subn, conf->p_prtn,
+ conf->is_ipoib, conf->rate, conf->mtu);
+
+ return 0;
+}
+
+
+static int partition_add_flag(unsigned lineno, struct part_conf *conf,
+ char *flag, char *val)
+{
+ int len = strlen(flag);
+ if (!strncmp(flag, "ipoib", len)) {
+ conf->is_ipoib = 1;
+ }
+ else if (!strncmp(flag, "mtu", len)) {
+ if (!val || (conf->mtu = strtoul(val, NULL, 0)) == 0)
+ PARSEWARN(conf->p_log, lineno,
+ "flag \'mtu\' requires valid value"
+ " - skipped.\n");
+ }
+ else if (!strncmp(flag, "rate", len)) {
+ if (!val || (conf->rate = strtoul(val, NULL, 0)) == 0)
+ PARSEWARN(conf->p_log, lineno,
+ "flag \'rate\' requires valid value"
+ " - skipped.\n");
+ }
+ else {
+ PARSEWARN(conf->p_log, lineno,
+ "unrecognized partition flag \'%s\'"
+ " - ignored.\n", flag);
+ }
+ return 0;
+}
+
+
+static int partition_add_port(unsigned lineno, struct part_conf *conf,
+ char *name, char *flag)
+{
+ osm_prtn_t *p = conf->p_prtn;
+ ib_net64_t guid;
+ boolean_t full = FALSE;
+
+ if (!name || !*name || !strncmp(name, "NONE", strlen(name)))
+ return 0;
+
+ if (flag) {
+ if(!strncmp(flag, "full", strlen(flag)))
+ full = TRUE;
+ else if(strncmp(flag, "partial", strlen(flag))) {
+ PARSEWARN(conf->p_log, lineno,
+ "unrecognized port flag \'%s\' -"
+ " suppose \'partial\'\n", flag);
+ }
+ }
+
+ if (!strncmp(name, "ALL", strlen(name))) {
+ return osm_prtn_add_all(conf->p_log, conf->p_subn, p,
+ full) == IB_SUCCESS ? 0 : -1;
+ }
+ else if (!strncmp(name, "SELF", strlen(name))) {
+ guid = cl_ntoh64(conf->p_subn->sm_port_guid);
+ }
+ else {
+ char *end;
+ guid = STRTO_IB_NET64(name, &end, 0);
+ if (!guid || *end)
+ return -1;
+ }
+
+ if (osm_prtn_add_port(conf->p_log, conf->p_subn, p,
+ cl_hton64(guid), full) != IB_SUCCESS)
+ return -1;
+
+ return 0;
+}
+
+
+/* conf file parser */
+
+#define STRIP_HEAD_SPACES(p) while (*(p) == ' ' || *(p) == '\t' || \
+ *(p) == '\n') { (p)++; }
+#define STRIP_TAIL_SPACES(p) { char *q = (p) + strlen(p); \
+ while ( q != (p) && ( *q == '\0' || \
+ *q == ' ' || *q == '\t' || \
+ *q == '\n')) { *q-- = '\0'; }; }
+
+static int parse_name_token(char *str, char **name, char **val)
+{
+ int len = 0;
+ char *p, *q;
+
+ *name = *val = NULL;
+
+ p = str;
+
+ while (*p == ' ' || *p == '\t' || *p == '\n')
+ p++;
+
+ q = strchr(p, '=');
+ if (q)
+ *q++ = '\0';
+
+ len = strlen(str) + 1;
+ str = q;
+
+ q = p + strlen(p);
+ while ( q != p &&
+ ( *q == '\0' || *q == ' ' || *q == '\t' || *q == '\n'))
+ *q-- = '\0';
+
+ *name = p;
+
+ p = str;
+ if (!p)
+ return len;
+
+ while (*p == ' ' || *p == '\t' || *p == '\n')
+ p++;
+
+ q = p + strlen(p);
+ len += q - str + 1;
+ while ( q != p &&
+ ( *q == '\0' || *q == ' ' || *q == '\t' || *q == '\n'))
+ *q-- = '\0';
+ *val = p;
+
+ return len;
+}
+
+
+static struct part_conf *new_part_conf(osm_log_t *p_log, osm_subn_t *p_subn)
+{
+ static struct part_conf part;
+ struct part_conf *conf = ∂
+ memset(conf, 0, sizeof(*conf));
+ conf->p_log = p_log;
+ conf->p_subn = p_subn;
+ conf->p_prtn = NULL;
+ return conf;
+}
+
+static int flush_part_conf(struct part_conf *conf)
+{
+ memset(conf, 0, sizeof(*conf));
+ return 0;
+}
+
+
+static int parse_part_conf(struct part_conf *conf, char *str, int lineno)
+{
+ int ret, len = 0;
+ char *name, *id, *flag, *flval;
+ char *q, *p;
+
+ p = str;
+ if (*p == '\t' || *p == '\0' || *p == '\n')
+ p++;
+
+ len += p - str;
+ str = p;
+
+ if (conf->p_prtn)
+ goto skip_header;
+
+ q = strchr(p, ':');
+ if (!q) {
+ PARSERR(conf->p_log, lineno,
+ "no partition definition found\n");
+ return -1;
+ }
+
+ *q++ = '\0';
+ str = q;
+
+ name = id = flag = flval = NULL;
+
+ q = strchr(p, ',');
+ if (q)
+ *q = '\0';
+
+ ret = parse_name_token(p, &name, &id);
+ p += ret;
+ len += ret;
+
+ while (q) {
+ flag = flval = NULL;
+ q = strchr(p, ',');
+ if (q)
+ *q++ = '\0';
+ ret = parse_name_token(p, &flag, &flval);
+ if (!flag) {
+ PARSERR(conf->p_log, lineno,
+ "bad partition flags\n");
+ return -1;
+ }
+ p += ret;
+ len += ret;
+ partition_add_flag(lineno, conf, flag, flval);
+ }
+
+ if (p != str || (partition_create(lineno, conf,
+ name, id, flag, flval) < 0)) {
+ PARSERR(conf->p_log, lineno,
+ "bad partition definition\n");
+ return -1;
+ }
+
+ skip_header:
+ do {
+ name = flag = NULL;
+ q = strchr(p, ',');
+ if (q)
+ *q++ = '\0';
+ ret = parse_name_token(p, &name, &flag);
+ if (partition_add_port(lineno, conf, name, flag) < 0) {
+ PARSERR(conf->p_log, lineno,
+ "bad PortGUID\n");
+ return -1;
+ }
+ p += ret;
+ len += ret;
+ } while (q);
+
+ return len;
+}
+
+int osm_prtn_config_parse_file(osm_log_t *p_log, osm_subn_t *p_subn,
+ const char *file_name)
+{
+ char line[1024];
+ struct part_conf *conf = NULL;
+ FILE *file;
+ int lineno;
+
+ file = fopen(file_name, "r");
+ if (!file) {
+ osm_log(p_log, OSM_LOG_VERBOSE,
+ "osm_prtn_config_parse_file: "
+ "cannot open config file \'%s\': %s\n",
+ file_name, strerror(errno));
+ return -1;
+ }
+
+ lineno = 0;
+
+ while (fgets(line, sizeof(line) - 1, file) != NULL) {
+ char *q, *p = line;
+
+ lineno++;
+
+ p = line;
+
+ q = strchr(p, '#');
+ if (q)
+ *q = '\0';
+
+ do {
+ int len;
+ while (*p == ' ' || *p == '\t' || *p == '\n')
+ p++;
+ if (*p == '\0')
+ break;
+
+ if (!conf &&
+ !(conf = new_part_conf(p_log, p_subn))) {
+ PARSERR(p_log, lineno,
+ "internal: cannot create config.\n");
+ break;
+ }
+
+ q = strchr(p, ';');
+ if (q)
+ *q = '\0';
+
+ len = parse_part_conf(conf, p, lineno);
+ if (len < 0) {
+ break;
+ }
+
+ p += len;
+
+ if (q) {
+ flush_part_conf(conf);
+ conf = NULL;
+ }
+ } while (q);
+ }
+
+ fclose(file);
+
+ return 0;
+}
diff --git a/osm/opensm/osm_sa_mcmember_record.c b/osm/opensm/osm_sa_mcmember_record.c
index 2c63adb..d41dc5a 100644
--- a/osm/opensm/osm_sa_mcmember_record.c
+++ b/osm/opensm/osm_sa_mcmember_record.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
* Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
* Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
*
@@ -1217,6 +1217,24 @@ __mgrp_request_is_realizable(
}
/**********************************************************************
+ Call this function to find or create a new mgrp.
+**********************************************************************/
+ib_api_status_t
+osm_mcmr_rcv_find_or_create_new_mgrp(
+ IN osm_mcmr_recv_t* const p_rcv,
+ IN ib_net64_t comp_mask,
+ IN ib_member_rec_t* const p_recvd_mcmember_rec,
+ OUT osm_mgrp_t **pp_mgrp)
+{
+ ib_api_status_t status;
+ status = __get_mgrp_by_mgid(p_rcv, p_recvd_mcmember_rec, pp_mgrp);
+ if (status == IB_SUCCESS)
+ return status;
+ return osm_mcmr_rcv_create_new_mgrp(p_rcv, comp_mask,
+ p_recvd_mcmember_rec, NULL, pp_mgrp);
+}
+
+/**********************************************************************
Call this function to create a new mgrp.
**********************************************************************/
ib_api_status_t
diff --git a/osm/opensm/osm_subnet.c b/osm/opensm/osm_subnet.c
index 5bc84a7..df185c5 100644
--- a/osm/opensm/osm_subnet.c
+++ b/osm/opensm/osm_subnet.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
* Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
* Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
*
@@ -53,11 +53,13 @@
#include <complib/cl_debug.h>
#include <opensm/osm_subnet.h>
+#include <opensm/osm_opensm.h>
#include <opensm/osm_log.h>
#include <opensm/osm_madw.h>
#include <opensm/osm_port.h>
#include <opensm/osm_switch.h>
#include <opensm/osm_remote_sm.h>
+#include <opensm/osm_partition.h>
#include <opensm/osm_node.h>
#include <opensm/osm_multicast.h>
#include <opensm/osm_inform.h>
@@ -97,6 +99,7 @@ osm_subn_destroy(
osm_port_t *p_port, *p_next_port;
osm_switch_t *p_sw, *p_next_sw;
osm_remote_sm_t *p_rsm, *p_next_rsm;
+ osm_prtn_t *p_prtn, *p_next_prtn;
osm_mgrp_t *p_mgrp, *p_next_mgrp;
osm_infr_t *p_infr, *p_next_infr;
@@ -135,6 +138,14 @@ osm_subn_destroy(
cl_free( p_rsm );
}
+ p_next_prtn = (osm_prtn_t*)cl_qmap_head( &p_subn->prtn_pkey_tbl );
+ while( p_next_prtn != (osm_prtn_t*)cl_qmap_end( &p_subn->prtn_pkey_tbl ) )
+ {
+ p_prtn = p_next_prtn;
+ p_next_prtn = (osm_prtn_t*)cl_qmap_next( &p_prtn->map_item );
+ osm_prtn_delete( &p_prtn );
+ }
+
p_next_mgrp = (osm_mgrp_t*)cl_qmap_head( &p_subn->mgrp_mlid_tbl );
while( p_next_mgrp != (osm_mgrp_t*)cl_qmap_end( &p_subn->mgrp_mlid_tbl ) )
{
@@ -167,10 +178,13 @@ osm_subn_destroy(
ib_api_status_t
osm_subn_init(
IN osm_subn_t* const p_subn,
+ IN osm_opensm_t * const p_osm,
IN const osm_subn_opt_t* const p_opt )
{
cl_status_t status;
+ p_subn->p_osm = p_osm;
+
status = cl_ptr_vector_init( &p_subn->node_lid_tbl,
OSM_SUBNET_VECTOR_MIN_SIZE,
OSM_SUBNET_VECTOR_GROW_SIZE );
@@ -428,6 +442,7 @@ osm_subn_set_default_opt(
p_opt->dump_files_dir = OSM_DEFAULT_TMP_DIR;
p_opt->log_file = OSM_DEFAULT_LOG_FILE;
+ p_opt->partition_config_file = OSM_DEFAULT_PARTITION_CONFIG_FILE;
p_opt->accum_log_file = TRUE;
p_opt->port_profile_switch_nodes = FALSE;
p_opt->max_port_profile = 0xffffffff;
More information about the general
mailing list