[QLGC VNIC] VNIC configuration tool.
authoraestrin <aestrin@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Tue, 24 Mar 2009 15:47:54 +0000 (15:47 +0000)
committeraestrin <aestrin@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Tue, 24 Mar 2009 15:47:54 +0000 (15:47 +0000)
Part of the solution for having a vendor defined device created by ibiou. This tool sends device IOCTLs to IBIOU for listing the reachable IOCs and for creation of child PDOs.
Submitted by Deepak Gupta (deepal.gupta@qlogic.com)

git-svn-id: svn://openib.tc.cornell.edu/gen1/trunk@2044 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

tools/dirs
tools/qlgcvnic_config/SOURCES [new file with mode: 0644]
tools/qlgcvnic_config/makefile [new file with mode: 0644]
tools/qlgcvnic_config/vnic_child_config.c [new file with mode: 0644]

index 2cd347e..2d121e9 100644 (file)
@@ -4,4 +4,5 @@ DIRS = \
        nsc                     \\r
        perftests       \\r
        part_man        \\r
-       infiniband-diags
\ No newline at end of file
+       infiniband-diags \\r
+       qlgcvnic_config\r
diff --git a/tools/qlgcvnic_config/SOURCES b/tools/qlgcvnic_config/SOURCES
new file mode 100644 (file)
index 0000000..b0a0efc
--- /dev/null
@@ -0,0 +1,20 @@
+TARGETNAME=qlgcvnic_config\r
+TARGETPATH=..\..\bin\user\obj$(BUILD_ALT_DIR)\r
+TARGETTYPE=PROGRAM\r
+UMTYPE=console\r
+USE_MSVCRT=1\r
+\r
+SOURCES= \\r
+       vnic_child_config.c\r
+\r
+INCLUDES=..\..\inc;..\..\inc\user;..\..\core\al\r
+TARGETLIBS= \\r
+!if $(FREEBUILD)\r
+                       $(TARGETPATH)\*\complib.lib \\r
+!else\r
+                       $(TARGETPATH)\*\complibd.lib \\r
+!endif\r
+\r
+#RCOPTIONS=/I..\..\win\include\r
+\r
+MSC_WARNING_LEVEL= /W3\r
diff --git a/tools/qlgcvnic_config/makefile b/tools/qlgcvnic_config/makefile
new file mode 100644 (file)
index 0000000..783b184
--- /dev/null
@@ -0,0 +1,7 @@
+#\r
+# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source\r
+# file to this component.  This file merely indirects to the real make file\r
+# that is shared by all the driver components of the OpenIB Windows project.\r
+#\r
+\r
+!INCLUDE ..\..\inc\openib.def\r
diff --git a/tools/qlgcvnic_config/vnic_child_config.c b/tools/qlgcvnic_config/vnic_child_config.c
new file mode 100644 (file)
index 0000000..ce70cac
--- /dev/null
@@ -0,0 +1,529 @@
+#include <stdio.h>\r
+#include <string.h>\r
+#include <wchar.h>\r
+#include <windows.h>\r
+#include <al_dev.h>\r
+#include <complib/cl_byteswap.h>\r
+#include <complib/cl_memory.h>\r
+\r
+#define MAX_DEVICE_ID_LEN     200\r
+#define MAX_DEVICE_STRING_LEN          MAX_DEVICE_ID_LEN + 2   /* add extra 4 bytes in case we need double NULL ending */\r
+\r
+#pragma pack(push, 1)\r
+typedef struct _ca_ioc_info {\r
+       net64_t                                 ca_guid;\r
+       ib_ioc_info_t                           info;\r
+       ib_svc_entry_t                          svc_entry_array[1];\r
+} ca_ioc_info_t;\r
+\r
+typedef struct _child_device_info {\r
+       wchar_t         device_id[MAX_DEVICE_STRING_LEN];  \r
+       uint32_t        device_id_size;\r
+       wchar_t         compatible_id[MAX_DEVICE_STRING_LEN];\r
+       uint32_t        compatible_id_size;\r
+       wchar_t         hardware_id[MAX_DEVICE_STRING_LEN];\r
+       uint32_t        hardware_id_size;\r
+       wchar_t         description[MAX_DEVICE_STRING_LEN];\r
+       uint32_t        description_size;\r
+       ca_ioc_info_t   ca_ioc_path;\r
+       uint32_t        uniqueinstanceid;\r
+}  child_device_info_t;\r
+\r
+#pragma pack(pop)\r
+\r
+int usage()\r
+{\r
+       printf( "Correct usage to create VNIC child devices is:-\n" );\r
+       printf( "qlgcvnic_config -c <CAGUID> <IOCGUID> "\r
+               "<InstanceID> <Interface Description>\n" );\r
+       printf( "Executing qlgcvnic_config without any option or with -l "\r
+               "option will list the IOCs reachable from the host\n" );\r
+       return -1;\r
+}\r
+\r
+DWORD  send_device_ioctl( DWORD ioctlcode, PVOID input_buf, DWORD in_size, PVOID *output_buf, PDWORD out_size )\r
+{\r
+       DWORD   dwRet = 0, dwMemSize, dwBytesRet = 0;\r
+       BOOL    bRet;\r
+       PVOID   pBuf;\r
+       HANDLE  hDevice = INVALID_HANDLE_VALUE;\r
+\r
+       hDevice = CreateFileW ( L"\\\\.\\VNICCONFIG",\r
+                               GENERIC_READ | GENERIC_WRITE,\r
+                               FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share mode none */\r
+                               NULL,                                   /* no security */\r
+                               OPEN_EXISTING,\r
+                               FILE_ATTRIBUTE_NORMAL,\r
+                               NULL );                                 /* no template; */\r
+\r
+       if ( hDevice == INVALID_HANDLE_VALUE ) \r
+       {\r
+               printf( "Error opening VNICCONFIG device file\n" );\r
+               return ERROR_FILE_NOT_FOUND;\r
+       }\r
+\r
+       switch( ioctlcode ) \r
+       {\r
+               case    UAL_IOC_DEVICE_CREATE:\r
+                       bRet = DeviceIoControl( hDevice, ioctlcode, input_buf, in_size, NULL, 0, &dwBytesRet, NULL );\r
+\r
+                       if ( !bRet ) \r
+                       {\r
+                               dwRet = GetLastError();\r
+                               printf( "GetLastError after UAL_IOC_DEVICE_CREATE gives %d\n", dwRet );\r
+                       }\r
+                       break;\r
+\r
+               case    UAL_IOC_LIST:\r
+                       dwMemSize = sizeof(ca_ioc_info_t ) * 2;\r
+                       pBuf = NULL;\r
+\r
+                       do \r
+                       {\r
+                               if ( pBuf ) \r
+                               {\r
+                                       cl_free( pBuf );\r
+                                       dwMemSize *= 2;                                 \r
+                                       pBuf = NULL;\r
+                               }\r
+\r
+                               pBuf = cl_malloc( dwMemSize );\r
+\r
+                               if ( !pBuf ) \r
+                               {\r
+                                       printf( "Insufficient memory\n" );\r
+                                       dwRet = ERROR_NOT_ENOUGH_MEMORY;\r
+                                       break;\r
+                               }\r
+\r
+                               bRet = DeviceIoControl( hDevice, ioctlcode, NULL, 0, pBuf, dwMemSize, &dwBytesRet, NULL );\r
+                               dwRet = GetLastError();\r
+\r
+                               if ( bRet ) \r
+                               {\r
+                                       dwRet = 0;\r
+                                       break;\r
+                               }\r
+                               \r
+                       }while( dwRet == ERROR_INSUFFICIENT_BUFFER );\r
+\r
+                       *output_buf = pBuf;\r
+                       *out_size = dwBytesRet;\r
+\r
+                       break;\r
+       }\r
+\r
+       CloseHandle( hDevice );\r
+       return dwRet;\r
+}\r
+\r
+ca_ioc_info_t  *find_ca_ioc_path ( ca_ioc_info_t       *pList, DWORD   nListSize,\r
+                       uint64_t        ca_guid, uint64_t       ioc_guid )\r
+{\r
+       while ( nListSize ) \r
+       {\r
+\r
+               if ( pList->ca_guid == ca_guid && pList->info.profile.ioc_guid == ioc_guid ) \r
+               {\r
+                       return pList;\r
+               }\r
+               nListSize--;\r
+               pList++;\r
+       }\r
+\r
+       return NULL;\r
+}\r
+\r
+#define        IBIOU_SERVICE_PARAM_KEY         "SYSTEM\\CurrentControlSet\\Services\\ibiou"\r
+#define        IBIOU_PARAM_KEY_DEVICE_VALUE    "StaticChild"\r
+#define        IBIOU_PARAMETER_NAME            "Parameters"\r
+#define        MAX_VALUE_LENGTH                2048\r
+\r
+DWORD  write_device_name( char *device_name )\r
+{\r
+\r
+       DWORD   dwRet = 0, dwBytesRet = 0, n_size = 100, dwType;\r
+       HKEY    hKey = INVALID_HANDLE_VALUE;\r
+       LONG    lRet = -1;\r
+       PVOID   pOldValue, pNewValue, pBuf;\r
+       char    szKeyName[200];\r
+\r
+       sprintf( szKeyName, "%s\\%s", IBIOU_SERVICE_PARAM_KEY, IBIOU_PARAMETER_NAME );\r
+       lRet = RegOpenKeyExA( HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_ALL_ACCESS, \r
+                               &hKey );\r
+\r
+\r
+       if ( lRet != ERROR_SUCCESS ) \r
+       {\r
+               printf( "Opening services key of ibiou failed\n" );\r
+               dwRet = -1;\r
+       } \r
+       else \r
+       {\r
+               do \r
+               {\r
+                       pOldValue = cl_malloc( n_size );\r
+\r
+                       if ( !pOldValue ) \r
+                       {\r
+                               printf( "Not enough memory on system\n" );\r
+                               break;\r
+                       }\r
+                       dwType = REG_MULTI_SZ;\r
+\r
+                       lRet = RegQueryValueExA( hKey, IBIOU_PARAM_KEY_DEVICE_VALUE, 0, &dwType, pOldValue, &dwBytesRet );\r
+\r
+\r
+                       if ( lRet == ERROR_MORE_DATA ) \r
+                       {\r
+                               cl_free( pOldValue );\r
+                               pOldValue = NULL;\r
+                               n_size = n_size*2;\r
+                       }\r
+\r
+               } while( lRet == ERROR_MORE_DATA && n_size < MAX_VALUE_LENGTH );\r
+\r
+               if ( lRet != ERROR_SUCCESS ) \r
+               {\r
+                       cl_free( pOldValue );\r
+                       pOldValue = NULL;\r
+               }\r
+\r
+\r
+               n_size = dwBytesRet + strlen( device_name )*sizeof( char ) + 2*sizeof( char ); /*  more for NULLs */\r
+               pNewValue = cl_malloc( n_size );\r
+               pBuf = pNewValue;\r
+               cl_memset( pNewValue, 0x00, n_size );\r
+               if ( !pNewValue ) \r
+               {\r
+                       printf( "Not enough memory on system\n" );\r
+               } \r
+               else \r
+               {\r
+                       if ( pOldValue ) \r
+                       {       /* Come here only when "StaticChild" key was there already*/\r
+                               cl_memcpy( pBuf, pOldValue, dwBytesRet );\r
+\r
+                               while ( *( ( PBYTE )pBuf ) != 0 || *( ( PBYTE ) pBuf + 1 ) != 0 )\r
+                                       pBuf = ( PBYTE ) pBuf + 1;\r
+\r
+                               pBuf = ( PBYTE ) pBuf + 1;\r
+                               cl_free( pOldValue );\r
+                               pOldValue = NULL;\r
+                       }\r
+\r
+                       cl_memcpy( pBuf, device_name, strlen( device_name ) );\r
+                       lRet = RegSetValueExA( hKey, IBIOU_PARAM_KEY_DEVICE_VALUE, 0, REG_MULTI_SZ, \r
+                                               pNewValue, ( strlen( device_name ) + dwBytesRet + 2 ) ); /* Two bytes for extra NULLs*/\r
+                       cl_free( pNewValue );\r
+                       RegCloseKey( hKey );\r
+                       if ( lRet != ERROR_SUCCESS ) \r
+                       {\r
+                               printf( "Error setting device name in value of services key of ibiou\n" );\r
+                               dwRet = -1;\r
+                       }\r
+               }\r
+\r
+       }\r
+       return dwRet;   \r
+}\r
+\r
+static const   char    *value_names[] = {\r
+               "CAGUID",\r
+#define                CAGUID_INDEX            0\r
+               "IOCGUID",\r
+#define                IOCGUID_INDEX           1\r
+               "CompatibleId",\r
+#define                COMPATIBLEID_INDEX      2\r
+               "Description",\r
+#define                DESCRIPTION_INDEX       3\r
+               "DeviceId",\r
+#define                DEVICEID_INDEX          4\r
+               "HardwareId",\r
+#define                HARDWAREID_INDEX        5\r
+               "InstanceId"\r
+#define                INSTANCEID_INDEX        6\r
+#define                MAXVALUE_INDEX          7\r
+};\r
+\r
+DWORD  write_deviceinfo_to_registry( uint64_t  ca_guid, uint64_t       ioc_guid, \r
+                                       uint32_t        instance_id, char *device_name )\r
+{\r
+       DWORD   dwRet = 0, dwDisposition, dwType, dwSize;\r
+       HKEY    hKey = INVALID_HANDLE_VALUE;\r
+       char    szKeyName[250];\r
+       LONG    lRet;\r
+       DWORD   dwIndex;\r
+       PVOID   pBuf;\r
+\r
+       dwRet = write_device_name( device_name );\r
+\r
+       if ( dwRet == 0 ) \r
+       {\r
+               sprintf( szKeyName, "%s\\%s\\%s", \r
+                       IBIOU_SERVICE_PARAM_KEY, IBIOU_PARAMETER_NAME, device_name );\r
+               lRet = RegCreateKeyExA( HKEY_LOCAL_MACHINE, szKeyName, 0,\r
+                                       NULL, REG_OPTION_NON_VOLATILE, \r
+                                       KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition  );\r
+\r
+               if ( dwDisposition == REG_CREATED_NEW_KEY ) \r
+               {\r
+                       dwIndex = CAGUID_INDEX;\r
+                       \r
+                       while ( dwIndex < MAXVALUE_INDEX ) \r
+                       {\r
+\r
+                               switch( dwIndex ) \r
+                               {\r
+                                       case    CAGUID_INDEX:\r
+                                               pBuf = &ca_guid;\r
+                                               dwType = REG_BINARY;\r
+                                               dwSize = sizeof( uint64_t );\r
+                                               break;\r
+\r
+                                       case    IOCGUID_INDEX:\r
+                                               pBuf = &ioc_guid;\r
+                                               dwType = REG_BINARY;\r
+                                               dwSize = sizeof( uint64_t );                                            \r
+                                               break;\r
+\r
+                                       case    DEVICEID_INDEX:\r
+                                               pBuf = "IBA\\qlgcvnic";\r
+                                               dwType = REG_SZ;\r
+                                               dwSize = strlen( pBuf ) + 1;\r
+                                               break;\r
+\r
+                                       case    COMPATIBLEID_INDEX:             /* Currently all id's used are same. */\r
+                                       case    HARDWAREID_INDEX:\r
+                                               pBuf = "IBA\\qlgcvnic";\r
+                                               dwType = REG_MULTI_SZ;\r
+                                               dwSize = strlen( pBuf ) + 1;                                            \r
+                                               break;\r
+\r
+                                       case    DESCRIPTION_INDEX:      \r
+                                               pBuf = device_name;\r
+                                               dwType = REG_SZ;\r
+                                               dwSize = strlen( pBuf ) + 1;                                            \r
+                                               break;\r
+\r
+                                       case    INSTANCEID_INDEX:\r
+                                               pBuf = &instance_id;\r
+                                               dwType = REG_DWORD;\r
+                                               dwSize = sizeof( instance_id );\r
+                                               break;\r
+\r
+                                       default:\r
+                                               break;\r
+                               }\r
+                               lRet = RegSetValueExA( hKey, value_names[dwIndex], 0,\r
+                                                       dwType, pBuf, dwSize );\r
+\r
+                               if ( lRet != ERROR_SUCCESS ) \r
+                               {\r
+                                       printf( "Failed in setting device information as Parameters of ibiou driver\n" );\r
+                                       dwRet = -1;\r
+                                       break;\r
+                               }\r
+\r
+                               dwIndex++;\r
+                       }\r
+               }\r
+\r
+               if ( hKey != INVALID_HANDLE_VALUE ) \r
+               {\r
+                       RegCloseKey( hKey );\r
+               }\r
+       }\r
+\r
+       return dwRet;\r
+}\r
+\r
+DWORD  create_child_device( uint64_t   ca_guid, uint64_t       ioc_guid, uint32_t instance_id, char *device_name )\r
+{\r
+       ca_ioc_info_t           *pList = NULL, *p_ca_ioc_entry = NULL;\r
+       DWORD                   dwRet = 0, dwBytesRet;\r
+       child_device_info_t     *child_dev = NULL;\r
+       WCHAR                   szDevName[200];\r
+\r
+\r
+       dwRet = send_device_ioctl( UAL_IOC_LIST, NULL, 0, &pList, &dwBytesRet );\r
+\r
+       if ( dwRet ) \r
+       {\r
+               printf( "Obtaining IOC LIST from ibiou failed\n" );\r
+       } \r
+       else \r
+       {\r
+               p_ca_ioc_entry = find_ca_ioc_path( pList, dwBytesRet/sizeof( ca_ioc_info_t ),\r
+                                       ca_guid, ioc_guid );\r
+\r
+               if ( p_ca_ioc_entry ) \r
+               {\r
+                       child_dev = cl_malloc( sizeof( child_device_info_t ) );\r
+                       cl_memset( child_dev, 0x00, sizeof( child_device_info_t ) );\r
+\r
+                       if ( !child_dev ) \r
+                       {\r
+                               printf( "Allocating memory for child device failed\n" );\r
+                       } \r
+                       else \r
+                       {\r
+                               child_dev->ca_ioc_path = *p_ca_ioc_entry;\r
+                               wcscpy( child_dev->device_id, L"IBA\\qlgcvnic" );\r
+                               child_dev->device_id_size = ( wcslen( child_dev->device_id ) + 1 )*sizeof( WCHAR );\r
+                               wcscpy( child_dev->hardware_id, L"IBA\\qlgcvnic" );\r
+                               child_dev->hardware_id_size = ( wcslen( child_dev->hardware_id ) + 2 )*sizeof( WCHAR );\r
+                               wcscpy( child_dev->compatible_id, L"IBA\\qlgcvnic" );\r
+                               child_dev->compatible_id_size = ( wcslen( child_dev->compatible_id ) + 2 )*sizeof( WCHAR );\r
+                               swprintf( szDevName, L"%S", device_name );\r
+                               wcscpy( child_dev->description, szDevName );\r
+                               child_dev->description_size = ( wcslen( child_dev->description ) + 1 )*sizeof( WCHAR );\r
+                               child_dev->uniqueinstanceid = instance_id;\r
+\r
+                               dwRet = send_device_ioctl( UAL_IOC_DEVICE_CREATE, child_dev, sizeof( *child_dev ), NULL, NULL );\r
+\r
+                               if ( !dwRet ) \r
+                               {\r
+                                       printf( "Child device creation for CA = %I64X and IOC = %I64X was successful\n", \r
+                                               cl_ntoh64( ca_guid ), cl_ntoh64( ioc_guid ) );\r
+                                       dwRet = write_deviceinfo_to_registry( ca_guid, ioc_guid, instance_id, device_name );\r
+                               }\r
+                       }\r
+               } \r
+               else \r
+               {\r
+                       dwRet = -1;\r
+                       printf( "No path CA=%I64X to IOC=%I64X found\n",\r
+                               cl_ntoh64( ca_guid ), cl_ntoh64( ioc_guid ) );\r
+               }\r
+       }\r
+\r
+       if ( dwRet ) \r
+       {\r
+               printf( "Child device creation for CA = %I64X and IOC = %I64X failed\n", \r
+                       cl_ntoh64( ca_guid ), cl_ntoh64( ioc_guid ) );\r
+       }\r
+\r
+\r
+       if ( pList ) \r
+       {\r
+               cl_free( pList );\r
+       }\r
+\r
+       return dwRet;\r
+}\r
+\r
+DWORD  list_ca_ioc_paths()\r
+{\r
+       DWORD           dwBytesRet = 0, dwRet, n_ca_ioc_path = 0;\r
+       ca_ioc_info_t   *pList = NULL;\r
+       PVOID           pBuf = NULL;\r
+\r
+       dwRet = send_device_ioctl( UAL_IOC_LIST, NULL, 0, &pList, &dwBytesRet );\r
+\r
+       if ( dwRet ) \r
+       {\r
+               printf( "Obtaining IOC list from ibiou failed\n" );\r
+       } \r
+       else if ( dwBytesRet )\r
+               {\r
+               pBuf = pList;\r
+               n_ca_ioc_path = dwBytesRet/sizeof( ca_ioc_info_t );\r
+\r
+               while ( n_ca_ioc_path ) \r
+               {\r
+                       printf( "Channel Adapter %I64X reaches to IOC %I64X\n", \r
+                               cl_ntoh64( pList->ca_guid ), cl_ntoh64( pList->info.profile.ioc_guid ) );\r
+                       pList++; n_ca_ioc_path--;\r
+               }\r
+       }\r
+       else \r
+       {\r
+               printf( "No IOCs are reachable from the host\nPlease check the connections of host\n" );\r
+       }\r
+\r
+       if ( pBuf ) \r
+       {\r
+               cl_free( pBuf );\r
+       }\r
+\r
+       return dwRet;\r
+}\r
+\r
+int _cdecl main ( int argc, char *argv[] )\r
+{\r
+       char            device_name[200];\r
+       int             i = 1;\r
+       BOOLEAN         b_list_ioc_paths = FALSE;\r
+       BOOLEAN         b_create_device = FALSE;\r
+       uint64_t        ca_guid, ioc_guid;\r
+       uint32_t        unique_id;\r
+       DWORD           ret = 0;\r
+\r
+       while ( i < argc  ) \r
+       {\r
+               if ( !strcmp( argv[i], "-l" ) ) \r
+               {\r
+                       b_list_ioc_paths = TRUE;\r
+               } \r
+               else if ( !strcmp( argv[i], "-c" ) ) \r
+               {\r
+                       b_create_device = TRUE;\r
+\r
+                       if ( argv[++i] ) \r
+                       {\r
+                               ca_guid = _strtoui64( argv[i], NULL, 16 );\r
+                       } \r
+                       else \r
+                       {\r
+                               return usage();\r
+                       }\r
+                       if ( argv[++i] ) \r
+                       {\r
+                               ioc_guid = _strtoui64( argv[i],  NULL, 16 );                            \r
+                       } \r
+                       else \r
+                       {\r
+                               return usage();\r
+                       }\r
+                       if ( argv[++i] ) \r
+                       {\r
+                               unique_id = strtoul( argv[i], NULL, 10 );\r
+                       }\r
+                       else \r
+                       {\r
+                               return usage();\r
+                       }\r
+                       if ( argv[++i] ) \r
+                       {\r
+                               strcpy( device_name, argv[i] );\r
+                       } \r
+                       else \r
+                       {\r
+                               return usage();\r
+                       }\r
+\r
+               } \r
+               else \r
+               {\r
+                       return usage();\r
+               }\r
+               i++;\r
+       }\r
+\r
+       if ( b_list_ioc_paths && b_create_device ) \r
+       {\r
+               return usage();\r
+       }\r
+\r
+       else if ( b_create_device ) \r
+       {\r
+               ret = create_child_device( cl_hton64( ca_guid ), cl_hton64( ioc_guid ), unique_id, device_name );\r
+       } \r
+       else \r
+       {\r
+               ret = list_ca_ioc_paths();\r
+       }\r
+\r
+       return 0;\r
+}\r