[ofa-general] [PATCH 1/3] ibutils/ibis: adding support for Congestion Control

Yevgeny Kliteynik kliteyn at dev.mellanox.co.il
Mon Jun 30 01:33:16 PDT 2008


Hi Oren,

This is the main patch of the CC support:
Implementing all the attributes and adding
get/set methods for these attributes.

Signed-off-by: Yevgeny Kliteynik <kliteyn at dev.mellanox.co.il>
---
 ibis/src/ibcc.c |  372 ++++++++++++++
 ibis/src/ibcc.h |  322 ++++++++++++
 ibis/src/ibcc.i | 1535 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 2229 insertions(+), 0 deletions(-)
 create mode 100644 ibis/src/ibcc.c
 create mode 100644 ibis/src/ibcc.h
 create mode 100644 ibis/src/ibcc.i

diff --git a/ibis/src/ibcc.c b/ibis/src/ibcc.c
new file mode 100644
index 0000000..9db247f
--- /dev/null
+++ b/ibis/src/ibcc.c
@@ -0,0 +1,372 @@
+/*
+ * Copyright (c) 2008 Mellanox Technologies LTD. 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 ibcc_t.
+ * This object represents the Congestion Control object.
+ * This object is part of the IBIS family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.0 $
+ */
+
+#include <string.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include "ibcc.h"
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_msgdef.h>
+
+
+/**********************************************************************
+ **********************************************************************/
+
+ibcc_t *
+ibcc_construct()
+{
+	ibcc_t* p_ibcc;
+	OSM_LOG_ENTER(&(IbisObj.log));
+
+	p_ibcc = malloc(sizeof(ibcc_t));
+	if (p_ibcc == NULL) {
+		goto Exit;
+	}
+	memset(p_ibcc, 0, sizeof(ibcc_t));
+
+    Exit :
+	OSM_LOG_EXIT(&(IbisObj.log));
+	return p_ibcc;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+void
+ibcc_destroy(
+	IN ibcc_t* const p_ibcc)
+{
+	OSM_LOG_ENTER(&(IbisObj.log));
+	p_ibcc->state = IBCC_STATE_INIT;
+	OSM_LOG_EXIT( &(IbisObj.log) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_api_status_t
+ibcc_init(
+	IN ibcc_t* const p_ibcc)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	OSM_LOG_ENTER(&(IbisObj.log));
+	p_ibcc->state = IBCC_STATE_INIT;
+	OSM_LOG_EXIT(&(IbisObj.log));
+	return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_api_status_t
+ibcc_bind(
+	IN ibcc_t* const p_ibcc)
+{
+	ib_api_status_t status = IB_SUCCESS;
+
+	OSM_LOG_ENTER(&(IbisObj.log));
+
+	/* Bind CongestionControl Management Class */
+	if ((status = ibis_gsi_mad_ctrl_bind(
+			&(IbisObj.mad_ctrl),
+			IB_MCLASS_CC, 2,
+			&p_ibcc->lid_route_bind)) != IB_SUCCESS)
+		goto Exit;
+
+	/* Set callback for ClassPortInfo attribute */
+	if ((status = ibis_gsi_mad_ctrl_set_class_attr_cb(
+			&(IbisObj.mad_ctrl),
+			IB_MCLASS_CC,
+			CL_NTOH16(IB_MAD_ATTR_CLASS_PORT_INFO),
+			ibis_gsi_sync_mad_batch_callback,
+			(void *)p_ibcc)) != IB_SUCCESS)
+		goto Exit;
+
+	/* Set callback for Notice attribute */
+	if ((status = ibis_gsi_mad_ctrl_set_class_attr_cb(
+			&(IbisObj.mad_ctrl),
+			IB_MCLASS_CC,
+			CL_NTOH16(IB_MAD_ATTR_NOTICE),
+			ibis_gsi_sync_mad_batch_callback,
+			(void *)p_ibcc)) != IB_SUCCESS)
+		goto Exit;
+
+	/* Set callback for CongestionInfo attribute */
+	if ((status = ibis_gsi_mad_ctrl_set_class_attr_cb(
+			&(IbisObj.mad_ctrl),
+			IB_MCLASS_CC,
+			CL_NTOH16(IB_MAD_ATTR_CONG_INFO),
+			ibis_gsi_sync_mad_batch_callback,
+			(void *)p_ibcc)) != IB_SUCCESS)
+		goto Exit;
+
+	/* Set callback for CongestionKeyInfo attribute */
+	if ((status = ibis_gsi_mad_ctrl_set_class_attr_cb(
+			&(IbisObj.mad_ctrl),
+			IB_MCLASS_CC,
+			CL_NTOH16(IB_MAD_ATTR_CONG_KEY_INFO),
+			ibis_gsi_sync_mad_batch_callback,
+			(void *)p_ibcc)) != IB_SUCCESS)
+		goto Exit;
+
+	/* Set callback for CongestionLog attribute */
+	if ((status = ibis_gsi_mad_ctrl_set_class_attr_cb(
+			&(IbisObj.mad_ctrl),
+			IB_MCLASS_CC,
+			CL_NTOH16(IB_MAD_ATTR_CONG_LOG),
+			ibis_gsi_sync_mad_batch_callback,
+			(void *)p_ibcc)) != IB_SUCCESS)
+		goto Exit;
+
+	/* Set callback for SwitchCongestionSetting attribute */
+	if ((status = ibis_gsi_mad_ctrl_set_class_attr_cb(
+			&(IbisObj.mad_ctrl),
+			IB_MCLASS_CC,
+			CL_NTOH16(IB_MAD_ATTR_SW_CONG_SETTING),
+			ibis_gsi_sync_mad_batch_callback,
+			(void *)p_ibcc)) != IB_SUCCESS)
+		goto Exit;
+
+	/* Set callback for SwitchPortCongestionSetting attribute */
+	if ((status = ibis_gsi_mad_ctrl_set_class_attr_cb(
+			&(IbisObj.mad_ctrl),
+			IB_MCLASS_CC,
+			CL_NTOH16(IB_MAD_ATTR_SW_PORT_CONG_SETTING),
+			ibis_gsi_sync_mad_batch_callback,
+			(void *)p_ibcc)) != IB_SUCCESS)
+		goto Exit;
+
+	/* Set callback for CACongestionSetting attribute */
+	if ((status = ibis_gsi_mad_ctrl_set_class_attr_cb(
+			&(IbisObj.mad_ctrl),
+			IB_MCLASS_CC,
+			CL_NTOH16(IB_MAD_ATTR_CA_CONG_SETTING),
+			ibis_gsi_sync_mad_batch_callback,
+			(void *)p_ibcc)) != IB_SUCCESS)
+		goto Exit;
+
+	/* Set callback for CongestionControlTable attribute */
+	if ((status = ibis_gsi_mad_ctrl_set_class_attr_cb(
+			&(IbisObj.mad_ctrl),
+			IB_MCLASS_CC,
+			CL_NTOH16(IB_MAD_ATTR_CC_TBL),
+			ibis_gsi_sync_mad_batch_callback,
+			(void *)p_ibcc)) != IB_SUCCESS)
+		goto Exit;
+
+	/* Set callback for TimeStamp attribute */
+	if ((status = ibis_gsi_mad_ctrl_set_class_attr_cb(
+			&(IbisObj.mad_ctrl),
+			IB_MCLASS_CC,
+			CL_NTOH16(IB_MAD_ATTR_TIME_STAMP),
+			ibis_gsi_sync_mad_batch_callback,
+			(void *)p_ibcc)) != IB_SUCCESS)
+		goto Exit;
+
+    Exit :
+	OSM_LOG_EXIT( &(IbisObj.log) );
+	return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static void
+__ibcc_prep_cc_mad(
+	IN ibcc_t       *p_ibcc,
+	IN uint16_t      lid,
+	IN uint8_t       method,
+	IN uint16_t      attribute_id,
+	IN uint32_t      attribute_mod,
+	IN uint64_t      cc_key,
+	IN uint8_t      *cc_log_data,
+	IN size_t        cc_log_data_size,
+	IN uint8_t      *cc_mgt_data,
+	IN size_t        cc_mgt_data_size,
+	OUT osm_madw_t **pp_madw)
+{
+	osm_mad_addr_t        mad_addr;
+	osm_madw_t            *p_madw;
+
+	OSM_LOG_ENTER(&(IbisObj.log));
+
+	mad_addr.dest_lid = cl_hton16(lid);
+	mad_addr.path_bits = 0;
+	mad_addr.static_rate = 0;
+
+	mad_addr.addr_type.gsi.remote_qp=cl_hton32(1);
+	mad_addr.addr_type.gsi.remote_qkey = cl_hton32(0x80010000);
+	mad_addr.addr_type.gsi.pkey_ix = 0;
+	mad_addr.addr_type.gsi.service_level = 0;
+	mad_addr.addr_type.gsi.global_route = FALSE;
+
+	p_madw = osm_mad_pool_get(&(IbisObj.mad_pool),
+				  p_ibcc->lid_route_bind,
+				  MAD_BLOCK_SIZE,
+				  &mad_addr);
+	*pp_madw = p_madw;
+
+	p_madw->resp_expected = TRUE;
+
+	memset((char*)p_madw->p_mad, 0, MAD_BLOCK_SIZE);
+
+	((ib_mad_t *)p_madw->p_mad)->base_ver = 1;
+	((ib_mad_t *)p_madw->p_mad)->mgmt_class = IB_MCLASS_CC;
+	((ib_mad_t *)p_madw->p_mad)->class_ver = 2;
+	((ib_mad_t *)p_madw->p_mad)->method = method;
+	((ib_mad_t *)p_madw->p_mad)->trans_id = ibis_get_tid();
+	((ib_mad_t *)p_madw->p_mad)->attr_id = cl_hton16(attribute_id);
+	((ib_mad_t *)p_madw->p_mad)->attr_mod = cl_hton32(attribute_mod);
+
+	((ib_cc_mad_t *)p_madw->p_mad)->cc_key = cl_hton64(cc_key);
+
+	memset(((ib_cc_mad_t *)p_madw->p_mad)->log_data,
+	       0, IB_CC_LOG_DATA_SIZE);
+	memset(((ib_cc_mad_t *)p_madw->p_mad)->mgt_data,
+	       0, IB_CC_MGT_DATA_SIZE);
+
+	if (method == IB_MAD_METHOD_GET) {
+		/* In SubnGet() method we leave log and
+		   management data clean - they should
+		   be filled by the response MAD only.*/
+	}
+	else {
+		if (cc_log_data_size > 0) {
+			CL_ASSERT(cc_log_data_size <= IB_CC_LOG_DATA_SIZE);
+			CL_ASSERT(cc_log_data);
+			memcpy(((ib_cc_mad_t *)p_madw->p_mad)->log_data,
+			       cc_log_data, cc_log_data_size);
+		}
+	
+		if (cc_mgt_data_size > 0) {
+			CL_ASSERT(cc_mgt_data_size <= IB_CC_MGT_DATA_SIZE);
+			CL_ASSERT(cc_mgt_data);
+			memcpy(((ib_cc_mad_t *)p_madw->p_mad)->mgt_data,
+			       cc_mgt_data, cc_mgt_data_size);
+		}
+	}
+
+	OSM_LOG_EXIT(&(IbisObj.log));
+}  /* __ibcc_prep_cc_mad() */
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_api_status_t
+ibcc_send_mad_by_lid (
+	ibcc_t   *p_ibcc,
+	uint64_t  cc_key,
+	uint8_t  *cc_log_data,
+	size_t    cc_log_data_size,
+	uint8_t  *cc_mgt_data,
+	size_t    cc_mgt_data_size,
+	uint16_t  lid,
+	uint16_t  attribute_id,
+	uint32_t  attribute_mod,
+	uint16_t  method)
+{
+	osm_madw_t      *p_madw;
+	ib_cc_mad_t      response_mad;
+	ib_api_status_t  status;
+
+	OSM_LOG_ENTER(&(IbisObj.log));
+
+	osm_log(&(IbisObj.log), OSM_LOG_DEBUG,
+		"ibcc_send_mad_by_lid: "
+		"Sending to lid:0x%04X method:0x%02X "
+		"attr:0x%04X mod:0x%08x\n",
+		lid, method, attribute_id, attribute_mod);
+
+	memset(&response_mad, 0, sizeof(ib_cc_mad_t));
+
+	__ibcc_prep_cc_mad(p_ibcc,
+			   lid,
+			   method,
+			   attribute_id,
+			   attribute_mod,
+			   cc_key,
+			   cc_log_data,
+			   cc_log_data_size,
+			   cc_mgt_data,
+			   cc_mgt_data_size,
+			   &p_madw);
+
+	/* send and wait */
+	status = ibis_gsi_send_sync_mad_batch(
+				&(IbisObj.mad_ctrl),
+				p_ibcc->lid_route_bind,
+				1,
+				&p_madw,
+				sizeof(ib_cc_mad_t),
+				(uint8_t*)&response_mad);
+
+	if (!response_mad.header.method)
+		status = IB_TIMEOUT;
+
+	if (status == IB_SUCCESS) {
+
+		if (cc_log_data)
+			memcpy(cc_log_data,
+			       response_mad.log_data,
+			       cc_log_data_size);
+
+		if (cc_mgt_data)
+			memcpy(cc_mgt_data,
+			       response_mad.mgt_data,
+			       cc_mgt_data_size);
+
+		if (cl_ntoh16(response_mad.header.status) & 0x7fff)
+			status = cl_ntoh16(response_mad.header.status);
+	}
+
+	OSM_LOG_EXIT(&(IbisObj.log));
+	return (status);
+}  /* ibcc_send_mad_by_lid() */
+
diff --git a/ibis/src/ibcc.h b/ibis/src/ibcc.h
new file mode 100644
index 0000000..149675c
--- /dev/null
+++ b/ibis/src/ibcc.h
@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 2008 Mellanox Technologies LTD. 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:
+ *	Definition of ibcc_t.
+ *	This object represents the Congestion Control Packets Interface
+ *	This object is part of the IBIS family of objects.
+ *
+ * Environment:
+ * 	Linux User Mode
+ *
+ * $Revision: 1.0 $
+ */
+
+#ifndef _IBCC_H_
+#define _IBCC_H_
+
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_msgdef.h>
+#include "ibis_api.h"
+#include "ibis.h"
+
+typedef enum _ibcc_state
+{
+	IBCC_STATE_INIT,
+	IBCC_STATE_READY,
+	IBCC_STATE_BUSY,
+} ibcc_state_t;
+
+#define MAD_PAYLOAD_SIZE 256
+
+#define IBCC_DEAFULT_KEY 0
+
+/****s* IBIS: ibcc/ibcc_t
+* NAME  ibcc_t
+*
+*
+* DESCRIPTION
+*	ibcc structure
+*
+* SYNOPSIS
+*/
+typedef struct _ibcc
+{
+	ibcc_state_t       state;
+	osm_bind_handle_t  lid_route_bind;
+} ibcc_t;
+/*
+* FIELDS
+*
+*	state
+*		The ibcc state: INIT, READ or BUSY
+*
+*	lid_route_bind
+*		The handle to bind with the lower level for lid routed packets
+*
+* SEE ALSO
+*
+*********/
+
+/****f* IBIS: ibcc/ibcc_construct
+* NAME
+*	ibcc_construct
+*
+* DESCRIPTION
+*	Allocation of ibcc_t struct
+*
+* SYNOPSIS
+*/
+ibcc_t*
+ibcc_construct(void);
+/*
+* PARAMETERS
+*
+*
+* RETURN VALUE
+*	Return a pointer to an ibcc struct. Null if fails to do so.
+*
+* NOTES
+*	First step of the creation of ibcc_t
+*
+* SEE ALSO
+*	ibcc_destroy ibcc_init
+*********/
+
+/****s* IBIS: ibcc/ibcc_destroy
+* NAME
+*	ibcc_destroy
+*
+* DESCRIPTION
+*	release of ibcc_t struct
+*
+* SYNOPSIS
+*/
+void
+ibcc_destroy(
+	IN ibcc_t* const p_ibcc);
+/*
+* PARAMETERS
+*	p_ibcc
+*		A pointer to the ibcc_t struct that is about to be released
+*
+* RETURN VALUE
+*
+* NOTES
+*	Final step of the releasing of ibcc_t
+*
+* SEE ALSO
+*	ibcc_construct
+*********/
+
+/****f* IBIS: ibcc/ibcc_init
+* NAME
+*	ibcc_init
+*
+* DESCRIPTION
+*	Initialization of an ibcc_t struct
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+ibcc_init(
+	IN ibcc_t* const p_ibcc);
+/*
+* PARAMETERS
+*	p_ibcc
+*		A pointer to the ibcc_t struct that is about to be initialized
+*
+* RETURN VALUE
+*	The status of the function.
+*
+* NOTES
+*
+* SEE ALSO
+*	ibcc_construct
+* *********/
+
+
+/****f* IBIS: ibcc/ibcc_bind
+* NAME
+*	ibcc_bind
+*
+* DESCRIPTION
+*	Binding the ibcc object to a lower level.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+ibcc_bind(
+	IN ibcc_t* const p_ibcc);
+/*
+* PARAMETERS
+*	p_ibcc
+*		A pointer to the ibcc_t struct that is about to be binded
+*
+* RETURN VALUE
+*	The status of the function.
+*
+* NOTES
+*
+* SEE ALSO
+*	ibcc_construct
+*********/
+
+/****f* IBIS: ibcc/ibcc_send_mad_by_lid
+* NAME
+*	ibcc_send_mad_by_lid
+*
+* DESCRIPTION
+*	Send a CC mad to the given LID.
+*
+* SYNOPSIS
+*	ibcc_send_mad_by_lid(p_ibcc, p_mad, lid, attr, mod, meth)
+*	Note that all values are in host order.
+*/
+ib_api_status_t
+ibcc_send_mad_by_lid (
+	ibcc_t   *p_ibcc,
+	uint64_t  cc_key,
+	uint8_t  *cc_log_data,
+	size_t    cc_log_data_size,
+	uint8_t  *cc_mgt_data,
+	size_t    cc_mgt_data_size,
+	uint16_t  lid,
+	uint16_t  attribute_id,
+	uint32_t  attribute_mod,
+	uint16_t  method);
+/*
+* PARAMETERS
+*	p_ibcc
+*		A pointer to the ibcc_t struct
+*
+*	cc_key
+*		Congestion Control key
+*
+*	cc_log_data
+*		[in/out] A pointer to CC log data.
+*		Will be overwritten in case of response.
+*
+*	cc_log_data_size
+*		[in] The size of the log data block
+*
+*	cc_mgt_data
+*		[in/out] A pointer to CC management data.
+*		Will be overwritten in case of response.
+*
+*	cc_mgt_data_size
+*		[in] The size of the mgt data block
+*
+*	lid
+*		The Destination lid of the MAD
+*
+*	attribute_id
+*		The Attribute ID
+*
+*	attribute_mod
+*		Attribute modifier value
+*
+*	method
+*		The MAD method: Set/Get/Trap...
+*
+* RETURN VALUE
+*	The status of the function or response status.
+*
+* NOTES
+*
+* SEE ALSO
+*
+*********/
+
+/****s* IBA Base: Types/ibcc_ca_cong_log_t
+* NAME
+*	ibcc_ca_cong_log_t
+*
+* DESCRIPTION
+*	IBA defined CongestionLog attribute (A10.4.3.5)
+*	has a union that includes Congestion Log for
+*	switches and CAs.
+*	Instead of dealing with the union in SWIG, the
+*	following struct is defined to deal only with
+*	CA congestion log.
+*	For more details, please see ib_cong_log_t
+*	definition in ib_types.h
+*
+* SYNOPSIS
+*/
+typedef struct _ib_ca_cong_log {
+	uint8_t log_type;
+	uint8_t cong_flags;
+	ib_net16_t event_counter;
+	ib_net16_t event_map;
+	ib_net16_t resv;
+	ib_net32_t time_stamp;
+	ib_cong_log_event_ca_t log_event[13];
+} ibcc_ca_cong_log_t;
+/*********/
+
+/****s* IBA Base: Types/ibcc_sw_cong_log_t
+* NAME
+*	ibcc_sw_cong_log_t
+*
+* DESCRIPTION
+*	IBA defined CongestionLog attribute (A10.4.3.5)
+*	has a union that includes Congestion Log for
+*	switches and CAs.
+*	Instead of dealing with the union in SWIG, the
+*	following struct is defined to deal only with
+*	switch congestion log.
+*	For more details, please see ib_cong_log_t
+*	definition in ib_types.h
+*
+* SYNOPSIS
+*/
+typedef struct _ib_sw_cong_log {
+	uint8_t log_type;
+	uint8_t cong_flags;
+	ib_net16_t event_counter;
+	ib_net32_t time_stamp;
+	uint8_t port_map[32];
+	ib_cong_log_event_sw_t entry_list[15];
+} ibcc_sw_cong_log_t;
+/*********/
+
+#endif /* _IBCC_H_ */
diff --git a/ibis/src/ibcc.i b/ibis/src/ibcc.i
new file mode 100644
index 0000000..49d9a89
--- /dev/null
+++ b/ibis/src/ibcc.i
@@ -0,0 +1,1535 @@
+/*
+ * Copyright (c) 2008 Mellanox Technologies LTD. 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$
+ */
+
+%text %{
+
+  Congestion Control:
+    The CC interface supports sending Congestion Control Packets to
+    the fabric devices.
+
+    A set of object types is defined. The user can allocate a new attribute
+    object. Then the object can be set using configure or the direct
+    manipulation methods.
+
+    Extra methods are provided for each object:
+    setByLid <lid> <attrMod>
+    getByLid <lid> <attrMod>
+%}
+
+/*
+ * NOTE : The simplest way to implement that interface is to
+ * code the Set section as embedded tcl code that will create a new
+ * object of the attribute type and use the given set of flags
+ * as configuration command. This way we let swig do the coding
+ * and parsing of each field.
+ */
+
+%{
+#include "stdio.h"
+#include <errno.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <iba/ib_types.h>
+#include <complib/cl_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_map.h>
+#include <complib/cl_debug.h>
+#include "ibis_api.h"
+
+	/* the global pointer to this CC mads manager */
+	static ibcc_t *gp_ibcc;
+
+	/* we probably want to use our own naming for classes */
+	typedef ib_class_port_info_t       ccClassPortInfo;
+	typedef ib_mad_notice_attr_t       ccNotice;
+	typedef ib_cong_info_t             ccCongestionInfo;
+	typedef ib_cong_key_info_t         ccCongestionKeyInfo;
+	typedef ibcc_ca_cong_log_t         ccCACongestionLog;
+	typedef ibcc_sw_cong_log_t         ccSWCongestionLog;
+	typedef ib_sw_cong_setting_t       ccSWCongestionSetting;
+	typedef ib_sw_port_cong_setting_t  ccSWPortCongestionSetting;
+	typedef ib_ca_cong_setting_t       ccCACongestionSetting;
+	typedef ib_cc_tbl_t                ccTable;
+	typedef ib_time_stamp_t            ccTimeStamp;
+
+	/* these are the global objects to be used
+	   for set/get (one for each attribute) */
+	ib_class_port_info_t               ibcc_class_port_info_obj;
+	ib_mad_notice_attr_t               ibcc_notice_obj;
+	ib_cong_info_t                     ibcc_cong_info_obj;
+	ib_cong_key_info_t                 ibcc_cong_key_info_obj;
+	ibcc_ca_cong_log_t                 ibcc_ca_cong_log_obj;
+	ibcc_sw_cong_log_t                 ibcc_sw_cong_log_obj;
+	ib_sw_cong_setting_t               ibcc_sw_cong_setting_obj;
+	ib_sw_port_cong_setting_t          ibcc_sw_port_cong_setting_obj;
+	ib_ca_cong_setting_t               ibcc_ca_cong_setting_obj;
+	ib_cc_tbl_t                        ibcc_table_obj;
+	ib_time_stamp_t                    ibcc_time_stamp_obj;
+
+%}
+
+//
+// STANDARD IB TYPE MAPS:
+//
+
+%typemap(tcl8,in) ib_gid_t*(ib_gid_t temp)
+{
+	char buf[38];
+	char *p_prefix, *p_guid;
+	char *str_token;
+
+	strcpy(buf, Tcl_GetStringFromObj($source,NULL));
+	p_prefix = strtok_r(buf,":", &str_token);
+	p_guid = strtok_r(NULL, " ", &str_token);
+	temp.unicast.prefix = cl_hton64(strtoull(p_prefix, NULL, 16));
+	errno = 0;
+	if (errno) {
+		printf("Wrong format for gid prefix:%s\n", p_prefix);
+		return TCL_ERROR;
+	}
+
+	temp.unicast.interface_id = cl_hton64(strtoull(p_guid, NULL, 16));
+	if (errno) {
+		printf("Wrong format for gid guid:%s\n", p_guid);
+		return TCL_ERROR;
+	}
+
+	$target = &temp;
+}
+
+//
+// INTERFACE DEFINITION (~copy of h file)
+//
+
+%section "IBCC Constants"
+/* These constants are provided by IBCC: */
+
+%section "IBCC Objects",pre
+/* This section describes the various object types exposed by IBCC. */
+%text %{
+
+%}
+
+/**************************************************
+ ***        ClassPortInfo (A10.4.3.1)           ***
+ **************************************************/
+
+typedef struct _ibcc_class_port_info {
+	uint8_t     base_ver;
+	uint8_t     class_ver;
+	ib_net16_t  cap_mask;
+	ib_net32_t  cap_mask2_resp_time;
+	ib_gid_t    redir_gid;
+	ib_net32_t  redir_tc_sl_fl;
+	ib_net16_t  redir_lid;
+	ib_net16_t  redir_pkey;
+	ib_net32_t  redir_qp;
+	ib_net32_t  redir_qkey;
+	ib_gid_t    trap_gid;
+	ib_net32_t  trap_tc_sl_fl;
+	ib_net16_t  trap_lid;
+	ib_net16_t  trap_pkey;
+	ib_net32_t  trap_hop_qp;
+	ib_net32_t  trap_qkey;
+} ccClassPortInfo;
+
+%addmethods ccClassPortInfo {
+
+	int getByLid(uint16_t lid) {
+		return ibcc_send_mad_by_lid (
+			gp_ibcc,
+			IBCC_DEAFULT_KEY,
+			NULL,                    // log data
+			0,                       // log data size
+			(uint8_t *)self,         // mgt data
+			sizeof(ccClassPortInfo), // mgt data size
+			lid,
+			CL_NTOH16(IB_MAD_ATTR_CLASS_PORT_INFO),
+			0,                       // attribute modifier
+			IB_MAD_METHOD_GET);
+	}
+
+	int setByLid(uint16_t lid) {
+		return ibcc_send_mad_by_lid(
+			gp_ibcc,
+			IBCC_DEAFULT_KEY,
+			NULL,                    // log data
+			0,                       // log data size
+			(uint8_t *)self,         // mgt data
+			sizeof(ccClassPortInfo), // mgt data size
+			lid,
+			CL_NTOH16(IB_MAD_ATTR_CLASS_PORT_INFO),
+			0,                       // attribute modifier
+			IB_MAD_METHOD_SET);
+	}
+}
+
+/**************************************************
+ ***       Notice - Trap 0 (A10.4.3.2)          ***
+ **************************************************/
+
+typedef struct _ibcc_notice
+{
+	uint8_t   generic_type;
+
+	union _notice_g_or_v {
+		struct {
+			uint8_t prod_type_msb;
+			ib_net16_t prod_type_lsb;
+			ib_net16_t trap_num;
+		} generic;
+	} g_or_v;
+
+	ib_net16_t   issuer_lid;
+	ib_net16_t   toggle_count;
+
+	union _data_details
+	{
+		struct _cc_raw_data {
+			uint8_array_t  details[54];
+		} raw_data;
+
+		struct {
+			ib_net16_t source_lid;   // Source LID from offending packet LRH
+			uint8_t method;          // Method, from common MAD header
+			uint8_t resv0;
+			ib_net16_t attr_id;       // Attribute ID, from common MAD header
+			ib_net16_t resv1;
+			ib_net32_t attr_mod;      // Attribute Modif, from common MAD header
+			ib_net32_t qp;            // 8b pad, 24b dest QP from BTH
+			ib_net64_t cc_key;        // CC key of the offending packet
+			ib_gid_t source_gid;      // GID from GRH of the offending packet
+			uint8_array_t padding[14];// Padding - ignored on read
+		} ntc_0;
+
+	} data_details;
+
+	ib_gid_t   issuer_gid;
+} ccNotice;
+
+%addmethods ccNotice {
+	int trapByLid(uint16_t lid) {
+		return ibcc_send_mad_by_lid(
+			gp_ibcc,
+			IBCC_DEAFULT_KEY,
+			NULL,                    // log data
+			0,                       // log data size
+			(uint8_t *)self,         // mgt data
+			sizeof(ccNotice),        // mgt data size
+			lid,
+			CL_NTOH16(IB_MAD_ATTR_NOTICE),
+			0,                       // attribute modifier
+			IB_MAD_METHOD_TRAP);
+	}
+}
+
+/**************************************************
+ ***       CongestionInfo (A10.4.3.3)           ***
+ **************************************************/
+
+typedef struct _ib_cong_info {
+	uint8_t cong_info;
+	uint8_t resv;
+	uint8_t ctrl_table_cap;
+} ccCongestionInfo;
+
+%addmethods ccCongestionInfo {
+	int getByLid(uint16_t lid) {
+		return ibcc_send_mad_by_lid (
+			gp_ibcc,
+			IBCC_DEAFULT_KEY,
+			NULL,                     // log data
+			0,                        // log data size
+			(uint8_t *)self,          // mgt data
+			sizeof(ccCongestionInfo), // mgt data size
+			lid,
+			CL_NTOH16(IB_MAD_ATTR_CONG_INFO),
+			0,                        // attribute modifier
+			IB_MAD_METHOD_GET);
+	}
+}
+
+/**************************************************
+ ***      CongestionKeyInfo (A10.4.3.4)         ***
+ **************************************************/
+
+typedef struct _ib_cong_key_info {
+	ib_net64_t cc_key;
+	uint8_t protect_bit;
+	uint8_t resv;
+	ib_net16_t lease_period;
+	ib_net16_t violations;
+} ccCongestionKeyInfo;
+
+%addmethods ccCongestionKeyInfo {
+
+	int getByLid(uint16_t lid) {
+		return ibcc_send_mad_by_lid (
+			gp_ibcc,
+			IBCC_DEAFULT_KEY,
+			NULL,                    // log data
+			0,                       // log data size
+			(uint8_t *)self,         // mgt data
+			sizeof(ccCongestionKeyInfo), // mgt data size
+			lid,
+			CL_NTOH16(IB_MAD_ATTR_CONG_KEY_INFO),
+			0,                       // attribute modifier
+			IB_MAD_METHOD_GET);
+	}
+
+	int setByLid(uint16_t lid) {
+		return ibcc_send_mad_by_lid(
+			gp_ibcc,
+			IBCC_DEAFULT_KEY,
+			NULL,                    // log data
+			0,                       // log data size
+			(uint8_t *)self,         // mgt data
+			sizeof(ccCongestionKeyInfo), // mgt data size
+			lid,
+			CL_NTOH16(IB_MAD_ATTR_CONG_KEY_INFO),
+			0,                       // attribute modifier
+			IB_MAD_METHOD_SET);
+	}
+}
+
+/**************************************************
+ ***        CongestionLog (A10.4.3.5)           ***
+ **************************************************/
+
+/*
+ * IBA defined CongestionLog attribute (A10.4.3.5)
+ * has the following definition:
+ *
+ *	typedef struct _ib_cong_log {
+ *		uint8_t log_type;
+ *		union _log_details
+ *		{
+ *			struct {
+ *				uint8_t cong_flags;
+ *				ib_net16_t event_counter;
+ *				ib_net32_t time_stamp;
+ *				uint8_array_t port_map[32];
+ *				ib_cong_log_event_sw_t entry_list[15];
+ *			} log_sw;
+ *
+ *			struct {
+ *				uint8_t cong_flags;
+ *				ib_net16_t event_counter;
+ *				ib_net16_t event_map;
+ *				ib_net16_t resv;
+ *				ib_net32_t time_stamp;
+ *				ib_cong_log_event_ca_t log_event[13];
+ *			} log_ca;
+ *
+ *		} log_details;
+ *	} ccCongestionLog;
+ *
+ * This definition has a union that includes Congestion Log for
+ * switches and CAs.
+ * Instead of dealing with the union in SWIG, we define two separate logs:
+ *   ccSWCongestionLog (for dealing only with switches)
+ *   ccCACongestionLog (for dealing only with CAs)
+ */
+
+%typemap(in) ib_cong_log_event_sw_t[ANY] (ib_cong_log_event_sw_t entrys[$dim0]) {
+	long int value;
+	long int entry_index = 0;
+	int k;
+	int countSubLists, idx, numElements;
+	int i = 0;
+	int option = 0;
+	Tcl_Obj ** subListObjArray;
+	Tcl_Obj  * tclObj;
+
+	if (Tcl_ListObjGetElements(interp, $source, &countSubLists, &subListObjArray) != TCL_OK)
+	{
+		printf("Error: wrong format for SW Congestion Log Event: %s\n",
+			Tcl_GetStringFromObj($source,NULL));
+		return TCL_ERROR;
+	}
+
+	/*
+	 * There are two options to configure log_event:
+	 *   1. Configure the whole list by providing list of value groups:
+	 *        ccSWCongestionLogMad configure -log_event {{1 2 3 4} {5 6 7 8}}
+	 *   2. Configure specific items from the list by providing index in addition to the above:
+	 *        ccSWCongestionLogMad configure -log_event {{4 1 2 3 4} {8 5 6 7 8}}
+	 */
+
+	if (countSubLists > 0) {
+
+		/* check how many members does the first substring have */
+
+		if (Tcl_ListObjLength(interp, subListObjArray[0], &numElements) != TCL_OK) {
+			printf("Error: wrong format for SW Congestion Entry: %s\n",
+				Tcl_GetStringFromObj(subListObjArray[0],NULL));
+			return TCL_ERROR;
+		}
+
+		if (numElements == 4)
+			option = 1;
+		else if (numElements == 5)
+			option = 2;
+		else {
+			printf("Error: wrong number of elements for SW Congestion Entry: %s\n",
+				Tcl_GetStringFromObj(subListObjArray[0],NULL));
+			return TCL_ERROR;
+		}
+	}
+	else {
+		/* if the user didn't specify anything, use option 1,
+		   wich will effectively clear the whole list values */
+		option = 1;
+	}
+
+	if (option == 1) {
+		/*
+		 * first option - list of groups of four values
+		 */
+
+		for (idx = 0; idx < countSubLists; idx++) {
+
+			if (Tcl_ListObjLength(interp, subListObjArray[idx], &numElements) != TCL_OK) {
+				printf("Error: wrong format for SW Congestion Log Event: %s\n",
+					Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+				return TCL_ERROR;
+			}
+
+			if (numElements != 4) {
+				printf("Error: wrong number of elements for SW Congestion Log Event: %s\n",
+					Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+				return TCL_ERROR;
+			}
+
+			for (k = 0; k < 4; k++) {
+
+				if (Tcl_ListObjIndex(interp, subListObjArray[idx], k, &tclObj) != TCL_OK) {
+					printf("Error: Fail to obtain the element of SW Congestion Log Event: %s\n",
+						Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+					return TCL_ERROR;
+				}
+				value = strtol(Tcl_GetStringFromObj(tclObj, NULL), NULL, 0);
+				switch (k) {
+					case 0: entrys[i].slid = cl_hton16(value); break;
+					case 1: entrys[i].dlid = cl_hton16(value); break;
+					case 2: entrys[i].resv0_sl = value; break;
+					case 3: entrys[i++].time_stamp = cl_hton32(value); break;
+					default: break;
+				}
+			}
+		}
+
+		for (; i < $dim0; i++) {
+			entrys[i].slid = 0;
+			entrys[i].dlid = 0;
+			entrys[i].resv0_sl = 0;
+			entrys[i].time_stamp = 0;
+		}
+	}
+	else {
+		/*
+		 * second option - index and four values
+		 */
+
+		for (idx = 0; idx < countSubLists; idx++) {
+
+			if (Tcl_ListObjLength(interp, subListObjArray[idx], &numElements) != TCL_OK) {
+				printf("Error: wrong format for SW Congestion Log Event: %s\n",
+					Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+				return TCL_ERROR;
+			}
+
+			if (numElements != 5) {
+				printf("Error: wrong number of elements for SW Congestion Log Event: %s\n",
+					Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+				return TCL_ERROR;
+			}
+
+			for (k = 0; k < 5; k++) {
+
+				if (Tcl_ListObjIndex(interp, subListObjArray[idx], k, &tclObj) != TCL_OK) {
+					printf("Error: Fail to obtain the element of SW Congestion Log Event: %s\n",
+						Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+					return TCL_ERROR;
+				}
+				value = strtol(Tcl_GetStringFromObj(tclObj, NULL), NULL, 0);
+				switch (k) {
+					case 0: entry_index = value; break;
+					case 1: entrys[entry_index].slid = cl_hton16(value); break;
+					case 2: entrys[entry_index].dlid = cl_hton16(value); break;
+					case 3: entrys[entry_index].resv0_sl = value; break;
+					case 4: entrys[entry_index].time_stamp = cl_hton32(value); break;
+					default: break;
+				}
+			}
+
+		}
+	}
+
+	$target = entrys;
+}
+
+%typemap(memberin) ib_cong_log_event_sw_t[ANY] {
+	int i;
+	for (i=0; i <$dim0 ; i++) {
+		$target[i] = *($source+i);
+	}
+}
+
+%typemap(tcl8,out) ib_cong_log_event_sw_t[ANY] {
+	int i;
+	char buff[99];
+
+	sprintf(buff, "-entry_list ");
+	Tcl_AppendResult(interp, buff, NULL);
+
+	for (i=0; i <$dim0 ; i++) {
+		sprintf(buff, "{#%u:", i);
+		Tcl_AppendResult(interp, buff, NULL);
+
+		if ($source[i].slid)
+			sprintf(buff, " -slid 0x%04x", cl_ntoh16($source[i].slid));
+		else
+			sprintf(buff, " -slid 0");
+		Tcl_AppendResult(interp, buff, NULL);
+
+		if ($source[i].dlid)
+			sprintf(buff, " -dlid 0x%04x", cl_ntoh16($source[i].dlid));
+		else
+			sprintf(buff, " -dlid 0");
+		Tcl_AppendResult(interp, buff, NULL);
+
+		if ($source[i].resv0_sl)
+			sprintf(buff, " -resv0_sl 0x%02x", $source[i].resv0_sl);
+		else
+			sprintf(buff, " -resv0_sl 0");
+		Tcl_AppendResult(interp, buff, NULL);
+
+		if ($source[i].time_stamp)
+			sprintf(buff, " -time_stamp 0x%08x", cl_ntoh32($source[i].time_stamp));
+		else
+			sprintf(buff, " -time_stamp 0");
+		Tcl_AppendResult(interp, buff, NULL);
+
+		sprintf(buff, "} ");
+		Tcl_AppendResult(interp, buff, NULL);
+	}
+}
+
+typedef struct _ib_cong_log_event_sw {
+	ib_net16_t slid;
+	ib_net16_t dlid;
+	uint8_t resv0_sl;
+	uint8_t resv1;
+	ib_net16_t resv2;
+	ib_net32_t time_stamp;
+} ib_cong_log_event_sw_t;
+
+/**************************************************/
+
+%typemap(in) ib_cong_log_event_ca_t[ANY] (ib_cong_log_event_ca_t entrys[$dim0]) {
+	long int value;
+	long int entry_index = 0;
+	int k;
+	int countSubLists, idx, numElements;
+	int i = 0;
+	int option = 0;
+	Tcl_Obj ** subListObjArray;
+	Tcl_Obj  * tclObj;
+
+	if (Tcl_ListObjGetElements(interp, $source, &countSubLists, &subListObjArray) != TCL_OK)
+	{
+		printf("Error: wrong format for CA Congestion Log Event: %s\n",
+			Tcl_GetStringFromObj($source,NULL));
+		return TCL_ERROR;
+	}
+
+	/*
+	 * There are two options to configure log_event:
+	 *   1. Configure the whole list by providing list of value groups:
+	 *        ccCACongestionLogMad configure -log_event {{1 2 3 4} {5 6 7 8}}
+	 *   2. Configure specific items from the list by providing index in addition to the above:
+	 *        ccCACongestionLogMad configure -log_event {{4 1 2 3 4} {8 5 6 7 8}}
+	 */
+
+	if (countSubLists > 0) {
+
+		/* check how many members does the first substring have */
+
+		if (Tcl_ListObjLength(interp, subListObjArray[0], &numElements) != TCL_OK) {
+			printf("Error: wrong format for CA Congestion Entry: %s\n",
+				Tcl_GetStringFromObj(subListObjArray[0],NULL));
+			return TCL_ERROR;
+		}
+
+		if (numElements == 4)
+			option = 1;
+		else if (numElements == 5)
+			option = 2;
+		else {
+			printf("Error: wrong number of elements for CA Congestion Entry: %s\n",
+				Tcl_GetStringFromObj(subListObjArray[0],NULL));
+			return TCL_ERROR;
+		}
+	}
+	else {
+		/* if the user didn't specify anything, use option 1,
+		   wich will effectively clear the whole list values */
+		option = 1;
+	}
+
+	if (option == 1) {
+		/*
+		 * first option - list of groups of four values
+		 */
+
+		for (idx = 0; idx < countSubLists; idx++) {
+
+			if (Tcl_ListObjLength(interp, subListObjArray[idx], &numElements) != TCL_OK) {
+				printf("Error: wrong format for CA Congestion Log Event: %s\n",
+					Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+				return TCL_ERROR;
+			}
+
+			if (numElements != 4) {
+				printf("Error: wrong number of elements for CA Congestion Log Event: %s\n",
+					Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+				return TCL_ERROR;
+			}
+
+			for (k = 0; k < 4; k++) {
+
+				if (Tcl_ListObjIndex(interp, subListObjArray[idx], k, &tclObj) != TCL_OK) {
+					printf("Error: Fail to obtain the element of CA Congestion Log Event: %s\n",
+						Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+					return TCL_ERROR;
+				}
+				value = strtol(Tcl_GetStringFromObj(tclObj, NULL), NULL, 0);
+				switch (k) {
+					case 0: entrys[i].resv0_local_qp = cl_hton32(value); break;
+					case 1: entrys[i].remote_qp_sl_service_type = cl_hton32(value); break;
+					case 2: entrys[i].remote_lid = cl_hton16(value); break;
+					case 3: entrys[i++].time_stamp = cl_hton32(value); break;
+					default: break;
+				}
+			}
+		}
+
+		for (; i < $dim0; i++) {
+			entrys[i].resv0_local_qp = 0;
+			entrys[i].remote_qp_sl_service_type = 0;
+			entrys[i].remote_lid = 0;
+			entrys[i].time_stamp = 0;
+		}
+	}
+	else {
+		/*
+		 * second option - index and four values
+		 */
+
+		for (idx = 0; idx < countSubLists; idx++) {
+
+			if (Tcl_ListObjLength(interp, subListObjArray[idx], &numElements) != TCL_OK) {
+				printf("Error: wrong format for CA Congestion Log Event: %s\n",
+					Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+				return TCL_ERROR;
+			}
+
+			if (numElements != 5) {
+				printf("Error: wrong number of elements for CA Congestion Log Event: %s\n",
+					Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+				return TCL_ERROR;
+			}
+
+			for (k = 0; k < 5; k++) {
+
+				if (Tcl_ListObjIndex(interp, subListObjArray[idx], k, &tclObj) != TCL_OK) {
+					printf("Error: Fail to obtain the element of CA Congestion Log Event: %s\n",
+						Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+					return TCL_ERROR;
+				}
+				value = strtol(Tcl_GetStringFromObj(tclObj, NULL), NULL, 0);
+				switch (k) {
+					case 0: entry_index = value; break;
+					case 1: entrys[entry_index].resv0_local_qp = cl_hton32(value); break;
+					case 2: entrys[entry_index].remote_qp_sl_service_type = cl_hton32(value); break;
+					case 3: entrys[entry_index].remote_lid = cl_hton16(value); break;
+					case 4: entrys[entry_index].time_stamp = cl_hton32(value); break;
+					default: break;
+				}
+			}
+
+		}
+	}
+
+	$target = entrys;
+}
+
+%typemap(memberin) ib_cong_log_event_ca_t[ANY] {
+	int i;
+	for (i=0; i <$dim0 ; i++) {
+		$target[i] = *($source+i);
+	}
+}
+
+%typemap(tcl8,out) ib_cong_log_event_ca_t[ANY] {
+	int i;
+	char buff[99];
+
+	sprintf(buff, "-entry_list ");
+	Tcl_AppendResult(interp, buff, NULL);
+
+	for (i=0; i <$dim0 ; i++) {
+		sprintf(buff, "{#%u:", i);
+		Tcl_AppendResult(interp, buff, NULL);
+
+		if ($source[i].resv0_local_qp)
+			sprintf(buff, " -resv0_local_qp 0x%08x", cl_ntoh32($source[i].resv0_local_qp));
+		else
+			sprintf(buff, " -resv0_local_qp 0");
+		Tcl_AppendResult(interp, buff, NULL);
+
+		if ($source[i].remote_qp_sl_service_type)
+			sprintf(buff, " -remote_qp_sl_service_type 0x%08x", cl_ntoh32($source[i].remote_qp_sl_service_type));
+		else
+			sprintf(buff, " -remote_qp_sl_service_type 0");
+		Tcl_AppendResult(interp, buff, NULL);
+
+		if ($source[i].remote_lid)
+			sprintf(buff, " -remote_lid 0x%04x", cl_ntoh16($source[i].remote_lid));
+		else
+			sprintf(buff, " -remote_lid 0");
+		Tcl_AppendResult(interp, buff, NULL);
+
+		if ($source[i].time_stamp)
+			sprintf(buff, " -time_stamp 0x%08x", cl_ntoh32($source[i].time_stamp));
+		else
+			sprintf(buff, " -time_stamp 0");
+		Tcl_AppendResult(interp, buff, NULL);
+
+		sprintf(buff, "} ");
+		Tcl_AppendResult(interp, buff, NULL);
+	}
+}
+
+typedef struct _ib_cong_log_event_ca {
+	ib_net32_t resv0_local_qp;
+	ib_net32_t remote_qp_sl_service_type;
+	ib_net16_t remote_lid;
+	ib_net16_t resv1;
+	ib_net32_t time_stamp;
+} ib_cong_log_event_ca_t;
+
+/**************************************************/
+
+typedef struct _ib_sw_cong_log {
+	uint8_t log_type;
+	uint8_t cong_flags;
+	ib_net16_t event_counter;
+	ib_net32_t time_stamp;
+	uint8_array_t port_map[32];
+	ib_cong_log_event_sw_t entry_list[15];
+} ccSWCongestionLog;
+
+%addmethods ccSWCongestionLog {
+	int getByLid(uint16_t lid) {
+		return ibcc_send_mad_by_lid (
+			gp_ibcc,
+			IBCC_DEAFULT_KEY,
+			(uint8_t *)self,           // log data
+			sizeof(ccSWCongestionLog), // log data size
+			NULL,                      // mgt data
+			0,                         // mgt data size
+			lid,
+			CL_NTOH16(IB_MAD_ATTR_CONG_LOG),
+			0,                       // attribute modifier
+			IB_MAD_METHOD_GET);
+	}
+}
+
+typedef struct _ib_ca_cong_log {
+	uint8_t log_type;
+	uint8_t cong_flags;
+	ib_net16_t event_counter;
+	ib_net16_t event_map;
+	ib_net16_t resv;
+	ib_net32_t time_stamp;
+	ib_cong_log_event_ca_t log_event[13];
+} ccCACongestionLog;
+
+%addmethods ccCACongestionLog {
+	int getByLid(uint16_t lid) {
+		return ibcc_send_mad_by_lid (
+			gp_ibcc,
+			IBCC_DEAFULT_KEY,
+			(uint8_t *)self,           // log data
+			sizeof(ccCACongestionLog), // log data size
+			NULL,                      // mgt data
+			0,                         // mgt data size
+			lid,
+			CL_NTOH16(IB_MAD_ATTR_CONG_LOG),
+			0,                       // attribute modifier
+			IB_MAD_METHOD_GET);
+	}
+}
+
+
+/**************************************************
+ ***    SwitchCongestionSetting (A10.4.3.6)     ***
+ **************************************************/
+
+typedef struct _ib_sw_cong_setting {
+	ib_net32_t control_map;
+	uint8_array_t victim_mask[32];
+	uint8_array_t credit_mask[32];
+	uint8_t threshold;
+	uint8_t packet_size;
+	uint8_t cs_threshold;
+	uint8_t resv0;
+	ib_net16_t cs_return_delay;
+	ib_net16_t marking_rate;
+} ccSWCongestionSetting;
+
+
+%addmethods ccSWCongestionSetting {
+
+	int getByLid(uint16_t lid) {
+		return ibcc_send_mad_by_lid (
+			gp_ibcc,
+			IBCC_DEAFULT_KEY,
+			NULL,                    // log data
+			0,                       // log data size
+			(uint8_t *)self,         // mgt data
+			sizeof(ccSWCongestionSetting),// mgt data size
+			lid,
+			CL_NTOH16(IB_MAD_ATTR_SW_CONG_SETTING),
+			0,                       // attribute modifier
+			IB_MAD_METHOD_GET);
+	}
+
+	int setByLid(uint16_t lid) {
+		return ibcc_send_mad_by_lid (
+			gp_ibcc,
+			IBCC_DEAFULT_KEY,
+			NULL,                    // log data
+			0,                       // log data size
+			(uint8_t *)self,         // mgt data
+			sizeof(ccSWCongestionSetting),// mgt data size
+			lid,
+			CL_NTOH16(IB_MAD_ATTR_SW_CONG_SETTING),
+			0,                       // attribute modifier
+			IB_MAD_METHOD_SET);
+	}
+
+}
+
+/**************************************************
+ ***   SwitchPortCongestionSetting (A10.4.3.7)  ***
+ **************************************************/
+
+%typemap(in) ib_sw_port_cong_setting_element_t[ANY] (ib_sw_port_cong_setting_element_t entrys[$dim0]) {
+	long int value;
+	long int entry_index = 0;
+	int k;
+	int countSubLists, idx, numElements;
+	int i = 0;
+	int option = 0;
+	Tcl_Obj ** subListObjArray;
+	Tcl_Obj  * tclObj;
+
+	if (Tcl_ListObjGetElements(interp, $source, &countSubLists, &subListObjArray) != TCL_OK)
+	{
+		printf("Error: wrong format for SW Port Congestion Setting Element: %s\n",
+			Tcl_GetStringFromObj($source,NULL));
+		return TCL_ERROR;
+	}
+
+	/*
+	 * There are two options to configure entry_list:
+	 *   1. Configure the whole list by providing list of value groups:
+	 *        ccSWPortCongestionSettingMad configure -block {{1 2 3} {4 5 6}}
+	 *   2. Configure specific items from the list by providing index in addition to the above:
+	 *        ccSWPortCongestionSettingMad configure -block {{4 1 2 3} {8 4 5 6}}
+	 */
+
+	if (countSubLists > 0) {
+
+		/* check how many members does the first substring have */
+
+		if (Tcl_ListObjLength(interp, subListObjArray[0], &numElements) != TCL_OK) {
+			printf("Error: wrong format for SW Port Congestion Setting Element: %s\n",
+				Tcl_GetStringFromObj(subListObjArray[0],NULL));
+			return TCL_ERROR;
+		}
+
+		if (numElements == 3)
+			option = 1;
+		else if (numElements == 4)
+			option = 2;
+		else {
+			printf("Error: wrong number of elements for SW Port Congestion Setting Element: %s\n",
+				Tcl_GetStringFromObj(subListObjArray[0],NULL));
+			return TCL_ERROR;
+		}
+	}
+	else {
+		/* if the user didn't specify anything, use option 1,
+		   wich will effectively clear the whole list values */
+		option = 1;
+	}
+
+	if (option == 1) {
+		/*
+		 * first option - list of groups of four values
+		 */
+
+		for (idx = 0; idx < countSubLists; idx++) {
+
+			if (Tcl_ListObjLength(interp, subListObjArray[idx], &numElements) != TCL_OK) {
+				printf("Error: wrong format for SW Port Congestion Setting Element: %s\n",
+					Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+				return TCL_ERROR;
+			}
+
+			if (numElements != 3) {
+				printf("Error: wrong number of elements for SW Port Congestion Setting Element: %s\n",
+					Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+				return TCL_ERROR;
+			}
+
+			for (k = 0; k < 3; k++) {
+
+				if (Tcl_ListObjIndex(interp, subListObjArray[idx], k, &tclObj) != TCL_OK) {
+					printf("Error: Fail to obtain the element of SW Port Congestion Setting Element: %s\n",
+						Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+					return TCL_ERROR;
+				}
+				value = strtol(Tcl_GetStringFromObj(tclObj, NULL), NULL, 0);
+				switch (k) {
+					case 0: entrys[i].valid_ctrl_type_res_threshold = value; break;
+					case 1: entrys[i].packet_size = value; break;
+					case 2: entrys[i++].cong_param = cl_hton16(value); break;
+					default: break;
+				}
+			}
+		}
+
+		for (; i < $dim0; i++) {
+			entrys[i].valid_ctrl_type_res_threshold = 0;
+			entrys[i].packet_size = 0;
+			entrys[i].cong_param = 0;
+		}
+	}
+	else {
+		/*
+		 * second option - index and four values
+		 */
+
+		for (idx = 0; idx < countSubLists; idx++) {
+
+			if (Tcl_ListObjLength(interp, subListObjArray[idx], &numElements) != TCL_OK) {
+				printf("Error: wrong format for SW Port Congestion Setting Element: %s\n",
+					Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+				return TCL_ERROR;
+			}
+
+			if (numElements != 4) {
+				printf("Error: wrong number of elements for SW Port Congestion Setting Element: %s\n",
+					Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+				return TCL_ERROR;
+			}
+
+			for (k = 0; k < 4; k++) {
+
+				if (Tcl_ListObjIndex(interp, subListObjArray[idx], k, &tclObj) != TCL_OK) {
+					printf("Error: Fail to obtain the element of SW Port Congestion Setting Element: %s\n",
+						Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+					return TCL_ERROR;
+				}
+				value = strtol(Tcl_GetStringFromObj(tclObj, NULL), NULL, 0);
+				switch (k) {
+					case 0: entry_index = value; break;
+					case 1: entrys[entry_index].valid_ctrl_type_res_threshold = value; break;
+					case 2: entrys[entry_index].packet_size = value; break;
+					case 3: entrys[entry_index].cong_param = cl_hton16(value); break;
+					default: break;
+				}
+			}
+
+		}
+	}
+
+	$target = entrys;
+}
+
+%typemap(memberin) ib_sw_port_cong_setting_element_t[ANY] {
+	int i;
+	for (i=0; i <$dim0 ; i++) {
+		$target[i] = *($source+i);
+	}
+}
+
+%typemap(tcl8,out) ib_sw_port_cong_setting_element_t[ANY] {
+	int i;
+	char buff[99];
+
+	sprintf(buff, "-block ");
+	Tcl_AppendResult(interp, buff, NULL);
+
+	for (i=0; i <$dim0 ; i++) {
+		sprintf(buff, "{#%u:", i);
+		Tcl_AppendResult(interp, buff, NULL);
+
+		if ($source[i].valid_ctrl_type_res_threshold)
+			sprintf(buff, " -valid_ctrl_type_res_threshold 0x%02x", $source[i].valid_ctrl_type_res_threshold);
+		else
+			sprintf(buff, " -valid_ctrl_type_res_threshold 0");
+		Tcl_AppendResult(interp, buff, NULL);
+
+		if ($source[i].packet_size)
+			sprintf(buff, " -packet_size 0x%02x", $source[i].packet_size);
+		else
+			sprintf(buff, " -packet_size 0");
+		Tcl_AppendResult(interp, buff, NULL);
+
+		if ($source[i].cong_param)
+			sprintf(buff, " -cong_param 0x%04x", cl_ntoh16($source[i].cong_param));
+		else
+			sprintf(buff, " -cong_param 0");
+		Tcl_AppendResult(interp, buff, NULL);
+
+		sprintf(buff, "} ");
+		Tcl_AppendResult(interp, buff, NULL);
+	}
+}
+
+typedef struct _ib_sw_port_cong_setting_element {
+	uint8_t valid_ctrl_type_res_threshold;
+	uint8_t packet_size;
+	ib_net16_t cong_param;
+} ib_sw_port_cong_setting_element_t;
+
+typedef struct _ib_sw_port_cong_setting {
+	ib_sw_port_cong_setting_element_t block[32];
+} ccSWPortCongestionSetting;
+
+%addmethods ccSWPortCongestionSetting {
+
+	int getByLid(uint16_t lid, uint8_t block) {
+		return ibcc_send_mad_by_lid (
+			gp_ibcc,
+			IBCC_DEAFULT_KEY,
+			NULL,                    // log data
+			0,                       // log data size
+			(uint8_t *)self,         // mgt data
+			sizeof(ccSWPortCongestionSetting),// mgt data size
+			lid,
+			CL_NTOH16(IB_MAD_ATTR_SW_PORT_CONG_SETTING),
+			block,                   // attribute modifier
+			IB_MAD_METHOD_GET);
+	}
+
+	int setByLid(uint16_t lid, uint8_t block) {
+		return ibcc_send_mad_by_lid (
+			gp_ibcc,
+			IBCC_DEAFULT_KEY,
+			NULL,                    // log data
+			0,                       // log data size
+			(uint8_t *)self,         // mgt data
+			sizeof(ccSWPortCongestionSetting),// mgt data size
+			lid,
+			CL_NTOH16(IB_MAD_ATTR_SW_PORT_CONG_SETTING),
+			block,                   // attribute modifier
+			IB_MAD_METHOD_SET);
+	}
+
+}
+
+/**************************************************
+ ***     CACongestionSetting (A10.4.3.8)        ***
+ **************************************************/
+
+%typemap(in) ib_ca_cong_entry_t[ANY] (ib_ca_cong_entry_t entrys[$dim0]) {
+	long int value;
+	long int entry_index = 0;
+	int k;
+	int countSubLists, idx, numElements;
+	int i = 0;
+	int option = 0;
+	Tcl_Obj ** subListObjArray;
+	Tcl_Obj  * tclObj;
+
+	if (Tcl_ListObjGetElements(interp, $source, &countSubLists, &subListObjArray) != TCL_OK)
+	{
+		printf("Error: wrong format for CA Congestion Setting: %s\n",
+			Tcl_GetStringFromObj($source,NULL));
+		return TCL_ERROR;
+	}
+
+	/*
+	 * There are two options to configure entry_list:
+	 *   1. Configure the whole list by providing list of value groups:
+	 *        ccCACongestionSetting configure -entry_list {{1 2 3 4} {5 6 7 8}}
+	 *   2. Configure specific items from the list by providing index in addition to the above:
+	 *        ccCACongestionSetting configure -entry_list {{4 1 2 3 4} {8 5 6 7 8}}
+	 */
+
+	if (countSubLists > 0) {
+
+		/* check how many members does the first substring have */
+
+		if (Tcl_ListObjLength(interp, subListObjArray[0], &numElements) != TCL_OK) {
+			printf("Error: wrong format for CA Congestion Entry: %s\n",
+				Tcl_GetStringFromObj(subListObjArray[0],NULL));
+			return TCL_ERROR;
+		}
+
+		if (numElements == 4)
+			option = 1;
+		else if (numElements == 5)
+			option = 2;
+		else {
+			printf("Error: wrong number of elements for CA Congestion Entry: %s\n",
+				Tcl_GetStringFromObj(subListObjArray[0],NULL));
+			return TCL_ERROR;
+		}
+	}
+	else {
+		/* if the user didn't specify anything, use option 1,
+		   wich will effectively clear the whole list values */
+		option = 1;
+	}
+
+	if (option == 1) {
+		/*
+		 * first option - list of groups of four values
+		 */
+
+		for (idx = 0; idx < countSubLists; idx++) {
+
+			if (Tcl_ListObjLength(interp, subListObjArray[idx], &numElements) != TCL_OK) {
+				printf("Error: wrong format for CA Congestion Entry: %s\n",
+					Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+				return TCL_ERROR;
+			}
+
+			if (numElements != 4) {
+				printf("Error: wrong number of elements for CA Congestion Entry: %s\n",
+					Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+				return TCL_ERROR;
+			}
+
+			for (k = 0; k < 4; k++) {
+
+				if (Tcl_ListObjIndex(interp, subListObjArray[idx], k, &tclObj) != TCL_OK) {
+					printf("Error: Fail to obtain the element of CA Congestion Entry: %s\n",
+						Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+					return TCL_ERROR;
+				}
+				value = strtol(Tcl_GetStringFromObj(tclObj, NULL), NULL, 0);
+				switch (k) {
+					case 0: entrys[i].ccti_timer = cl_hton16(value); break;
+					case 1: entrys[i].ccti_increase = value; break;
+					case 2: entrys[i].trigger_threshold = value; break;
+					case 3: entrys[i++].ccti_min = value; break;
+					default: break;
+				}
+			}
+		}
+
+		for (; i < $dim0; i++) {
+			entrys[i].ccti_timer = 0;
+			entrys[i].ccti_increase = 0;
+			entrys[i].trigger_threshold = 0;
+			entrys[i].ccti_min = 0;
+		}
+	}
+	else {
+		/*
+		 * second option - index and four values
+		 */
+
+		for (idx = 0; idx < countSubLists; idx++) {
+
+			if (Tcl_ListObjLength(interp, subListObjArray[idx], &numElements) != TCL_OK) {
+				printf("Error: wrong format for CA Congestion Entry: %s\n",
+					Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+				return TCL_ERROR;
+			}
+
+			if (numElements != 5) {
+				printf("Error: wrong number of elements for CA Congestion Entry: %s\n",
+					Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+				return TCL_ERROR;
+			}
+
+			for (k = 0; k < 5; k++) {
+
+				if (Tcl_ListObjIndex(interp, subListObjArray[idx], k, &tclObj) != TCL_OK) {
+					printf("Error: Fail to obtain the element of CA Congestion Entry: %s\n",
+						Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+					return TCL_ERROR;
+				}
+				value = strtol(Tcl_GetStringFromObj(tclObj, NULL), NULL, 0);
+				switch (k) {
+					case 0: entry_index = value; break;
+					case 1: entrys[entry_index].ccti_timer = cl_hton16(value); break;
+					case 2: entrys[entry_index].ccti_increase = value; break;
+					case 3: entrys[entry_index].trigger_threshold = value; break;
+					case 4: entrys[entry_index].ccti_min = value; break;
+					default: break;
+				}
+			}
+
+		}
+	}
+
+	$target = entrys;
+}
+
+%typemap(memberin) ib_ca_cong_entry_t[ANY] {
+	int i;
+	for (i=0; i <$dim0 ; i++) {
+		$target[i] = *($source+i);
+	}
+}
+
+%typemap(tcl8,out) ib_ca_cong_entry_t[ANY] {
+	int i;
+	char buff[99];
+
+	sprintf(buff, "-entry_list ");
+	Tcl_AppendResult(interp, buff, NULL);
+
+	for (i=0; i <$dim0 ; i++) {
+		sprintf(buff, "{SL%u:", i);
+		Tcl_AppendResult(interp, buff, NULL);
+
+		if ($source[i].ccti_timer)
+			sprintf(buff, " -ccti_timer 0x%04x", cl_ntoh16($source[i].ccti_timer));
+		else
+			sprintf(buff, " -ccti_timer 0");
+		Tcl_AppendResult(interp, buff, NULL);
+
+		if ($source[i].ccti_increase)
+			sprintf(buff, " -ccti_increase 0x%02x", $source[i].ccti_increase);
+		else
+			sprintf(buff, " -ccti_increase 0");
+		Tcl_AppendResult(interp, buff, NULL);
+
+		if ($source[i].trigger_threshold)
+			sprintf(buff, " -trigger_threshold 0x%02x", $source[i].trigger_threshold);
+		else
+			sprintf(buff, " -trigger_threshold 0");
+		Tcl_AppendResult(interp, buff, NULL);
+
+		if ($source[i].ccti_min)
+			sprintf(buff, " -ccti_min 0x%02x", $source[i].ccti_min);
+		else
+			sprintf(buff, " -ccti_min 0");
+		Tcl_AppendResult(interp, buff, NULL);
+
+		sprintf(buff, "} ");
+		Tcl_AppendResult(interp, buff, NULL);
+	}
+}
+
+typedef struct _ib_ca_cong_entry {
+	ib_net16_t ccti_timer;
+	uint8_t ccti_increase;
+	uint8_t trigger_threshold;
+	uint8_t ccti_min;
+	uint8_t resv0;
+	ib_net16_t resv1;
+} ib_ca_cong_entry_t;
+
+typedef struct _ib_ca_cong_setting {
+	uint8_t port_control;
+	uint8_t resv0;
+	ib_net16_t control_map;
+	ib_ca_cong_entry_t entry_list[16];
+} ccCACongestionSetting;
+
+
+%addmethods ccCACongestionSetting {
+
+	int getByLid(uint16_t lid) {
+		return ibcc_send_mad_by_lid (
+			gp_ibcc,
+			IBCC_DEAFULT_KEY,
+			NULL,                    // log data
+			0,                       // log data size
+			(uint8_t *)self,         // mgt data
+			sizeof(ccCACongestionSetting),// mgt data size
+			lid,
+			CL_NTOH16(IB_MAD_ATTR_CA_CONG_SETTING),
+			0,                       // attribute modifier
+			IB_MAD_METHOD_GET);
+	}
+
+	int setByLid(uint16_t lid) {
+		return ibcc_send_mad_by_lid (
+			gp_ibcc,
+			IBCC_DEAFULT_KEY,
+			NULL,                    // log data
+			0,                       // log data size
+			(uint8_t *)self,         // mgt data
+			sizeof(ccCACongestionSetting),// mgt data size
+			lid,
+			CL_NTOH16(IB_MAD_ATTR_CA_CONG_SETTING),
+			0,                       // attribute modifier
+			IB_MAD_METHOD_SET);
+	}
+
+}
+
+/**************************************************
+ ***     CongestionControlTable (A10.4.3.9)     ***
+ **************************************************/
+
+%typemap(in) ib_cc_tbl_entry_t[ANY] (ib_cc_tbl_entry_t entrys[$dim0]) {
+	long int value;
+	long int entry_index = 0;
+	int countSubLists, idx, numElements;
+	int i = 0;
+	int option = 0;
+	Tcl_Obj ** subListObjArray;
+	Tcl_Obj  * tclObj;
+
+	if (Tcl_ListObjGetElements(interp, $source, &countSubLists, &subListObjArray) != TCL_OK)
+	{
+		printf("Error: wrong format for CC Table: %s\n",
+			Tcl_GetStringFromObj($source,NULL));
+		return TCL_ERROR;
+	}
+
+	/*
+	 * There are two options to configure entry_list:
+	 *   1. Configure the whole list by providing list of values:
+	 *        ccTableMad configure -entry_list {1 2 3 4 5 6}
+	 *   2. Configure specific items from the list by providing index and value:
+	 *        ccTableMad configure -entry_list {{1 3} {2 4} {7 16}}
+	 */
+
+	if (countSubLists > 0) {
+
+		/* check how many members does the first substring have */
+
+		if (Tcl_ListObjLength(interp, subListObjArray[0], &numElements) != TCL_OK) {
+			printf("Error: wrong format for CC Table Entry: %s\n",
+				Tcl_GetStringFromObj(subListObjArray[0],NULL));
+			return TCL_ERROR;
+		}
+
+		if (numElements == 1)
+			option = 1;
+		else if (numElements == 2)
+			option = 2;
+		else {
+			printf("Error: wrong number of elements for CC Table Entry: %s\n",
+				Tcl_GetStringFromObj(subListObjArray[0],NULL));
+			return TCL_ERROR;
+		}
+	}
+	else {
+		/* if the user didn't specify anything, use option 1,
+		   wich will effectively clear the whole list values */
+		option = 1;
+	}
+
+	if (option == 1) {
+		/*
+		 * first option - list of values
+		 */
+
+		for (idx = 0; idx < countSubLists; idx++) {
+
+			if (Tcl_ListObjLength(interp, subListObjArray[idx], &numElements) != TCL_OK) {
+				printf("Error: wrong format for CC Table Entry: %s\n",
+					Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+				return TCL_ERROR;
+			}
+
+			if (numElements != 1) {
+				printf("Error: wrong number of elements for CC Table Entry: %s\n",
+					Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+				return TCL_ERROR;
+			}
+
+			if (Tcl_ListObjIndex(interp, subListObjArray[idx], 0, &tclObj) != TCL_OK) {
+				printf("Error: Fail to obtain the element of CC Table Entry: %s\n",
+					Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+				return TCL_ERROR;
+			}
+
+			value = strtol(Tcl_GetStringFromObj(tclObj, NULL), NULL, 0);
+
+			entrys[i++].shift_multiplier = cl_hton16(value);
+		}
+
+		for (; i < $dim0; i++)
+			entrys[i].shift_multiplier = 0;
+	}
+	else {
+		/*
+		 * second option - index and value
+		 */
+
+		for (idx = 0; idx < countSubLists; idx++) {
+
+			if (Tcl_ListObjLength(interp, subListObjArray[idx], &numElements) != TCL_OK) {
+				printf("Error: wrong format for CC Table Entry: %s\n",
+					Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+				return TCL_ERROR;
+			}
+
+			if (numElements != 2) {
+				printf("Error: wrong number of elements for CC Table Entry: %s\n",
+					Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+				return TCL_ERROR;
+			}
+
+			if (Tcl_ListObjIndex(interp, subListObjArray[idx], 0, &tclObj) != TCL_OK) {
+				printf("Error: Fail to obtain the element of CC Table Entry: %s\n",
+					Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+				return TCL_ERROR;
+			}
+
+			entry_index = strtol(Tcl_GetStringFromObj(tclObj, NULL), NULL, 0);
+
+			if (Tcl_ListObjIndex(interp, subListObjArray[idx], 1, &tclObj) != TCL_OK) {
+				printf("Error: Fail to obtain the element of CC Table Entry: %s\n",
+					Tcl_GetStringFromObj(subListObjArray[idx],NULL));
+				return TCL_ERROR;
+			}
+
+			value = strtol(Tcl_GetStringFromObj(tclObj, NULL), NULL, 0);
+
+			entrys[entry_index].shift_multiplier = cl_hton16(value);
+		}
+	}
+
+	$target = entrys;
+}
+
+%typemap(memberin) ib_cc_tbl_entry_t[ANY] {
+	int i;
+	for (i=0; i <$dim0 ; i++) {
+		$target[i] = *($source+i);
+	}
+}
+
+%typemap(tcl8,out) ib_cc_tbl_entry_t[ANY] {
+	int i;
+	char buff[99];
+
+	sprintf(buff, "-entry_list ");
+	Tcl_AppendResult(interp, buff, NULL);
+
+	for (i=0; i <$dim0 ; i++) {
+		if ($source[i].shift_multiplier)
+			sprintf(buff, "{#%u: 0x%04x} ", i, cl_ntoh16($source[i].shift_multiplier));
+		else
+			sprintf(buff, "{#%u: 0} ", i);
+		Tcl_AppendResult(interp, buff, NULL);
+	}
+}
+
+typedef struct _ibcc_tbl_entry {
+	ib_net16_t shift_multiplier;
+} ib_cc_tbl_entry_t;
+
+typedef struct _ib_cc_tbl {
+	ib_net16_t ccti_limit;
+	ib_net16_t resv;
+	ib_cc_tbl_entry_t entry_list[64];
+} ccTable;
+
+%addmethods ccTable {
+
+	int getByLid(uint16_t lid, uint8_t sn) {
+		return ibcc_send_mad_by_lid (
+			gp_ibcc,
+			IBCC_DEAFULT_KEY,
+			NULL,                    // log data
+			0,                       // log data size
+			(uint8_t *)self,         // mgt data
+			sizeof(ccTable),         // mgt data size
+			lid,
+			CL_NTOH16(IB_MAD_ATTR_CC_TBL),
+			sn,                      // attribute modifier
+			IB_MAD_METHOD_GET);
+	}
+
+	int setByLid(uint16_t lid, uint8_t sn) {
+		return ibcc_send_mad_by_lid (
+			gp_ibcc,
+			IBCC_DEAFULT_KEY,
+			NULL,                    // log data
+			0,                       // log data size
+			(uint8_t *)self,         // mgt data
+			sizeof(ccTable),         // mgt data size
+			lid,
+			CL_NTOH16(IB_MAD_ATTR_CC_TBL),
+			sn,                      // attribute modifier
+			IB_MAD_METHOD_SET);
+	}
+
+}
+
+/**************************************************
+ ***           TimeStamp (A10.4.3.10)           ***
+ **************************************************/
+
+typedef struct _ib_time_stamp {
+	ib_net32_t value;
+} ccTimeStamp;
+
+%addmethods ccTimeStamp {
+
+	int getByLid(uint16_t lid) {
+		return ibcc_send_mad_by_lid (
+			gp_ibcc,
+			IBCC_DEAFULT_KEY,
+			NULL,                    // log data
+			0,                       // log data size
+			(uint8_t *)self,         // mgt data
+			sizeof(ccTimeStamp),     // mgt data size
+			lid,
+			CL_NTOH16(IB_MAD_ATTR_TIME_STAMP),
+			0,                       // attribute modifier
+			IB_MAD_METHOD_GET);
+	}
+
+}
-- 
1.5.1.4





More information about the general mailing list