From: ftillier Date: Tue, 6 Dec 2005 21:41:40 +0000 (+0000) Subject: [IPoIB] Add support for address translation X-Git-Url: https://openfabrics.org/gitweb/?a=commitdiff_plain;h=0d46f34be44813142966119424f58b6f6df5e3c2;p=~shefty%2Frdma-win.git [IPoIB] Add support for address translation Based on patch submitted by Tzachi Dar (tzachid@mellanox.co.il) git-svn-id: svn://openib.tc.cornell.edu/gen1@195 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86 --- diff --git a/trunk/inc/iba/ib_at_ioctl.h b/trunk/inc/iba/ib_at_ioctl.h new file mode 100644 index 00000000..47e2f13f --- /dev/null +++ b/trunk/inc/iba/ib_at_ioctl.h @@ -0,0 +1,133 @@ +/* +* Copyright (c) 2005 Mellanox Technologies. All rights reserved. +* Copyright (c) 2005 SilverStorm Technologies. All rights reserved. +* +* This software is available to you under 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$ +*/ + +/* This file is shared between user- and kernel-mode */ + +#include + + +#ifndef _IB_AT_IOCTL_H_ +#define _IB_AT_IOCTL_H_ + + +#define IBAT_IOCTL_VERSION 2 + +#define IBAT_MAC_LEN 6 + + +#define IOCTL_IBAT( n ) \ + CTL_CODE( FILE_DEVICE_UNKNOWN, (0x800 + n), \ + METHOD_BUFFERED, FILE_READ_ACCESS ) + +/** This IRP is used to return all available CAs ports number + * and port guid */ +#define IOCTL_IBAT_PORTS IOCTL_IBAT( 1 ) + +typedef struct _IBAT_PORT_RECORD +{ + UINT64 CaGuid; + UINT64 PortGuid; +} IBAT_PORT_RECORD; + +typedef struct _IOCTL_IBAT_PORTS_IN +{ + ULONG Version; + +} IOCTL_IBAT_PORTS_IN; + +typedef struct _IOCTL_IBAT_PORTS_OUT +{ + /** Total size, of the output buffer needed if the + * suplied buffer wasn't enough */ + ULONG Size; + LONG NumPorts; + IBAT_PORT_RECORD Ports[1]; + +} IOCTL_IBAT_PORTS_OUT; + + +/** This IRP is used to return all the ip addresses that + * are assigned to a port */ +#define IOCTL_IBAT_IP_ADDRESSES IOCTL_IBAT( 2 ) + +typedef struct _IOCTL_IBAT_IP_ADDRESSES_IN +{ + ULONG Version; + /** The guid of the port that we are querying for. May be + * zero if querying for IP addresses of all ports. */ + UINT64 PortGuid; + +} IOCTL_IBAT_IP_ADDRESSES_IN; + +typedef struct _IP_ADDRESS +{ + /** Might only be 4 or 6 */ + CHAR IpVersion; + /** Sized to support both IPv4 and IPv6 */ + UCHAR Address[16]; + +} IP_ADDRESS; + +typedef struct _IOCTL_IBAT_IP_ADDRESSES_OUT +{ + /** Total size of the output buffer needed if the + * suplied buffer wasn't enough */ + ULONG Size; + LONG AddressCount; + IP_ADDRESS Address[1]; + +} IOCTL_IBAT_IP_ADDRESSES_OUT; + + +/** This IRP is used to convert a remote MAC addresses to a remote GID */ +#define IOCTL_IBAT_MAC_TO_GID IOCTL_IBAT( 3 ) + +typedef struct _IOCTL_IBAT_MAC_TO_GID_IN +{ + ULONG Version; + UINT64 PortGuid; + UCHAR DestMac[IBAT_MAC_LEN]; + +} IOCTL_IBAT_MAC_TO_GID_IN; + +typedef struct _IOCTL_IBAT_MAC_TO_GID_OUT +{ + ib_gid_t DestGid; + +} IOCTL_IBAT_MAC_TO_GID_OUT; + + +#define IBAT_DEV_NAME L"\\Device\\ibat" +#define IBAT_DOS_DEV_NAME L"\\DosDevices\\Global\\ibat" +#define IBAT_WIN32_NAME L"\\\\.\\ibat" + +#endif /* _IB_AT_IOCTL_H_ */ diff --git a/trunk/tests/dirs b/trunk/tests/dirs index a9d217f8..fc792b6c 100644 --- a/trunk/tests/dirs +++ b/trunk/tests/dirs @@ -2,4 +2,5 @@ DIRS=\ alts \ cmtest \ wsd \ + ibat \ limits diff --git a/trunk/tests/ibat/dirs b/trunk/tests/ibat/dirs new file mode 100644 index 00000000..389156fd --- /dev/null +++ b/trunk/tests/ibat/dirs @@ -0,0 +1,2 @@ +DIRS=\ + user diff --git a/trunk/tests/ibat/user/PrintIp.c b/trunk/tests/ibat/user/PrintIp.c new file mode 100644 index 00000000..8fc1c443 --- /dev/null +++ b/trunk/tests/ibat/user/PrintIp.c @@ -0,0 +1,253 @@ +/* +* Copyright (c) 2005 Mellanox Technologies. All rights reserved. +* Copyright (c) 2005 SilverStorm Technologies. All rights reserved. +* +* This software is available to you under 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$ +*/ + + +#include +#include +#include +#include +#include "iba\ib_types.h" +#include + + +// Print all ips that are related to infiniband on this computer +int print_ips() +{ + HANDLE hKernelLib; + HRESULT hr = S_OK; + char temp [1000]; + char temp1 [1000]; + IOCTL_IBAT_PORTS_IN ipoib_ports_in; + IOCTL_IBAT_PORTS_OUT *p_ipoib_ports_out; + IBAT_PORT_RECORD *ports_records; + + IOCTL_IBAT_IP_ADDRESSES_IN addresses_in; + IOCTL_IBAT_IP_ADDRESSES_OUT *addresses_out; + IP_ADDRESS *ip_addreses; + + BOOL ret; + int i,j; + DWORD BytesReturned = 0; + + printf("Adapters that are known to the ipoib modules are:\n\n"); + + hKernelLib = + CreateFileW( + IBAT_WIN32_NAME, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, // share mode none + NULL, // no security + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL // no template + ); + + if (hKernelLib == INVALID_HANDLE_VALUE) { + hr = HRESULT_FROM_WIN32(GetLastError()); + printf("failed to open the kernel device hr=0x%x\n", hr); + return 1; + } + + ipoib_ports_in.Version = IBAT_IOCTL_VERSION; + + p_ipoib_ports_out = (IOCTL_IBAT_PORTS_OUT *)temp; + + ret = DeviceIoControl( + hKernelLib, + IOCTL_IBAT_PORTS, + &ipoib_ports_in, + sizeof(ipoib_ports_in), + p_ipoib_ports_out, + sizeof(temp), + &BytesReturned, + NULL + ); + + if (ret == 0) { + hr = HRESULT_FROM_WIN32(GetLastError()); + printf("DeviceIoControl failed for IOCTL_IBAT_PORTS hr=0x%x\n", hr); + return 1; + } + if (p_ipoib_ports_out->Size > sizeof(temp)) { + printf("Data truncated, please call again with a buffer of %d bytes", p_ipoib_ports_out->Size); + } + + ports_records = p_ipoib_ports_out->Ports; + printf("Number of devices %d\n", p_ipoib_ports_out->NumPorts); + for (i = 0 ; i < p_ipoib_ports_out->NumPorts; i++) + { + printf("%d: ca guid = 0x%I64x port guid=0x%I64x\n", i, CL_NTOH64(ports_records[i].CaGuid), CL_NTOH64(ports_records[i].PortGuid)); + + // print the ip adresses of this port + addresses_in.Version = IBAT_IOCTL_VERSION; + addresses_in.PortGuid = ports_records[i].PortGuid; + + addresses_out = (IOCTL_IBAT_IP_ADDRESSES_OUT *)temp1; + + ret = DeviceIoControl( + hKernelLib, + IOCTL_IBAT_IP_ADDRESSES, + &addresses_in, + sizeof(addresses_in), + addresses_out, + sizeof(temp1), + &BytesReturned, + NULL + ); + + if (ret == 0) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + printf("DeviceIoControl failed for IOCTL_IBAT_IP_ADDRESSES hr=0x%x\n", hr); + return 1; + } + if (addresses_out->Size > sizeof(temp1) ) + { + printf("Data truncated, please call again with a buffer of %d bytes", p_ipoib_ports_out->Size); + return 1; + } + + printf(" found %d ips:", addresses_out->AddressCount); + ip_addreses = addresses_out->Address; + for (j = 0; j < addresses_out->AddressCount; j++) + { + printf(" %d.%d.%d.%d ", + ip_addreses[j].Address[12], + ip_addreses[j].Address[13], + ip_addreses[j].Address[14], + ip_addreses[j].Address[15]); + } + printf("\n"); + } + + return 0; +}; + +void print_usage(char *argv[]) +{ + printf("This program is used to print ip adapters and their addresses or to do arp\n"); + printf("Usage is: %s \n",argv[0]); + printf("or %s (for example %s remoteip 1.2.3.4)\n", argv[0],argv[0]); +} + +int remote_ip(char *remote_ip) +{ + HANDLE hKernelLib; + HRESULT hr = S_OK; + IPAddr ip; + char *pIp = (char *)&ip; + int b1,b2,b3,b4; + DWORD ret; + IOCTL_IBAT_MAC_TO_GID_IN mac; + IOCTL_IBAT_MAC_TO_GID_OUT gid; + DWORD BytesReturned = 0; + + ULONG pMacAddr[2], PhyAddrLen ; + unsigned char *pMac = (unsigned char *)&pMacAddr; + PhyAddrLen = sizeof(pMacAddr); + + hKernelLib = + CreateFileW( + IBAT_WIN32_NAME, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, // share mode none + NULL, // no security + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL // no template + ); + + if (hKernelLib == INVALID_HANDLE_VALUE) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + printf("failed to open the kernel device hr=0x%x\n", hr); + return 1; + } + + sscanf(remote_ip, "%d.%d.%d.%d", &b1, &b2, &b3, &b4); + printf("Calling arp for addresses %d.%d.%d.%d\n", b1, b2, b3, b4); + + pIp[0] = (char)b1; + pIp[1] = (char)b2; + pIp[2] = (char)b3; + pIp[3] = (char)b4; + + ret = SendARP(ip ,0 ,pMacAddr, &PhyAddrLen ); + if (ret != NO_ERROR) + { + printf("Error in SendARP"); + return 1; + } + + printf("Mac of the remote addresses is %x-%x-%x-%x-%x-%x\n", + pMac[0], pMac[1], pMac[2], pMac[3], pMac[4], pMac[5] ); + + // query for the gid + memcpy(mac.DestMac, pMac, 6); + + ret = DeviceIoControl( + hKernelLib, + IOCTL_IBAT_MAC_TO_GID, + &mac, + sizeof(mac), + &gid, + sizeof(gid), + &BytesReturned, + NULL ); + + if (ret == 0) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + printf("DeviceIoControl failed for IOCTL_IBAT_IP_ADDRESSES hr=0x%x\n", hr); + } + + printf("lid of remote ip is = 0x%I64x : 0x%I64x\n", CL_NTOH64(gid.DestGid.unicast.prefix), CL_NTOH64(gid.DestGid.unicast.interface_id)); + + return 0; +} + + +int __cdecl main(int argc, char *argv[]) +{ + if (argc < 2) { + print_usage(argv); + return 1; + } + if (!strcmp(argv[1], "print_ips")) { + return print_ips(); + } + if (!strcmp(argv[1], "remoteip")) { + return remote_ip(argv[2]); + } + print_usage(argv); + return 1; +} diff --git a/trunk/tests/ibat/user/SOURCES b/trunk/tests/ibat/user/SOURCES new file mode 100644 index 00000000..b50428b7 --- /dev/null +++ b/trunk/tests/ibat/user/SOURCES @@ -0,0 +1,18 @@ +TARGETNAME=PrintIP +TARGETPATH=..\..\..\bin\user\obj$(BUILD_ALT_DIR) +TARGETTYPE=PROGRAM +UMTYPE=console +USE_CRTDLL=1 + +SOURCES=\ + PrintIp.c + +TARGETLIBS=\ + $(SDK_LIB_PATH)\ws2_32.lib \ + $(SDK_LIB_PATH)\Iphlpapi.lib + +MSC_WARNING_LEVEL= /W4 + +INCLUDES=..\..\..\inc;\ + ..\..\..\inc\user;\ + $(PLATFORM_SDK_PATH)\include; diff --git a/trunk/tests/ibat/user/makefile b/trunk/tests/ibat/user/makefile new file mode 100644 index 00000000..9c985f57 --- /dev/null +++ b/trunk/tests/ibat/user/makefile @@ -0,0 +1,7 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the driver components of the Windows NT DDK +# + +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/trunk/ulp/ipoib/kernel/SOURCES b/trunk/ulp/ipoib/kernel/SOURCES index a7f370da..dda21429 100644 --- a/trunk/ulp/ipoib/kernel/SOURCES +++ b/trunk/ulp/ipoib/kernel/SOURCES @@ -6,7 +6,8 @@ SOURCES= ipoib.rc \ ipoib_driver.c \ ipoib_adapter.c \ ipoib_endpoint.c \ - ipoib_port.c + ipoib_port.c \ + ipoib_ibat.c INCLUDES=..;..\..\..\inc;..\..\..\inc\kernel; diff --git a/trunk/ulp/ipoib/kernel/ipoib_adapter.c b/trunk/ulp/ipoib/kernel/ipoib_adapter.c index b1837474..f7c811c6 100644 --- a/trunk/ulp/ipoib/kernel/ipoib_adapter.c +++ b/trunk/ulp/ipoib/kernel/ipoib_adapter.c @@ -190,7 +190,7 @@ ipoib_create_adapter( } KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); - InsertHeadList( &g_ipoib.adapter_list, &p_adapter->entry ); + cl_qlist_insert_tail( &g_ipoib.adapter_list, &p_adapter->entry ); KeReleaseInStackQueuedSpinLock( &hdl ); status = adapter_init( p_adapter ); @@ -243,7 +243,6 @@ ipoib_destroy_adapter( cl_mutex_acquire( &p_adapter->mutex ); cl_obj_lock( &p_adapter->obj ); p_adapter->state = IB_PNP_PORT_REMOVE; - cl_obj_unlock( &p_adapter->obj ); /* * Clear the pointer to the port object since the object destruction @@ -252,6 +251,8 @@ ipoib_destroy_adapter( */ p_adapter->p_port = NULL; + cl_obj_unlock( &p_adapter->obj ); + cl_mutex_release( &p_adapter->mutex ); cl_obj_destroy( &p_adapter->obj ); @@ -429,8 +430,8 @@ __adapter_destroying( } KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); - ASSERT( !IsListEmpty( &g_ipoib.adapter_list ) ); - RemoveEntryList( &p_adapter->entry ); + ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) ); + cl_qlist_remove_item( &g_ipoib.adapter_list, &p_adapter->entry ); KeReleaseInStackQueuedSpinLock( &hdl ); IPOIB_EXIT( IPOIB_DBG_INIT ); @@ -476,6 +477,7 @@ __ipoib_pnp_cb( { ib_api_status_t status; ipoib_adapter_t *p_adapter; + ipoib_port_t *p_port; ib_pnp_event_t old_state; IPOIB_ENTER( IPOIB_DBG_PNP ); @@ -527,17 +529,20 @@ __ipoib_pnp_cb( p_adapter->state = IB_PNP_PORT_ADD; cl_obj_unlock( &p_adapter->obj ); status = ipoib_create_port( p_adapter, - (ib_pnp_port_rec_t*)p_pnp_rec, &p_adapter->p_port ); + (ib_pnp_port_rec_t*)p_pnp_rec, &p_port ); + cl_obj_lock( &p_adapter->obj ); if( status != IB_SUCCESS ) { - cl_obj_lock( &p_adapter->obj ); p_adapter->state = old_state; cl_obj_unlock( &p_adapter->obj ); p_adapter->hung = TRUE; break; } - p_pnp_rec->context = p_adapter->p_port; + p_pnp_rec->context = p_port; + + p_adapter->p_port = p_port; + cl_obj_unlock( &p_adapter->obj ); break; case IB_PNP_PORT_REMOVE: @@ -546,9 +551,10 @@ __ipoib_pnp_cb( cl_obj_lock( &p_adapter->obj ); p_adapter->state = IB_PNP_PORT_REMOVE; - cl_obj_unlock( &p_adapter->obj ); - ipoib_port_destroy( p_adapter->p_port ); + p_port = p_adapter->p_port; p_adapter->p_port = NULL; + cl_obj_unlock( &p_adapter->obj ); + ipoib_port_destroy( p_port ); p_pnp_rec->context = NULL; status = IB_SUCCESS; break; @@ -732,6 +738,7 @@ __ipoib_pnp_dereg( IN void* context ) { ipoib_adapter_t* p_adapter; + ipoib_port_t* p_port; ib_api_status_t status; ib_pnp_event_t state; @@ -751,14 +758,14 @@ __ipoib_pnp_dereg( state = p_adapter->state; + /* Destroy the current port instance if it still exists. */ + p_port = p_adapter->p_port; + p_adapter->p_port = NULL; cl_obj_unlock( &p_adapter->obj ); - /* Destroy the current port instance if it still exists. */ - if( p_adapter->p_port ) - { - ipoib_port_destroy( p_adapter->p_port ); - p_adapter->p_port = NULL; - } + if( p_port ) + ipoib_port_destroy( p_port ); + /* Complete any pending OIDs. */ ipoib_resume_oids( p_adapter ); diff --git a/trunk/ulp/ipoib/kernel/ipoib_adapter.h b/trunk/ulp/ipoib/kernel/ipoib_adapter.h index ba67e240..dbd891cd 100644 --- a/trunk/ulp/ipoib/kernel/ipoib_adapter.h +++ b/trunk/ulp/ipoib/kernel/ipoib_adapter.h @@ -130,7 +130,7 @@ typedef struct _ipoib_adapter NDIS_HANDLE h_adapter; ipoib_ifc_data_t guids; - LIST_ENTRY entry; + cl_list_item_t entry; ib_al_handle_t h_al; ib_pnp_handle_t h_pnp; diff --git a/trunk/ulp/ipoib/kernel/ipoib_debug.h b/trunk/ulp/ipoib/kernel/ipoib_debug.h index a96cd69e..7b58334d 100644 --- a/trunk/ulp/ipoib/kernel/ipoib_debug.h +++ b/trunk/ulp/ipoib/kernel/ipoib_debug.h @@ -59,6 +59,7 @@ extern uint32_t g_ipoib_dbg_lvl; #define IPOIB_DBG_MCAST (1 << 7) #define IPOIB_DBG_ALLOC (1 << 8) #define IPOIB_DBG_OID (1 << 9) +#define IPOIB_DBG_IOCTL (1 << 10) #define IPOIB_DBG_FUNC (1 << 28) /* For function entry/exit */ #define IPOIB_DBG_INFO (1 << 29) /* For verbose information */ diff --git a/trunk/ulp/ipoib/kernel/ipoib_driver.c b/trunk/ulp/ipoib/kernel/ipoib_driver.c index c1451f87..7322a3bf 100644 --- a/trunk/ulp/ipoib/kernel/ipoib_driver.c +++ b/trunk/ulp/ipoib/kernel/ipoib_driver.c @@ -33,6 +33,7 @@ #include "ipoib_driver.h" #include "ipoib_debug.h" #include "ipoib_port.h" +#include "ipoib_ibat.h" #include #include #include @@ -266,9 +267,10 @@ DriverEntry( __ipoib_read_registry(p_registry_path); KeInitializeSpinLock( &g_ipoib.lock ); - InitializeListHead( &g_ipoib.adapter_list ); + cl_qlist_init( &g_ipoib.adapter_list ); - NdisMInitializeWrapper( &ndis_handle, p_drv_obj, p_registry_path, NULL ); + NdisMInitializeWrapper( + &g_ipoib.h_ndis_wrapper, p_drv_obj, p_registry_path, NULL ); memset(&characteristics, 0, sizeof(characteristics)); characteristics.MajorNdisVersion = MAJOR_NDIS_VERSION; @@ -289,18 +291,17 @@ DriverEntry( #endif status = NdisMRegisterMiniport( - ndis_handle, &characteristics, sizeof(characteristics) ); + g_ipoib.h_ndis_wrapper, &characteristics, sizeof(characteristics) ); if( status != NDIS_STATUS_SUCCESS ) { IPOIB_TRACE( IPOIB_DBG_ERROR, ("NdisMRegisterMiniport failed with status of %d\n", status) ); - NdisTerminateWrapper( ndis_handle, NULL ); + NdisTerminateWrapper( g_ipoib.h_ndis_wrapper, NULL ); CL_DEINIT; + return status; } - else - { - NdisMRegisterUnloadHandler( ndis_handle, ipoib_unload ); - } + + NdisMRegisterUnloadHandler( g_ipoib.h_ndis_wrapper, ipoib_unload ); IPOIB_EXIT( IPOIB_DBG_INIT ); return status; @@ -643,6 +644,8 @@ ipoib_initialize( return NDIS_STATUS_FAILURE; } + ipoib_ref_ibat(); + IPOIB_EXIT( IPOIB_DBG_INIT ); return status; } @@ -661,6 +664,8 @@ ipoib_halt( IPOIB_ENTER( IPOIB_DBG_INIT ); + ipoib_deref_ibat(); + CL_ASSERT( adapter_context ); p_adapter = (ipoib_adapter_t*)adapter_context; @@ -2244,7 +2249,7 @@ __ipoib_dereg_addrs( for( idx = 0; idx < cl_vector_get_size( &p_adapter->ip_vector); idx++ ) { p_addr_item = (net_address_item_t*) - cl_vector_get_ptr( &p_adapter->ip_vector, idx ); + cl_vector_get_ptr( &p_adapter->ip_vector, idx ); if( !p_addr_item->p_reg ) continue; diff --git a/trunk/ulp/ipoib/kernel/ipoib_driver.h b/trunk/ulp/ipoib/kernel/ipoib_driver.h index 94bea711..0d42d597 100644 --- a/trunk/ulp/ipoib/kernel/ipoib_driver.h +++ b/trunk/ulp/ipoib/kernel/ipoib_driver.h @@ -64,11 +64,15 @@ typedef struct _ipoib_globals { KSPIN_LOCK lock; - LIST_ENTRY adapter_list; + cl_qlist_t adapter_list; cl_qlist_t bundle_list; atomic32_t laa_idx; + NDIS_HANDLE h_ndis_wrapper; + NDIS_HANDLE h_ibat_dev; + volatile LONG ibat_ref; + } ipoib_globals_t; /* * FIELDS @@ -83,6 +87,9 @@ typedef struct _ipoib_globals * * laa_idx * Global counter for generating LAA MACs +* +* h_ibat_dev +* Device handle returned by NdisMRegisterDevice. *********/ extern ipoib_globals_t g_ipoib; diff --git a/trunk/ulp/ipoib/kernel/ipoib_ibat.c b/trunk/ulp/ipoib/kernel/ipoib_ibat.c new file mode 100644 index 00000000..0b47206a --- /dev/null +++ b/trunk/ulp/ipoib/kernel/ipoib_ibat.c @@ -0,0 +1,472 @@ +/* + * Copyright (c) 2005 Mellanox Technologies. All rights reserved. + * Copyright (c) 2005 SilverStorm Technologies. All rights reserved. + * + * This software is available to you under 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$ + */ + + +#include "ipoib_driver.h" +#include "ipoib_adapter.h" +#include "ipoib_port.h" +#include "ipoib_debug.h" +#include + + +static NTSTATUS +__ipoib_create( + IN DEVICE_OBJECT* const pDevObj, + IN IRP* const pIrp ); + +static NTSTATUS +__ipoib_cleanup( + IN DEVICE_OBJECT* const pDevObj, + IN IRP* const pIrp ); + +static NTSTATUS +__ipoib_close( + IN DEVICE_OBJECT* const pDevObj, + IN IRP* const pIrp ); + +static NTSTATUS +__ipoib_dispatch( + IN DEVICE_OBJECT* const pDevObj, + IN IRP* const pIrp ); + + +static NTSTATUS +__ibat_get_ports( + IN IRP *pIrp, + IN IO_STACK_LOCATION *pIoStack ) +{ + IOCTL_IBAT_PORTS_IN *pIn; + IOCTL_IBAT_PORTS_OUT *pOut; + KLOCK_QUEUE_HANDLE hdl; + cl_list_item_t *pItem; + ipoib_adapter_t *pAdapter; + LONG nPorts; + + IPOIB_ENTER(IPOIB_DBG_IOCTL); + + if( pIoStack->Parameters.DeviceIoControl.InputBufferLength != + sizeof(IOCTL_IBAT_PORTS_IN) ) + { + IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR, ("Invalid input buffer size.\n") ); + return STATUS_INVALID_PARAMETER; + } + + if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength < + sizeof(IOCTL_IBAT_PORTS_OUT) ) + { + IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR, ("Invalid output buffer size.\n") ); + return STATUS_INVALID_PARAMETER; + } + + pIn = pIrp->AssociatedIrp.SystemBuffer; + pOut = pIrp->AssociatedIrp.SystemBuffer; + + if( pIn->Version != IBAT_IOCTL_VERSION ) + { + IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR, ("Invalid version.\n") ); + return STATUS_INVALID_PARAMETER; + } + + KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); + nPorts = (LONG)cl_qlist_count( &g_ipoib.adapter_list ); + switch( nPorts ) + { + case 0: + cl_memclr( pOut->Ports, sizeof(pOut->Ports) ); + /* Fall through */ + case 1: + pOut->Size = sizeof(IOCTL_IBAT_PORTS_OUT); + break; + + default: + pOut->Size = sizeof(IOCTL_IBAT_PORTS_OUT) + + (sizeof(IBAT_PORT_RECORD) * (nPorts - 1)); + break; + } + + pIrp->IoStatus.Information = pOut->Size; + + if( pOut->Size > pIoStack->Parameters.DeviceIoControl.OutputBufferLength ) + { + nPorts = 1 + + (pIoStack->Parameters.DeviceIoControl.OutputBufferLength - + sizeof(IOCTL_IBAT_PORTS_OUT)) / sizeof(IBAT_PORT_RECORD); + + pIrp->IoStatus.Information = sizeof(IOCTL_IBAT_PORTS_OUT) + + ((nPorts - 1) * sizeof(IBAT_PORT_RECORD)); + } + + pOut->NumPorts = 0; + pItem = cl_qlist_head( &g_ipoib.adapter_list ); + while( pOut->NumPorts != nPorts ) + { + pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry ); + pOut->Ports[pOut->NumPorts].CaGuid = pAdapter->guids.ca_guid; + pOut->Ports[pOut->NumPorts].PortGuid = pAdapter->guids.port_guid; + pOut->NumPorts++; + + pItem = cl_qlist_next( pItem ); + } + + KeReleaseInStackQueuedSpinLock( &hdl ); + return STATUS_SUCCESS; +} + + +static NTSTATUS +__ibat_get_ips( + IN IRP *pIrp, + IN IO_STACK_LOCATION *pIoStack ) +{ + IOCTL_IBAT_IP_ADDRESSES_IN *pIn; + IOCTL_IBAT_IP_ADDRESSES_OUT *pOut; + KLOCK_QUEUE_HANDLE hdl; + cl_list_item_t *pItem; + ipoib_adapter_t *pAdapter; + LONG nIps, maxIps; + size_t idx; + net_address_item_t *pAddr; + UINT64 PortGuid; + + IPOIB_ENTER(IPOIB_DBG_IOCTL); + + if( pIoStack->Parameters.DeviceIoControl.InputBufferLength != + sizeof(IOCTL_IBAT_IP_ADDRESSES_IN) ) + { + IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR, ("Invalid input buffer size.\n") ); + return STATUS_INVALID_PARAMETER; + } + + if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength < + sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT) ) + { + IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR, ("Invalid output buffer size.\n") ); + return STATUS_INVALID_PARAMETER; + } + + pIn = pIrp->AssociatedIrp.SystemBuffer; + pOut = pIrp->AssociatedIrp.SystemBuffer; + + if( pIn->Version != IBAT_IOCTL_VERSION ) + { + IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR, ("Invalid version.\n") ); + return STATUS_INVALID_PARAMETER; + } + + PortGuid = pIn->PortGuid; + + nIps = 0; + pOut->AddressCount = 0; + maxIps = 1 + + ((pIoStack->Parameters.DeviceIoControl.OutputBufferLength - + sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT)) / sizeof(IP_ADDRESS)); + + KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); + for( pItem = cl_qlist_head( &g_ipoib.adapter_list ); + pItem != cl_qlist_end( &g_ipoib.adapter_list ); + pItem = cl_qlist_next( pItem ) ) + { + pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry ); + if( PortGuid && pAdapter->guids.port_guid != PortGuid ) + continue; + + cl_obj_lock( &pAdapter->obj ); + nIps += (LONG)cl_vector_get_size( &pAdapter->ip_vector ); + + for( idx = 0; + idx < cl_vector_get_size( &pAdapter->ip_vector ); + idx++ ) + { + if( pOut->AddressCount == maxIps ) + break; + + pAddr = (net_address_item_t*) + cl_vector_get_ptr( &pAdapter->ip_vector, idx ); + + pOut->Address[pOut->AddressCount].IpVersion = 4; + cl_memclr( &pOut->Address[pOut->AddressCount].Address, + sizeof(IP_ADDRESS) ); + cl_memcpy( &pOut->Address[pOut->AddressCount].Address[12], + pAddr->address.as_bytes, IPV4_ADDR_SIZE ); + + pOut->AddressCount++; + } + cl_obj_unlock( &pAdapter->obj ); + } + + pOut->Size = sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT); + if( --nIps ) + pOut->Size += sizeof(IP_ADDRESS) * nIps; + + pIrp->IoStatus.Information = sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT); + if( --maxIps < nIps ) + pIrp->IoStatus.Information += (sizeof(IP_ADDRESS) * maxIps); + else + pIrp->IoStatus.Information += (sizeof(IP_ADDRESS) * nIps); + + KeReleaseInStackQueuedSpinLock( &hdl ); + return STATUS_SUCCESS; +} + + +static NTSTATUS +__ibat_mac_to_gid( + IN IRP *pIrp, + IN IO_STACK_LOCATION *pIoStack ) +{ + NTSTATUS status = STATUS_INVALID_PARAMETER; + IOCTL_IBAT_MAC_TO_GID_IN *pIn; + IOCTL_IBAT_MAC_TO_GID_OUT *pOut; + KLOCK_QUEUE_HANDLE hdl; + cl_list_item_t *pItem; + ipoib_adapter_t *pAdapter; + + IPOIB_ENTER(IPOIB_DBG_IOCTL); + + if( pIoStack->Parameters.DeviceIoControl.InputBufferLength != + sizeof(IOCTL_IBAT_PORTS_IN) ) + { + IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR, ("Invalid input buffer size.\n") ); + return STATUS_INVALID_PARAMETER; + } + + if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength != + sizeof(IOCTL_IBAT_PORTS_OUT) ) + { + IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR, ("Invalid output buffer size.\n") ); + return STATUS_INVALID_PARAMETER; + } + + pIn = pIrp->AssociatedIrp.SystemBuffer; + pOut = pIrp->AssociatedIrp.SystemBuffer; + + if( pIn->Version != IBAT_IOCTL_VERSION ) + { + IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR, ("Invalid version.\n") ); + return STATUS_INVALID_PARAMETER; + } + + KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); + + for( pItem = cl_qlist_head( &g_ipoib.adapter_list ); + pItem != cl_qlist_end( &g_ipoib.adapter_list ); + pItem = cl_qlist_next( pItem ) ) + { + pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry ); + if( pIn->PortGuid != pAdapter->guids.port_guid ) + continue; + + /* Found the port - lookup the MAC. */ + cl_obj_lock( &pAdapter->obj ); + if( pAdapter->p_port ) + { + status = ipoib_mac_to_gid( + pAdapter->p_port, *(mac_addr_t*)pIn->DestMac, &pOut->DestGid ); + if( NT_SUCCESS( status ) ) + { + pIrp->IoStatus.Information = + sizeof(IOCTL_IBAT_MAC_TO_GID_OUT); + } + } + cl_obj_unlock( &pAdapter->obj ); + break; + } + + KeReleaseInStackQueuedSpinLock( &hdl ); + + return status; +} + + +void +ipoib_ref_ibat() +{ + NDIS_STATUS status; + NDIS_STRING DeviceName; + NDIS_STRING DeviceLinkUnicodeString; + PDRIVER_DISPATCH DispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1]; + DEVICE_OBJECT *p_dev_obj; + + IPOIB_ENTER( IPOIB_DBG_IOCTL ); + + if( InterlockedIncrement( &g_ipoib.ibat_ref ) == 1 ) + { + NdisInitUnicodeString( &DeviceName, IBAT_DEV_NAME ); + NdisInitUnicodeString( &DeviceLinkUnicodeString, IBAT_DOS_DEV_NAME ); + + NdisZeroMemory( DispatchTable, sizeof(DispatchTable) ); + + DispatchTable[IRP_MJ_CREATE] = __ipoib_create; + DispatchTable[IRP_MJ_CLEANUP] = __ipoib_cleanup; + DispatchTable[IRP_MJ_CLOSE] = __ipoib_close; + DispatchTable[IRP_MJ_DEVICE_CONTROL] = __ipoib_dispatch; + DispatchTable[IRP_MJ_INTERNAL_DEVICE_CONTROL] = __ipoib_dispatch; + + status = NdisMRegisterDevice( g_ipoib.h_ndis_wrapper, + &DeviceName, &DeviceLinkUnicodeString, &DispatchTable[0], + &p_dev_obj, &g_ipoib.h_ibat_dev ); + if( status != NDIS_STATUS_SUCCESS ) + { + IPOIB_TRACE( IPOIB_DBG_ERROR, + ("NdisMRegisterDevice failed with status of %d\n", status) ); + } + } + + IPOIB_EXIT( IPOIB_DBG_IOCTL ); +} + + +void +ipoib_deref_ibat() +{ + IPOIB_ENTER( IPOIB_DBG_IOCTL ); + + if( InterlockedDecrement( &g_ipoib.ibat_ref ) ) + { + IPOIB_EXIT( IPOIB_DBG_IOCTL ); + return; + } + + if( g_ipoib.h_ibat_dev ) + { + NdisMDeregisterDevice( g_ipoib.h_ibat_dev ); + g_ipoib.h_ibat_dev = NULL; + } + + IPOIB_EXIT( IPOIB_DBG_IOCTL ); +} + + +static NTSTATUS +__ipoib_create( + IN DEVICE_OBJECT* const pDevObj, + IN IRP* const pIrp ) +{ + IPOIB_ENTER( IPOIB_DBG_IOCTL ); + + UNREFERENCED_PARAMETER( pDevObj ); + + ipoib_ref_ibat(); + + pIrp->IoStatus.Status = STATUS_SUCCESS; + pIrp->IoStatus.Information = 0; + IoCompleteRequest( pIrp, IO_NO_INCREMENT ); + + IPOIB_EXIT( IPOIB_DBG_IOCTL ); + return STATUS_SUCCESS; +} + + +static NTSTATUS +__ipoib_cleanup( + IN DEVICE_OBJECT* const pDevObj, + IN IRP* const pIrp ) +{ + IPOIB_ENTER( IPOIB_DBG_IOCTL ); + + UNREFERENCED_PARAMETER( pDevObj ); + + ipoib_deref_ibat(); + + pIrp->IoStatus.Status = STATUS_SUCCESS; + pIrp->IoStatus.Information = 0; + IoCompleteRequest( pIrp, IO_NO_INCREMENT ); + + IPOIB_EXIT( IPOIB_DBG_IOCTL ); + return STATUS_SUCCESS; +} + + +static NTSTATUS +__ipoib_close( + IN DEVICE_OBJECT* const pDevObj, + IN IRP* const pIrp ) +{ + IPOIB_ENTER( IPOIB_DBG_IOCTL ); + + UNREFERENCED_PARAMETER( pDevObj ); + + pIrp->IoStatus.Status = STATUS_SUCCESS; + pIrp->IoStatus.Information = 0; + IoCompleteRequest( pIrp, IO_NO_INCREMENT ); + + IPOIB_EXIT( IPOIB_DBG_IOCTL ); + return STATUS_SUCCESS; +} + + +static NTSTATUS +__ipoib_dispatch( + IN DEVICE_OBJECT* const pDevObj, + IN IRP* const pIrp ) +{ + IO_STACK_LOCATION *pIoStack; + NTSTATUS status = STATUS_SUCCESS; + + IPOIB_ENTER( IPOIB_DBG_IOCTL ); + + UNREFERENCED_PARAMETER( pDevObj ); + + pIoStack = IoGetCurrentIrpStackLocation( pIrp ); + + pIrp->IoStatus.Information = 0; + + switch( pIoStack->Parameters.DeviceIoControl.IoControlCode ) + { + case IOCTL_IBAT_PORTS: + IPOIB_TRACE( IPOIB_DBG_IOCTL, ("IOCTL_IBAT_PORTS recieved\n") ); + status = __ibat_get_ports( pIrp, pIoStack ); + break; + + case IOCTL_IBAT_IP_ADDRESSES: + IPOIB_TRACE( IPOIB_DBG_IOCTL, ("IOCTL_IBAT_IP_ADDRESSES recieved\n" )); + status = __ibat_get_ips( pIrp, pIoStack ); + break; + + case IOCTL_IBAT_MAC_TO_GID: + IPOIB_TRACE( IPOIB_DBG_IOCTL, ("IOCTL_IBAT_MAC_TO_GID recieved\n" )); + status = __ibat_mac_to_gid( pIrp, pIoStack ); + break; + + default: + IPOIB_TRACE( IPOIB_DBG_WARN, ("unknow IOCTL code = 0x%x\n", + pIoStack->Parameters.DeviceIoControl.IoControlCode) ); + status = STATUS_INVALID_PARAMETER; + } + + pIrp->IoStatus.Status = status; + IoCompleteRequest( pIrp, IO_NO_INCREMENT ); + + IPOIB_EXIT( IPOIB_DBG_IOCTL ); + return status; +} + diff --git a/trunk/ulp/ipoib/kernel/ipoib_ibat.h b/trunk/ulp/ipoib/kernel/ipoib_ibat.h new file mode 100644 index 00000000..83d01951 --- /dev/null +++ b/trunk/ulp/ipoib/kernel/ipoib_ibat.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2005 Mellanox Technologies. All rights reserved. + * Copyright (c) 2005 SilverStorm Technologies. All rights reserved. + * + * This software is available to you under 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$ + */ + + +#ifndef _IPOIB_IBAT_H_ +#define _IPOIB_IBAT_H_ + + +void +ipoib_ref_ibat(); + +void +ipoib_deref_ibat(); + + +#endif /* _IPOIB_IBAT_H_ */ diff --git a/trunk/ulp/ipoib/kernel/ipoib_port.c b/trunk/ulp/ipoib/kernel/ipoib_port.c index 9ab1a415..62abceac 100644 --- a/trunk/ulp/ipoib/kernel/ipoib_port.c +++ b/trunk/ulp/ipoib/kernel/ipoib_port.c @@ -521,7 +521,7 @@ ipoib_port_destroy( CL_ASSERT( p_port ); CL_ASSERT( p_port->p_adapter ); - CL_ASSERT( p_port->p_adapter->p_port == p_port ); + CL_ASSERT( !p_port->p_adapter->p_port ); cl_obj_destroy( &p_port->obj ); @@ -3897,6 +3897,40 @@ __endpt_mgr_remove( } +NTSTATUS +ipoib_mac_to_gid( + IN ipoib_port_t* const p_port, + IN const mac_addr_t mac, + OUT ib_gid_t* p_gid ) +{ + ipoib_endpt_t* p_endpt; + cl_map_item_t *p_item; + uint64_t key = 0; + + IPOIB_ENTER( IPOIB_DBG_ENDPT ); + + cl_memcpy( &key, &mac, sizeof(mac_addr_t) ); + + cl_obj_lock( &p_port->obj ); + + p_item = cl_qmap_get( &p_port->endpt_mgr.mac_endpts, key ); + if( p_item == cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) ) + { + cl_obj_unlock( &p_port->obj ); + IPOIB_TRACE_EXIT( IPOIB_DBG_ENDPT, ("Failed endpoint lookup.\n") ); + return STATUS_INVALID_PARAMETER; + } + + p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item ); + *p_gid = p_endpt->dgid; + + cl_obj_unlock( &p_port->obj ); + + IPOIB_EXIT( IPOIB_DBG_ENDPT ); + return STATUS_SUCCESS; +} + + static inline NDIS_STATUS __endpt_mgr_ref( IN ipoib_port_t* const p_port, diff --git a/trunk/ulp/ipoib/kernel/ipoib_port.h b/trunk/ulp/ipoib/kernel/ipoib_port.h index 7c122929..8d78ce69 100644 --- a/trunk/ulp/ipoib/kernel/ipoib_port.h +++ b/trunk/ulp/ipoib/kernel/ipoib_port.h @@ -584,5 +584,10 @@ void ipoib_port_resume( IN ipoib_port_t* const p_port ); +NTSTATUS +ipoib_mac_to_gid( + IN ipoib_port_t* const p_port, + IN const mac_addr_t mac, + OUT ib_gid_t* p_gid ); #endif /* _IPOIB_PORT_H_ */