[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