[openib-general] [PATCH 1/2] OpenSM: Add support for SA InformInfoRecord

Hal Rosenstock halr at voltaire.com
Tue Dec 5 07:02:03 PST 2006


OpenSM: Add support for SA InformInfoRecord

The following patch adds initial SA InformInfoRecord support into
OpenSM.

Signed-off-by: Hal Rosenstock <halr at voltaire.com>

diff --git a/osm/include/opensm/osm_inform.h b/osm/include/opensm/osm_inform.h
index 40fec93..0bc8810 100644
--- a/osm/include/opensm/osm_inform.h
+++ b/osm/include/opensm/osm_inform.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.
  *
@@ -254,6 +254,72 @@ osm_infr_get_by_rid(
 *	Inform Record, osm_infr_construct, osm_infr_destroy
 *********/
 
+/****f* OpenSM: Inform Record/osm_infr_get_by_gid
+* NAME
+*	osm_infr_get_by_gid
+*
+* DESCRIPTION
+*	Find a matching osm_infr_t in the subnet DB by inform_info_record
+*	subscriber GID
+*
+* SYNOPSIS
+*/
+osm_infr_t*
+osm_infr_get_by_gid(
+	IN osm_subn_t	const	*p_subn,
+	IN osm_log_t	*p_log,
+	IN ib_inform_info_record_t* const p_inf_rec );
+/*
+* PARAMETERS
+*	p_subn 
+*		[in] Pointer to the subnet object
+*
+*	p_log
+*		[in] Pointer to the log object
+*
+*	p_inf_rec
+*		[in] Pointer to an inform_info record with the search
+*		     subscriber GID
+*
+* RETURN
+*	The matching osm_infr_t
+* SEE ALSO
+*	Inform Record, osm_infr_construct, osm_infr_destroy
+*********/
+
+/****f* OpenSM: Inform Record/osm_infr_get_by_enum
+* NAME
+*       osm_infr_get_by_enum
+*
+* DESCRIPTION
+*       Find a matching osm_infr_t in the subnet DB by inform_info_record
+*       subscriber enum 
+*
+* SYNOPSIS
+*/
+osm_infr_t*
+osm_infr_get_by_enum(
+	IN osm_subn_t	const	*p_subn,
+	IN osm_log_t	*p_log,
+	IN ib_inform_info_record_t* const p_inf_rec );
+/*
+* PARAMETERS
+*	p_subn 
+*		[in] Pointer to the subnet object
+*
+*	p_log
+*		[in] Pointer to the log object
+*
+*	p_inf_rec
+*		[in] Pointer to an inform_info record with the search
+*		     subscriber enum 
+*
+* RETURN
+*	The matching osm_infr_t
+* SEE ALSO
+*	Inform Record, osm_infr_construct, osm_infr_destroy
+*********/
+
 /****f* OpenSM: Inform Record/osm_infr_get_by_rec
 * NAME
 *	osm_infr_get_by_rec
diff --git a/osm/include/opensm/osm_msgdef.h b/osm/include/opensm/osm_msgdef.h
index 4439339..73af838 100644
--- a/osm/include/opensm/osm_msgdef.h
+++ b/osm/include/opensm/osm_msgdef.h
@@ -191,6 +191,7 @@ enum
 	OSM_MSG_MAD_VL_ARB,
 	OSM_MSG_MAD_SLVL,
 	OSM_MSG_MAD_GUIDINFO_RECORD,
+	OSM_MSG_MAD_INFORM_INFO_RECORD,
 #if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
 	OSM_MSG_MAD_MULTIPATH_RECORD,
 #endif
diff --git a/osm/include/opensm/osm_sa_informinfo.h b/osm/include/opensm/osm_sa_informinfo.h
index 2e57f43..c22c1eb 100644
--- a/osm/include/opensm/osm_sa_informinfo.h
+++ b/osm/include/opensm/osm_sa_informinfo.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.
  *
@@ -33,7 +33,6 @@
  *
  */
 
-
 /*
  * Abstract:
  * 	Declaration of osm_infr_rcv_t.
@@ -108,6 +107,7 @@ typedef struct _osm_infr_rcv
 	osm_mad_pool_t		*p_mad_pool;
 	osm_log_t		*p_log;
 	cl_plock_t		*p_lock;
+	cl_qlock_pool_t		pool;
 } osm_infr_rcv_t;
 /*
 * FIELDS
@@ -123,6 +123,10 @@ typedef struct _osm_infr_rcv
 *	p_lock
 *		Pointer to the serializing lock.
 *
+*	pool
+*		Pool of linkable InformInfo Record objects used to
+*		generate the query response.
+*
 * SEE ALSO
 *	InformInfo Receiver object
 *********/
@@ -262,6 +266,34 @@ osm_infr_rcv_process(
 *	InformInfo Receiver
 *********/
 
+/****f* OpenSM: InformInfo Record Receiver/osm_infir_rcv_process
+* NAME
+*	osm_infir_rcv_process
+*
+* DESCRIPTION
+*	Process the InformInfo Record request.
+*
+* SYNOPSIS
+*/
+void
+osm_infir_rcv_process(
+	IN osm_infr_rcv_t*		const p_rcv,
+	IN const osm_madw_t*		const p_madw );
+/*
+* PARAMETERS
+*	p_rcv
+*		[in] Pointer to an osm_infr_rcv_t object.
+*
+*	p_madw
+*		[in] Pointer to the MAD Wrapper containing the MAD
+*		that contains the node's InformInfo Record attribute.
+* NOTES
+*	This function processes a InformInfo Record attribute.
+*
+* SEE ALSO
+*	InformInfo Receiver
+*********/
+
 END_C_DECLS
 
 #endif	/* _OSM_SA_INFR_H_ */
diff --git a/osm/include/opensm/osm_sa_informinfo_ctrl.h b/osm/include/opensm/osm_sa_informinfo_ctrl.h
index 21dd0a7..a14c5b4 100644
--- a/osm/include/opensm/osm_sa_informinfo_ctrl.h
+++ b/osm/include/opensm/osm_sa_informinfo_ctrl.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.
  *
@@ -103,6 +103,7 @@ typedef struct _osm_infr_rcv_ctrl
   osm_log_t			*p_log;
   cl_dispatcher_t		*p_disp;
   cl_disp_reg_handle_t		h_disp;
+  cl_disp_reg_handle_t		h_disp2;
 } osm_infr_rcv_ctrl_t;
 /*
 * FIELDS
diff --git a/osm/opensm/osm_inform.c b/osm/opensm/osm_inform.c
index 178dba2..92647ef 100644
--- a/osm/opensm/osm_inform.c
+++ b/osm/opensm/osm_inform.c
@@ -94,7 +94,7 @@ osm_infr_init(
   /* what else do we need in the inform_record ??? */
 
   /* copy the contents of the provided informinfo */
-  memcpy(p_infr,p_infr_rec, sizeof(osm_infr_t));
+  memcpy(p_infr, p_infr_rec, sizeof(osm_infr_t));
 }
 
 /**********************************************************************
@@ -143,6 +143,54 @@ __match_rid_of_inf_rec(
 }
 
 /**********************************************************************
+ * Match an infr by the subscriber GID of the stored inform_info_record
+ **********************************************************************/
+static
+cl_status_t
+__match_gid_of_inf_rec(
+  IN  const cl_list_item_t* const p_list_item,
+  IN  void*                       context )
+{
+  ib_inform_info_record_t* p_infr_rec = (ib_inform_info_record_t  *)context;
+  osm_infr_t* p_infr = (osm_infr_t*)p_list_item;
+  int32_t count;
+
+  count = memcmp(
+    &p_infr->inform_record,
+    p_infr_rec,
+    sizeof(p_infr_rec->subscriber_gid) );
+
+  if(count == 0)
+    return CL_SUCCESS;
+  else
+    return CL_NOT_FOUND;
+}
+
+/**********************************************************************
+ * Match an infr by the subscriber enum of the stored inform_info_record
+ **********************************************************************/
+static
+cl_status_t
+__match_enum_of_inf_rec(
+  IN  const cl_list_item_t* const p_list_item,
+  IN  void*                       context )
+{
+  ib_inform_info_record_t* p_infr_rec = (ib_inform_info_record_t  *)context;
+  osm_infr_t* p_infr = (osm_infr_t*)p_list_item;
+  int32_t count;
+
+  count = memcmp(
+    &p_infr->inform_record.subscriber_enum,
+    &p_infr_rec->subscriber_enum,
+    sizeof(p_infr_rec->subscriber_enum) );
+
+  if(count == 0)
+    return CL_SUCCESS;
+  else
+    return CL_NOT_FOUND;
+}
+
+/**********************************************************************
  **********************************************************************/
 osm_infr_t*
 osm_infr_get_by_rid(
@@ -168,6 +216,54 @@ osm_infr_get_by_rid(
 
 /**********************************************************************
  **********************************************************************/
+osm_infr_t*
+osm_infr_get_by_gid(
+  IN osm_subn_t const *p_subn,
+  IN osm_log_t *p_log,
+  IN ib_inform_info_record_t* const p_infr_rec )
+{
+  cl_list_item_t* p_list_item;
+
+  OSM_LOG_ENTER( p_log, osm_infr_get_by_gid );
+
+  p_list_item = cl_qlist_find_from_head(
+    &p_subn->sa_infr_list,
+    __match_gid_of_inf_rec,
+    p_infr_rec );
+
+  if( p_list_item == cl_qlist_end( &p_subn->sa_infr_list ) )
+    p_list_item = NULL;
+
+  OSM_LOG_EXIT( p_log );
+  return (osm_infr_t*)p_list_item;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_infr_t*
+osm_infr_get_by_enum(
+  IN osm_subn_t const *p_subn,
+  IN osm_log_t *p_log,
+  IN ib_inform_info_record_t* const p_infr_rec )
+{
+  cl_list_item_t* p_list_item;
+
+  OSM_LOG_ENTER( p_log, osm_infr_get_by_enum );
+
+  p_list_item = cl_qlist_find_from_head(
+    &p_subn->sa_infr_list,
+    __match_enum_of_inf_rec,
+    p_infr_rec );
+
+  if( p_list_item == cl_qlist_end( &p_subn->sa_infr_list ) )
+    p_list_item = NULL;
+
+  OSM_LOG_EXIT( p_log );
+  return (osm_infr_t*)p_list_item;
+}
+
+/**********************************************************************
+ **********************************************************************/
 void
 __dump_all_informs(
     IN osm_subn_t  const *p_subn,
diff --git a/osm/opensm/osm_sa_informinfo.c b/osm/opensm/osm_sa_informinfo.c
index c979365..2667e49 100644
--- a/osm/opensm/osm_sa_informinfo.c
+++ b/osm/opensm/osm_sa_informinfo.c
@@ -33,7 +33,6 @@
  *
  */
 
-
 /*
  * Abstract:
  *    Implementation of osm_infr_rcv_t.
@@ -67,6 +66,26 @@
 #include <opensm/osm_inform.h>
 #include <opensm/osm_pkey.h>
 
+#define OSM_IIR_RCV_POOL_MIN_SIZE      32
+#define OSM_IIR_RCV_POOL_GROW_SIZE     32
+
+typedef struct _osm_iir_item
+{
+  cl_pool_item_t          pool_item;
+  ib_inform_info_record_t rec;
+} osm_iir_item_t;
+
+typedef struct _osm_iir_search_ctxt
+{
+  const ib_inform_info_record_t*  p_rcvd_rec;
+  ib_net64_t                      comp_mask;
+  cl_qlist_t*                     p_list;
+  ib_gid_t                        subscriber_gid;
+  ib_net16_t                      subscriber_enum;
+  osm_infr_rcv_t*                 p_rcv;
+  osm_physp_t*                    p_req_physp;
+} osm_iir_search_ctxt_t;
+
 /**********************************************************************
  **********************************************************************/
 void
@@ -74,6 +93,7 @@ osm_infr_rcv_construct(
   IN osm_infr_rcv_t* const p_rcv )
 {
   memset( p_rcv, 0, sizeof(*p_rcv) );
+  cl_qlock_pool_construct( &p_rcv->pool );
 }
 
 /**********************************************************************
@@ -85,7 +105,7 @@ osm_infr_rcv_destroy(
   CL_ASSERT( p_rcv );
 
   OSM_LOG_ENTER( p_rcv->p_log, osm_infr_rcv_destroy );
-
+  cl_qlock_pool_destroy( &p_rcv->pool );
   OSM_LOG_EXIT( p_rcv->p_log );
 }
 
@@ -112,7 +132,12 @@ osm_infr_rcv_init(
   p_rcv->p_resp = p_resp;
   p_rcv->p_mad_pool = p_mad_pool;
 
-  status = IB_SUCCESS;
+  status = cl_qlock_pool_init( &p_rcv->pool,
+                               OSM_IIR_RCV_POOL_MIN_SIZE,
+                               0,
+                               OSM_IIR_RCV_POOL_GROW_SIZE,
+                               sizeof(osm_iir_item_t),
+                               NULL, NULL, NULL );
 
   OSM_LOG_EXIT( p_rcv->p_log );
   return( status );
@@ -333,6 +358,339 @@ __osm_infr_rcv_respond(
 }
 
 /**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_inform_info_rec_by_comp_mask(
+  IN osm_infr_rcv_t*       const p_rcv,
+  IN const osm_infr_t*     const p_infr,
+  osm_iir_search_ctxt_t*   const p_ctxt )
+{
+  const ib_inform_info_record_t* p_rcvd_rec = NULL; 
+  ib_net64_t               comp_mask;
+  ib_net64_t               portguid;
+  osm_port_t *             p_subscriber_port;
+  osm_physp_t *            p_subscriber_physp;
+  const osm_physp_t*       p_req_physp;
+  osm_infr_t*              p_infr_rec = NULL;
+  ib_inform_info_record_t  inform_info_rec;
+  osm_iir_item_t*          p_rec_item;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_inform_info_rec_by_comp_mask );
+
+  p_rcvd_rec = p_ctxt->p_rcvd_rec;
+  comp_mask = p_ctxt->comp_mask;
+  p_req_physp = p_ctxt->p_req_physp;
+
+  /* Both subscriber GID and enum specified */
+  if ((comp_mask & IB_IIR_COMPMASK_SUBSCRIBERGID) &&
+      (comp_mask & IB_IIR_COMPMASK_ENUM))
+  {
+    inform_info_rec.subscriber_gid = p_ctxt->subscriber_gid;
+    inform_info_rec.subscriber_enum = p_ctxt->subscriber_enum;
+    p_infr_rec = osm_infr_get_by_rid(p_rcv->p_subn, p_rcv->p_log, &inform_info_rec);
+    goto Done;
+  }
+
+  if (comp_mask & IB_IIR_COMPMASK_SUBSCRIBERGID)
+  {
+    inform_info_rec.subscriber_gid = p_ctxt->subscriber_gid;
+    p_infr_rec = osm_infr_get_by_gid(p_rcv->p_subn, p_rcv->p_log, &inform_info_rec);
+    goto Done;
+  }
+
+  if (comp_mask & IB_IIR_COMPMASK_ENUM)
+  {
+    inform_info_rec.subscriber_enum = p_ctxt->subscriber_enum;
+    p_infr_rec = osm_infr_get_by_enum(p_rcv->p_subn, p_rcv->p_log, &inform_info_rec);
+    goto Done;
+  }
+
+  /* Implement any other needed search cases */
+
+Done:
+  if (p_infr_rec)
+  {
+    /* Ensure pkey is shared before returning any records */
+    portguid = p_infr_rec->inform_record.subscriber_gid.unicast.interface_id;
+    p_subscriber_port = osm_get_port_by_guid( p_rcv->p_subn, portguid);
+    if ( p_subscriber_port == NULL )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_sa_inform_info_rec_by_comp_mask: ERR 430D: "
+               "Invalid subscriber port guid: 0x%016" PRIx64 "\n",
+               cl_ntoh64(portguid) );
+      goto Exit;
+    }
+
+    /* get the subscriber InformInfo physical port */
+    p_subscriber_physp = osm_port_get_default_phys_ptr(p_subscriber_port);
+    /* make sure that the requester and subscriber port can access each other 
+       according to the current partitioning. */
+    if (! osm_physp_share_pkey( p_rcv->p_log, p_req_physp, p_subscriber_physp))
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+               "__osm_sa_inform_info_rec_by_comp_mask: "
+               "requester and subscriber ports don't share pkey\n" );
+      goto Exit;
+    }
+ 
+    p_rec_item = (osm_iir_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+    if( p_rec_item == NULL )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_sa_inform_info_rec_by_comp_mask: ERR 430E: "
+               "cl_qlock_pool_get failed\n" );
+      goto Exit;
+    }
+
+    memcpy((void *)&p_rec_item->rec, (void *)&p_infr_rec->inform_record, sizeof(ib_inform_info_record_t));
+    cl_qlist_insert_tail( p_ctxt->p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+  }
+
+Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_inform_info_rec_by_comp_mask_cb(
+  IN cl_list_item_t*       const p_list_item,
+  IN void*                 context )
+{
+  const osm_infr_t* const p_infr = (osm_infr_t *)p_list_item;
+  osm_iir_search_ctxt_t*   const p_ctxt = (osm_iir_search_ctxt_t *)context;
+
+  __osm_sa_inform_info_rec_by_comp_mask( p_ctxt->p_rcv, p_infr, p_ctxt );
+}
+
+/**********************************************************************
+Received a Get(InformInfoRecord) or GetTable(InformInfoRecord) MAD
+**********************************************************************/
+static void
+osm_infr_rcv_process_get_method(
+  IN osm_infr_rcv_t*      const p_rcv,
+  IN const osm_madw_t*    const p_madw )
+{
+  ib_sa_mad_t*            p_rcvd_mad;
+  const ib_inform_info_record_t* p_rcvd_rec;
+  ib_inform_info_record_t* p_resp_rec;
+  cl_qlist_t              rec_list;
+  osm_madw_t*             p_resp_madw;
+  ib_sa_mad_t*            p_resp_sa_mad;
+  uint32_t                num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+  uint32_t                trim_num_rec;
+#endif
+  uint32_t                i, j;
+  osm_iir_search_ctxt_t   context;
+  osm_iir_item_t*         p_rec_item;
+  ib_api_status_t         status = IB_SUCCESS;
+  osm_physp_t*            p_req_physp;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_infr_rcv_process_get_method );
+
+  CL_ASSERT( p_madw );
+  p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_rcvd_rec =
+    (ib_inform_info_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+
+  /* update the requester physical port. */
+  p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+                                          p_rcv->p_subn,
+                                          osm_madw_get_mad_addr_ptr(p_madw) );
+  if (p_req_physp == NULL)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_infr_rcv_process_get_method: ERR 4309: "
+             "Cannot find requester physical port\n" );
+    goto Exit;
+  }
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+    osm_dump_inform_info_record( p_rcv->p_log, p_rcvd_rec, OSM_LOG_DEBUG );
+
+  cl_qlist_init( &rec_list );
+
+  context.p_rcvd_rec = p_rcvd_rec;
+  context.p_list = &rec_list;
+  context.comp_mask = p_rcvd_mad->comp_mask;
+  context.subscriber_gid = p_rcvd_rec->subscriber_gid;
+  context.subscriber_enum = p_rcvd_rec->subscriber_enum;
+  context.p_rcv = p_rcv;
+  context.p_req_physp = p_req_physp;
+
+  osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+           "osm_infr_rcv_process_get_method: "
+           "Query Subscriber GID:0x%016" PRIx64 " : 0x%016" PRIx64 "(%02X) Enum:0x%X(%02X)\n",
+           cl_ntoh64(p_rcvd_rec->subscriber_gid.unicast.prefix),
+           cl_ntoh64(p_rcvd_rec->subscriber_gid.unicast.interface_id),
+           (p_rcvd_mad->comp_mask & IB_IIR_COMPMASK_SUBSCRIBERGID) != 0,
+           cl_ntoh16(p_rcvd_rec->subscriber_enum),
+           (p_rcvd_mad->comp_mask & IB_IIR_COMPMASK_ENUM) != 0 );
+
+  /* Only Enum 0 is supported currently!!! */
+  if (((p_rcvd_mad->comp_mask & IB_IIR_COMPMASK_ENUM) == 0) || (p_rcvd_rec->subscriber_enum == 0))
+  {
+    cl_plock_acquire( p_rcv->p_lock );
+
+    cl_qlist_apply_func( &p_rcv->p_subn->sa_infr_list,
+                         __osm_sa_inform_info_rec_by_comp_mask_cb,
+                         &context );
+
+    cl_plock_release( p_rcv->p_lock );
+  }
+  else
+  {
+     osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+              "osm_infr_rcv_process_get_method: "
+              "Non-zero Enum is not currently supported\n" );
+  }
+
+  num_rec = cl_qlist_count( &rec_list );
+
+  /*
+   * C15-0.1.30:
+   * If we do a SubnAdmGet and got more than one record it is an error !
+   */
+  if (p_rcvd_mad->method == IB_MAD_METHOD_GET)
+  {
+    if (num_rec == 0)
+    {
+      osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+      goto Exit;
+    }
+    if (num_rec > 1)
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_infr_rcv_process_get_method: ERR 430A: "
+               "More than one record for SubnAdmGet (%u)\n",
+               num_rec );
+      osm_sa_send_error( p_rcv->p_resp, p_madw,
+                         IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
+
+      /* need to set the mem free ... */
+      p_rec_item = (osm_iir_item_t*)cl_qlist_remove_head( &rec_list );
+      while( p_rec_item != (osm_iir_item_t*)cl_qlist_end( &rec_list ) )
+      {
+        cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+        p_rec_item = (osm_iir_item_t*)cl_qlist_remove_head( &rec_list );
+      }
+
+      goto Exit;
+    }
+  }
+
+  pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+  /* we limit the number of records to a single packet */
+  trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_inform_info_record_t);
+  if (trim_num_rec < num_rec)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "osm_infr_rcv_process_get_method: "
+             "Number of records:%u trimmed to:%u to fit in one MAD\n",
+             num_rec, trim_num_rec );
+    num_rec = trim_num_rec;
+  }
+#endif
+
+  osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+           "osm_infr_rcv_process_get_method: "
+           "Returning %u records\n", num_rec );
+
+  /* 
+   * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+   */
+  p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+                                  p_madw->h_bind,
+                                  num_rec * sizeof(ib_inform_info_record_t) + IB_SA_MAD_HDR_SIZE,
+                                  &p_madw->mad_addr );
+
+  if( !p_resp_madw )
+  {
+    osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+            "osm_infr_rcv_process_get_method: ERR 430B: "
+            "osm_mad_pool_get failed\n" );
+
+    for( i = 0; i < num_rec; i++ )
+    {
+      p_rec_item = (osm_iir_item_t*)cl_qlist_remove_head( &rec_list );
+      cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+    }
+
+    osm_sa_send_error( p_rcv->p_resp, p_madw,
+                       IB_SA_MAD_STATUS_NO_RESOURCES );
+
+    goto Exit;
+  }
+
+  p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+  /*
+    Copy the MAD header back into the response mad.
+    Set the 'R' bit and the payload length,
+    Then copy all records from the list into the response payload.
+  */
+
+  memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE );
+  p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+  /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */
+  p_resp_sa_mad->sm_key = 0;
+  /* Fill in the offset (paylen will be done by the rmpp SAR) */
+  p_resp_sa_mad->attr_offset =
+    ib_get_attr_offset( sizeof(ib_inform_info_record_t) );
+
+  p_resp_rec = (ib_inform_info_record_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+#ifndef VENDOR_RMPP_SUPPORT
+  /* we support only one packet RMPP - so we will set the first and
+     last flags for gettable */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+  {
+    p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE;
+  }
+#else
+  /* forcefully define the packet as RMPP one */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+  for( i = 0; i < pre_trim_num_rec; i++ )
+  {
+    p_rec_item = (osm_iir_item_t*)cl_qlist_remove_head( &rec_list );
+    /* copy only if not trimmed */
+    if (i < num_rec)
+    {
+      *p_resp_rec = p_rec_item->rec;
+      /* clear reserved and pad fields in InformInfoRecord */
+      for (j = 0; j < 6; j++)
+        p_resp_rec->reserved[j] = 0;
+      for (j = 0; j < 4; j++)
+        p_resp_rec->pad[j] = 0;
+    }
+    cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+    p_resp_rec++;
+  }
+
+  CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+  status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+  if (status != IB_SUCCESS)
+  {
+    osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+            "osm_infr_rcv_process_get_method: ERR 430C: "
+            "osm_vendor_send status = %s\n",
+            ib_get_err_str(status));
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/*********************************************************************
 Received a Set(InformInfo) MAD
 **********************************************************************/
 static void
@@ -395,6 +753,12 @@ osm_infr_rcv_process_set_method(
     osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID );
     goto Exit;
   }
+osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+         "osm_infr_rcv_process_set_method: "
+         "LID 0x%04X GID 0x%016" PRIx64 " : 0x%016" PRIx64"\n",
+         cl_ntoh16(p_madw->mad_addr.dest_lid),
+         cl_ntoh64(inform_info_rec.inform_record.subscriber_gid.unicast.prefix),
+         cl_ntoh64(inform_info_rec.inform_record.subscriber_gid.unicast.interface_id));
 
   /*
    * MODIFICATIONS DONE ON INCOMING REQUEST:
@@ -472,7 +836,6 @@ osm_infr_rcv_process_set_method(
 
       /* Add this new osm_infr_t object to subnet object */
       osm_infr_insert_to_db( p_rcv->p_subn, p_rcv->p_log, p_infr );
-
     }
     else
     {
@@ -513,6 +876,8 @@ osm_infr_rcv_process_set_method(
   OSM_LOG_EXIT( p_rcv->p_log );
 }
 
+/*********************************************************************
+**********************************************************************/
 void
 osm_infr_rcv_process(
   IN osm_infr_rcv_t*       const p_rcv,
@@ -543,3 +908,37 @@ osm_infr_rcv_process(
  Exit:
   OSM_LOG_EXIT( p_rcv->p_log );
 }
+
+/*********************************************************************
+**********************************************************************/
+void
+osm_infir_rcv_process(
+  IN osm_infr_rcv_t*       const p_rcv,
+  IN const osm_madw_t*     const p_madw )
+{
+  ib_sa_mad_t *p_sa_mad;
+    
+  OSM_LOG_ENTER( p_rcv->p_log, osm_infr_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+
+  CL_ASSERT( p_sa_mad->attr_id == IB_MAD_ATTR_INFORM_INFO_RECORD );
+
+  if ( (p_sa_mad->method != IB_MAD_METHOD_GET) &&
+       (p_sa_mad->method != IB_MAD_METHOD_GETTABLE) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "osm_infir_rcv_process: "
+             "Unsupported Method (%s)\n",
+             ib_get_sa_method_str( p_sa_mad->method ) );
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+    goto Exit;
+  }
+
+  osm_infr_rcv_process_get_method( p_rcv, p_madw );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
diff --git a/osm/opensm/osm_sa_informinfo_ctrl.c b/osm/opensm/osm_sa_informinfo_ctrl.c
index 76fc402..1637155 100644
--- a/osm/opensm/osm_sa_informinfo_ctrl.c
+++ b/osm/opensm/osm_sa_informinfo_ctrl.c
@@ -33,7 +33,6 @@
  *
  */
 
-
 /*
  * Abstract:
  *    Implementation of osm_infr_rcv_ctrl_t.
@@ -68,12 +67,25 @@ __osm_infr_rcv_ctrl_disp_callback(
 
 /**********************************************************************
  **********************************************************************/
+static void
+__osm_infir_rcv_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_infir_rcv_process( ((osm_infr_rcv_ctrl_t*)context)->p_rcv,
+                         (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
 void
 osm_infr_rcv_ctrl_construct(
   IN osm_infr_rcv_ctrl_t* const p_ctrl )
 {
   memset( p_ctrl, 0, sizeof(*p_ctrl) );
   p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+  p_ctrl->h_disp2 = CL_DISP_INVALID_HANDLE;
 }
 
 /**********************************************************************
@@ -83,6 +95,7 @@ osm_infr_rcv_ctrl_destroy(
   IN osm_infr_rcv_ctrl_t* const p_ctrl )
 {
   CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp2 );
   cl_disp_unregister( p_ctrl->h_disp );
 }
 
@@ -119,6 +132,22 @@ osm_infr_rcv_ctrl_init(
     goto Exit;
   }
 
+  p_ctrl->h_disp2 = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_INFORM_INFO_RECORD,
+    __osm_infir_rcv_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp2 == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_infr_rcv_ctrl_init: ERR 1702: "
+             "Dispatcher registration failed\n" );
+    cl_disp_unregister( p_ctrl->h_disp );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
  Exit:
   OSM_LOG_EXIT( p_log );
   return( status );
diff --git a/osm/opensm/osm_sa_mad_ctrl.c b/osm/opensm/osm_sa_mad_ctrl.c
index 56386b1..2605fbf 100644
--- a/osm/opensm/osm_sa_mad_ctrl.c
+++ b/osm/opensm/osm_sa_mad_ctrl.c
@@ -208,6 +208,10 @@ __osm_sa_mad_ctrl_process(
     msg_id = OSM_MSG_MAD_GUIDINFO_RECORD;
     break;
 
+  case IB_MAD_ATTR_INFORM_INFO_RECORD:
+    msg_id = OSM_MSG_MAD_INFORM_INFO_RECORD;
+    break;
+
 #if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
   case IB_MAD_ATTR_MULTIPATH_RECORD:
     msg_id = OSM_MSG_MAD_MULTIPATH_RECORD;







More information about the general mailing list