--- /dev/null
+/*\r
+ * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id$\r
+ */\r
+\r
+\r
+/*\r
+ * Abstract:\r
+ * Test limits for:\r
+ * - memory registration\r
+ * - CQ creation\r
+ * - CQ resize\r
+ * - QP creation\r
+ *\r
+ * Environment:\r
+ * User Mode\r
+ */\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <stdarg.h>\r
+#include <ctype.h>\r
+#include <complib/cl_atomic.h>\r
+#include <complib/cl_debug.h>\r
+#include <complib/cl_event.h>\r
+#include <complib/cl_math.h>\r
+#include <complib/cl_mutex.h>\r
+#include <complib/cl_qlist.h>\r
+#include <complib/cl_thread.h>\r
+#include <complib/cl_timer.h>\r
+#include <iba/ib_types.h>\r
+#include <iba/ib_al.h>\r
+\r
+\r
+/* Globals */\r
+#define CMT_DBG_VERBOSE 1\r
+\r
+\r
+uint32_t cmt_dbg_lvl = 0x80000000;\r
+\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static void\r
+__show_usage()\r
+{\r
+ printf( "\n------- ib_limits - Usage and options ----------------------\n" );\r
+ printf( "Usage: ib_limits [options]\n");\r
+ printf( "Options:\n" );\r
+ printf( "-m\n"\r
+ "--memory\n"\r
+ "\tThis option directs ib_limits to test memory registration\n" );\r
+ printf( "-c\n"\r
+ "--cq\n"\r
+ "\tThis option directs ib_limits to test CQ creation\n" );\r
+ printf( "-r\n"\r
+ "--resize_cq\n"\r
+ "\tThis option directs ib_limits to test CQ resize\n" );\r
+ printf( "-q\n"\r
+ "--qp\n"\r
+ "\tThis option directs ib_limits to test QP creation\n" );\r
+ printf( "-v\n"\r
+ "--verbose\n"\r
+ " This option enables verbosity level to debug console.\n" );\r
+ printf( "-h\n"\r
+ "--help\n"\r
+ " Display this usage info then exit.\n\n" );\r
+}\r
+\r
+\r
+/* Windows support. */\r
+struct option\r
+{\r
+ const char *long_name;\r
+ unsigned long flag;\r
+ void *pfn_handler;\r
+ char short_name;\r
+};\r
+\r
+static char *optarg;\r
+\r
+#define strtoull strtoul\r
+\r
+\r
+boolean_t test_mr, test_cq, test_resize, test_qp;\r
+\r
+\r
+char\r
+getopt_long(\r
+ int argc,\r
+ char *argv[],\r
+ const char *short_option,\r
+ const struct option *long_option,\r
+ void *unused )\r
+{\r
+ static int i = 1;\r
+ int j;\r
+ char ret = 0;\r
+\r
+ UNUSED_PARAM( unused );\r
+\r
+ if( i == argc )\r
+ return -1;\r
+\r
+ if( argv[i][0] != '-' )\r
+ return ret;\r
+\r
+ /* find the first character of the value. */\r
+ for( j = 1; isalpha( argv[i][j] ); j++ )\r
+ ;\r
+ optarg = &argv[i][j];\r
+\r
+ if( argv[i][1] == '-' )\r
+ {\r
+ /* Long option. */\r
+ for( j = 0; long_option[j].long_name; j++ )\r
+ {\r
+ if( strncmp( &argv[i][2], long_option[j].long_name,\r
+ optarg - argv[i] - 2 ) )\r
+ {\r
+ continue;\r
+ }\r
+\r
+ switch( long_option[j].flag )\r
+ {\r
+ case 1:\r
+ if( *optarg == '\0' )\r
+ return 0;\r
+ default:\r
+ break;\r
+ }\r
+ ret = long_option[j].short_name;\r
+ break;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ for( j = 0; short_option[j] != '\0'; j++ )\r
+ {\r
+ if( !isalpha( short_option[j] ) )\r
+ return 0;\r
+\r
+ if( short_option[j] == argv[i][1] )\r
+ {\r
+ ret = short_option[j];\r
+ break;\r
+ }\r
+\r
+ if( short_option[j+1] == ':' )\r
+ {\r
+ if( *optarg == '\0' )\r
+ return 0;\r
+ j++;\r
+ }\r
+ }\r
+ }\r
+ i++;\r
+ return ret;\r
+}\r
+\r
+\r
+static boolean_t\r
+__parse_options(\r
+ int argc,\r
+ char* argv[] )\r
+{\r
+ uint32_t next_option;\r
+ const char* const short_option = "mcrq:vh";\r
+\r
+ /*\r
+ In the array below, the 2nd parameter specified the number\r
+ of arguments as follows:\r
+ 0: no arguments\r
+ 1: argument\r
+ 2: optional\r
+ */\r
+ const struct option long_option[] =\r
+ {\r
+ { "memory", 2, NULL, 'm'},\r
+ { "cq", 2, NULL, 'c'},\r
+ { "resize_cq",2, NULL, 'r'},\r
+ { "qp", 2, NULL, 'q'},\r
+ { "verbose", 0, NULL, 'v'},\r
+ { "help", 0, NULL, 'h'},\r
+ { NULL, 0, NULL, 0 } /* Required at end of array */\r
+ };\r
+\r
+ test_mr = FALSE;\r
+ test_cq = FALSE;\r
+ test_resize = FALSE;\r
+ test_qp = FALSE;\r
+\r
+ /* parse cmd line arguments as input params */\r
+ do\r
+ {\r
+ next_option = getopt_long( argc, argv, short_option,\r
+ long_option, NULL );\r
+\r
+ switch( next_option )\r
+ {\r
+ case 'm':\r
+ test_mr = TRUE;\r
+ printf( "\tTest Memory Registration\n" );\r
+ break;\r
+\r
+ case 'c':\r
+ test_cq = TRUE;\r
+ printf( "\tTest CQ\n" );\r
+ break;\r
+\r
+ case 'r':\r
+ test_resize = TRUE;\r
+ printf( "\tTest CQ Resize\n" );\r
+ break;\r
+\r
+ case 'q':\r
+ test_qp = TRUE;\r
+ printf( "\tTest QP\n" );\r
+ break;\r
+\r
+ case 'v':\r
+ cmt_dbg_lvl = 0xFFFFFFFF;\r
+ printf( "\tverbose\n" );\r
+ break;\r
+\r
+ case 'h':\r
+ __show_usage();\r
+ return FALSE;\r
+\r
+ case -1:\r
+ break;\r
+\r
+ default: /* something wrong */\r
+ __show_usage();\r
+ return FALSE;\r
+ }\r
+ } while( next_option != -1 );\r
+\r
+ return TRUE;\r
+}\r
+\r
+\r
+struct __mr_buf\r
+{\r
+ cl_list_item_t list_item;\r
+ ib_mr_handle_t h_mr;\r
+ char buf[8192 - sizeof(ib_mr_handle_t) - sizeof(cl_list_item_t)];\r
+};\r
+\r
+static void\r
+__test_mr(\r
+ ib_pd_handle_t h_pd )\r
+{\r
+ ib_api_status_t status = IB_SUCCESS;\r
+ struct __mr_buf *p_mr;\r
+ int i = 0;\r
+ ib_mr_create_t mr_create;\r
+ cl_qlist_t mr_list;\r
+ net32_t lkey, rkey;\r
+ int64_t reg_time, dereg_time, tmp_time, cnt;\r
+\r
+ printf( "MR testing [\n" );\r
+\r
+ cl_qlist_init( &mr_list );\r
+ reg_time = 0;\r
+ dereg_time = 0;\r
+ cnt = 0;\r
+\r
+ do\r
+ {\r
+ p_mr = cl_malloc( sizeof(struct __mr_buf) );\r
+ if( !p_mr )\r
+ {\r
+ i++;\r
+ printf( "Failed to allocate memory.\n" );\r
+ continue;\r
+ }\r
+\r
+ mr_create.vaddr = p_mr->buf;\r
+ mr_create.length = sizeof(p_mr->buf);\r
+ mr_create.access_ctrl =\r
+ IB_AC_LOCAL_WRITE | IB_AC_RDMA_READ | IB_AC_RDMA_WRITE;\r
+\r
+ tmp_time = cl_get_time_stamp();\r
+ status = ib_reg_mem( h_pd, &mr_create, &lkey, &rkey, &p_mr->h_mr );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ i++;\r
+ printf( "ib_reg_mem returned %s\n", ib_get_err_str( status ) );\r
+ cl_free( p_mr );\r
+ continue;\r
+ }\r
+ reg_time += cl_get_time_stamp() - tmp_time;\r
+ cnt++;\r
+\r
+ cl_qlist_insert_tail( &mr_list, &p_mr->list_item );\r
+\r
+ } while( status == IB_SUCCESS || i < 1000 );\r
+\r
+ while( cl_qlist_count( &mr_list ) )\r
+ {\r
+ p_mr = PARENT_STRUCT( cl_qlist_remove_head( &mr_list ),\r
+ struct __mr_buf, list_item );\r
+\r
+ tmp_time = cl_get_time_stamp();\r
+ status = ib_dereg_mr( p_mr->h_mr );\r
+ if( status != IB_SUCCESS )\r
+ printf( "ib_dereg_mr returned %s\n", ib_get_err_str( status ) );\r
+ dereg_time += cl_get_time_stamp() - tmp_time;\r
+\r
+ cl_free( p_mr );\r
+ }\r
+\r
+ printf( "reg time %f, dereg time %f\n", (double)reg_time/(double)cnt,\r
+ (double)dereg_time/(double)cnt );\r
+ printf( "MR testing ]\n" );\r
+}\r
+\r
+\r
+struct __cq\r
+{\r
+ cl_list_item_t list_item;\r
+ ib_cq_handle_t h_cq;\r
+};\r
+\r
+static void\r
+__test_cq(\r
+ ib_ca_handle_t h_ca,\r
+ boolean_t resize )\r
+{\r
+ ib_api_status_t status = IB_SUCCESS;\r
+ struct __cq *p_cq;\r
+ int i = 0, j;\r
+ ib_cq_create_t cq_create;\r
+ cl_qlist_t cq_list;\r
+ cl_waitobj_handle_t h_waitobj;\r
+ uint32_t size;\r
+\r
+ printf( "CQ %stesting [\n", resize?"resize ":"" );\r
+\r
+ cl_qlist_init( &cq_list );\r
+\r
+ if( cl_waitobj_create( FALSE, &h_waitobj ) != CL_SUCCESS )\r
+ {\r
+ printf( "Failed to allocate CQ wait object.\n" );\r
+ return;\r
+ }\r
+\r
+ do\r
+ {\r
+ p_cq = cl_malloc( sizeof(*p_cq) );\r
+ if( !p_cq )\r
+ {\r
+ i++;\r
+ printf( "Failed to allocate memory.\n" );\r
+ continue;\r
+ }\r
+\r
+ cq_create.h_wait_obj = h_waitobj;\r
+ cq_create.pfn_comp_cb = NULL;\r
+ if( resize )\r
+ cq_create.size = 32;\r
+ else\r
+ cq_create.size = 4096;\r
+\r
+ status = ib_create_cq( h_ca, &cq_create, NULL, NULL, &p_cq->h_cq );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ i++;\r
+ printf( "ib_create_cq returned %s\n", ib_get_err_str( status ) );\r
+ cl_free( p_cq );\r
+ continue;\r
+ }\r
+\r
+ if( resize )\r
+ {\r
+ size = 256;\r
+ j = 0;\r
+\r
+ do\r
+ {\r
+ status = ib_modify_cq( p_cq->h_cq, &size );\r
+ if( status == IB_SUCCESS )\r
+ {\r
+ size += 256;\r
+ }\r
+ else\r
+ {\r
+ j++;\r
+ printf( "ib_modify_cq returned %s\n",\r
+ ib_get_err_str( status ) );\r
+ }\r
+\r
+ } while( status == IB_SUCCESS || j < 100 );\r
+ }\r
+\r
+ cl_qlist_insert_tail( &cq_list, &p_cq->list_item );\r
+\r
+ } while( status == IB_SUCCESS || i < 1000 );\r
+\r
+ while( cl_qlist_count( &cq_list ) )\r
+ {\r
+ p_cq = PARENT_STRUCT( cl_qlist_remove_head( &cq_list ),\r
+ struct __cq, list_item );\r
+\r
+ status = ib_destroy_cq( p_cq->h_cq, NULL );\r
+ if( status != IB_SUCCESS )\r
+ printf( "ib_destroy_cq returned %s\n", ib_get_err_str( status ) );\r
+\r
+ cl_free( p_cq );\r
+ }\r
+\r
+ printf( "CQ %stesting ]\n", resize?"resize ":"" );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+int __cdecl\r
+main(\r
+ int argc,\r
+ char* argv[] )\r
+{\r
+ ib_api_status_t status;\r
+ ib_al_handle_t h_al;\r
+ ib_ca_handle_t h_ca;\r
+ ib_pd_handle_t h_pd;\r
+ size_t size;\r
+ net64_t *ca_guids;\r
+\r
+ /* Set defaults. */\r
+ if( !__parse_options( argc, argv ) )\r
+ return 1;\r
+\r
+ status = ib_open_al( &h_al );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ printf( "ib_open_al returned %s\n", ib_get_err_str( status ) );\r
+ return 1;\r
+ }\r
+\r
+ size = 0;\r
+ status = ib_get_ca_guids( h_al, NULL, &size );\r
+ if( status != IB_INSUFFICIENT_MEMORY )\r
+ {\r
+ printf( "ib_get_ca_guids for array size returned %s",\r
+ ib_get_err_str( status ) );\r
+ goto done;\r
+ }\r
+\r
+ if( size == 0 )\r
+ {\r
+ printf( "No CAs installed.\n" );\r
+ goto done;\r
+ }\r
+\r
+ ca_guids = malloc( sizeof(net64_t) * size );\r
+ if( !ca_guids )\r
+ {\r
+ printf( "Failed to allocate CA GUID array.\n" );\r
+ goto done;\r
+ }\r
+\r
+ status = ib_get_ca_guids( h_al, ca_guids, &size );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ printf( "ib_get_ca_guids for CA guids returned %s",\r
+ ib_get_err_str( status ) );\r
+ free( ca_guids );\r
+ goto done;\r
+ }\r
+\r
+ status = ib_open_ca( h_al, ca_guids[0], NULL, NULL, &h_ca );\r
+ free( ca_guids );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ printf( "ib_open_ca returned %s", ib_get_err_str( status ) );\r
+ goto done;\r
+ }\r
+\r
+ status = ib_alloc_pd( h_ca, IB_PDT_NORMAL, NULL, &h_pd );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ printf( "ib_alloc_pd returned %s", ib_get_err_str( status ) );\r
+ goto done;\r
+ }\r
+\r
+ if( test_mr )\r
+ __test_mr( h_pd );\r
+\r
+ if( test_cq )\r
+ __test_cq( h_ca, FALSE );\r
+\r
+ if( test_resize )\r
+ __test_cq( h_ca, TRUE );\r
+\r
+ //if( test_qp )\r
+ // __test_qp( h_ca, h_pd );\r
+\r
+done:\r
+ ib_close_al( h_al );\r
+\r
+ return 0;\r
+}\r