[ofw] [PATCH 5/7] winverbs: add connection support to library

Sean Hefty sean.hefty at intel.com
Fri Jan 16 14:37:22 PST 2009


Update the winverbs interface and library to add support for connection
establishment.  The implementation supports XP, 2003, and 2008.  Because
kernel support for IP is lacking in XP and 2003, the winverbs userspace
library performs address and route resolution, rather than relying on the
kernel driver to perform those operations.

The interface for datagram support was updated to match that used for
connections, but datagram support is not implemented at this time.

Signed-off-by: Sean Hefty <sean.hefty at intel.com>
---
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/inc/user/rdma/winverbs.h branches\winverbs/inc/user/rdma/winverbs.h
--- trunk/inc/user/rdma/winverbs.h	2008-07-18 12:24:44.239383200 -0700
+++ branches\winverbs/inc/user/rdma/winverbs.h	2008-12-01 23:12:37.475375000 -0800
@@ -35,6 +35,7 @@
 #include <initguid.h>
 
 #include <winsock2.h>
+#include <ws2tcpip.h>
 #include <unknwn.h>
 #include <rdma\wvstatus.h>
 
@@ -156,21 +157,13 @@ typedef struct _WV_PORT_ATTRIBUTES
 
 }	WV_PORT_ATTRIBUTES;
 
-typedef struct _WV_ADDRESS
+typedef struct _WV_DEVICE_ADDRESS
 {
-	SOCKET_ADDRESS	Address;
-	NET64			DeviceGuid;
-	NET16			Pkey;
-	UINT8			PortNumber;
-
-}	WV_ADDRESS;
-
-typedef struct _WV_ADDRESS_LIST
-{
-	SIZE_T			Count;
-	WV_ADDRESS		Address[1];
+	NET64				DeviceGuid;
+	NET16				Pkey;
+	UINT8				PortNumber;
 
-}	WV_ADDRESS_LIST;
+}	WV_DEVICE_ADDRESS;
 
 // Port notification flags
 #define WV_EVENT_ERROR				0x00000001
@@ -476,8 +469,6 @@ typedef struct _WV_QP_ATTRIBUTES
 
 #define WV_CM_UDP_QKEY	0x01234567
 
-#pragma warning(push)
-#pragma warning(disable: 4200)
 typedef struct _WV_CONNECT_PARAM
 {
 	SIZE_T				DataLength;
@@ -486,7 +477,7 @@ typedef struct _WV_CONNECT_PARAM
 	UINT8				RetryCount;			// Ignored when accepting
 	UINT8				RnrRetryCount;
 	UINT8				Reserved[2];
-	UINT8				Data[];
+	UINT8				Data[56];
 
 }	WV_CONNECT_PARAM;
 
@@ -496,27 +487,39 @@ typedef struct _WV_DATAGRAM_PARAM
 	WV_ADDRESS_VECTOR	AddressVector;
 	NET32				Qpn;
 	NET32				Qkey;
-	UINT8				Data[];
+	UINT8				Data[56];
 
 }	WV_DATAGRAM_PARAM;
-#pragma warning(pop)
+
+typedef union _WV_SOCKADDR
+{
+	SOCKADDR			Sa;
+	SOCKADDR_IN			Sin;
+	SOCKADDR_IN6		Sin6;
+
+}	WV_SOCKADDR;
 
 typedef struct _WV_CONNECT_ATTRIBUTES
 {
-	WV_ADDRESS			LocalAddress;
-	SOCKET_ADDRESS		PeerAddress;
+	WV_SOCKADDR			LocalAddress;
+	WV_SOCKADDR			PeerAddress;
+	WV_DEVICE_ADDRESS	Device;
 	WV_CONNECT_PARAM	Param;
 
 }	WV_CONNECT_ATTRIBUTES;
 
 typedef struct _WV_DATAGRAM_ATTRIBUTES
 {
-	WV_ADDRESS			LocalAddress;
-	SOCKET_ADDRESS		PeerAddress;		// Specify when querying
+	WV_SOCKADDR			LocalAddress;
+	WV_SOCKADDR			PeerAddress;		// Specify when querying
+	WV_DEVICE_ADDRESS	Device;
 	WV_DATAGRAM_PARAM	Param;
 
 }	WV_DATAGRAM_ATTRIBUTES;
 
+// Endpoint options
+#define WV_EP_OPTION_ROUTE				0x00000001
+
 #undef INTERFACE
 #define INTERFACE IWVOverlapped
 // {64687592-aa67-4b55-bc4b-e189bdd2fc4f}
@@ -1126,15 +1129,27 @@ DECLARE_INTERFACE_(IWVEndpoint, IWVOverl
 		) PURE;
 
 	// IWVEndpoint methods
+	STDMETHOD(Modify)(
+		THIS_
+		__in DWORD Option,
+		__in_bcount_opt(OptionLength) const VOID* pOptionData,
+		__in SIZE_T OptionLength
+		) PURE;
+
 	STDMETHOD(BindAddress)(
 		THIS_
-		__in const struct sockaddr* pAddress
+		__in SOCKADDR* pAddress
+		) PURE;
+
+	STDMETHOD(Listen)(
+		THIS_
+		__in SIZE_T Backlog
 		) PURE;
 
 	STDMETHOD(Reject)(
 		THIS_
-		__in_bcount_opt(PrivateDataLength) const VOID* pPrivateData,
-		__in SIZE_T PrivateDataLength
+		__in_bcount_opt(UserDataLength) const VOID* pUserData,
+		__in SIZE_T UserDataLength
 		) PURE;
 };
 
@@ -1175,21 +1190,40 @@ DECLARE_INTERFACE_(IWVConnectEndpoint, I
 		) PURE;
 
 	// IWVEndpoint methods
+	__override STDMETHOD(Modify)(
+		THIS_
+		__in DWORD Option,
+		__in_bcount_opt(OptionLength) const VOID* pOptionData,
+		__in SIZE_T OptionLength
+		) PURE;
+
 	__override STDMETHOD(BindAddress)(
 		THIS_
-		__in const struct sockaddr* pAddress
+		__in SOCKADDR* pAddress
+		) PURE;
+
+	__override STDMETHOD(Listen)(
+		THIS_
+		__in SIZE_T Backlog
 		) PURE;
 
 	__override STDMETHOD(Reject)(
 		THIS_
-		__in_bcount_opt(PrivateDataLength) const VOID* pPrivateData,
-		__in SIZE_T PrivateDataLength
+		__in_bcount_opt(UserDataLength) const VOID* pUserData,
+		__in SIZE_T UserDataLength
 		) PURE;
 
 	// IWVConnectEndpoint methods
+	STDMETHOD(GetRequest)(
+		THIS_
+		__in IWVConnectEndpoint* pEndpoint,
+		__in_opt OVERLAPPED* pOverlapped
+		) PURE;
+
 	STDMETHOD(Connect)(
 		THIS_
 		__in IWVConnectQueuePair* pQp,
+		__in const SOCKADDR* pAddress,
 		__in WV_CONNECT_PARAM* pParam,
 		__in_opt OVERLAPPED* pOverlapped
 		) PURE;
@@ -1202,8 +1236,7 @@ DECLARE_INTERFACE_(IWVConnectEndpoint, I
 		) PURE;
 
 	STDMETHOD(Disconnect)(
-		THIS_
-		__in_opt OVERLAPPED* pOverlapped
+		THIS
 		) PURE;
 
 	STDMETHOD(NotifyDisconnect)(
@@ -1254,23 +1287,41 @@ DECLARE_INTERFACE_(IWVDatagramEndpoint, 
 		) PURE;
 
 	// IWVEndpoint methods
+	__override STDMETHOD(Modify)(
+		THIS_
+		__in DWORD Option,
+		__in_bcount_opt(OptionLength) const VOID* pOptionData,
+		__in SIZE_T OptionLength
+		) PURE;
+
 	__override STDMETHOD(BindAddress)(
 		THIS_
-		__in const struct sockaddr* pAddress
+		__in SOCKADDR* pAddress
+		) PURE;
+
+	__override STDMETHOD(Listen)(
+		THIS_
+		__in SIZE_T Backlog
 		) PURE;
 
 	__override STDMETHOD(Reject)(
 		THIS_
-		__in_bcount_opt(PrivateDataLength) const VOID* pPrivateData,
-		__in SIZE_T PrivateDataLength
+		__in_bcount_opt(UserDataLength) const VOID* pUserData,
+		__in SIZE_T UserDataLength
 		) PURE;
 
 	// IWVDatagramEndpoint methods
+	STDMETHOD(GetRequest)(
+		THIS_
+		__in IWVDatagramEndpoint* pEndpoint,
+		__in_opt OVERLAPPED* pOverlapped
+		) PURE;
+
 	STDMETHOD(Lookup)(
 		THIS_
-		__in const struct sockaddr* pAddress,
-		__in_bcount_opt(PrivateDataLength) const VOID* pPrivateData,
-		__in SIZE_T PrivateDataLength,
+		__in const SOCKADDR* pAddress,
+		__in_bcount_opt(UserDataLength) const VOID* pUserData,
+		__in SIZE_T UserDataLength,
 		__in_opt OVERLAPPED* pOverlapped
 		) PURE;
 
@@ -1282,13 +1333,13 @@ DECLARE_INTERFACE_(IWVDatagramEndpoint, 
 
 	STDMETHOD(JoinMulticast)(
 		THIS_
-		__in const struct sockaddr* pAddress,
+		__in const SOCKADDR* pAddress,
 		__in_opt OVERLAPPED* pOverlapped
 		) PURE;
 
 	STDMETHOD(LeaveMulticast)(
 		THIS_
-		__in const struct sockaddr* pAddress,
+		__in const SOCKADDR* pAddress,
 		__in_opt OVERLAPPED* pOverlapped
 		) PURE;
 
@@ -1300,50 +1351,6 @@ DECLARE_INTERFACE_(IWVDatagramEndpoint, 
 
 
 #undef INTERFACE
-#define INTERFACE IWVListen
-// {5b839fd4-7410-441f-a2d9-5d75b1d8599b}
-DEFINE_GUID(IID_IWVListen, 0x5b839fd4, 0x7410, 0x441f,
-			0xa2, 0xd9, 0x5d, 0x75, 0xb1, 0xd8, 0x59, 0x9b);
-
-DECLARE_INTERFACE_(IWVListen, IWVOverlapped)
-{
-	// IUnknown methods
-	__override STDMETHOD(QueryInterface)(
-		THIS_
-		REFIID riid,
-		LPVOID FAR* ppvObj
-		) PURE;
-
-	__override STDMETHOD_(ULONG,AddRef)(
-		THIS
-		) PURE;
-
-	__override STDMETHOD_(ULONG,Release)(
-		THIS
-		) PURE;
-
-	// IWVOverlapped methods
-	__override STDMETHOD(CancelOverlappedRequests)(
-		THIS
-		) PURE;
-
-	__override STDMETHOD(GetOverlappedResult)(
-		THIS_
-		__inout_opt OVERLAPPED *pOverlapped,
-		__out DWORD *pNumberOfBytesTransferred,
-		__in BOOL bWait
-		) PURE;
-
-	// IWVListen methods
-	STDMETHOD(GetRequest)(
-		THIS_
-		__in IWVEndpoint* pEndpoint,
-		__in_opt OVERLAPPED* pOverlapped
-		) PURE;
-};
-
-
-#undef INTERFACE
 #define INTERFACE IWVDevice
 // {244af78c-b1ac-40e4-9896-271d58d591b8}
 DEFINE_GUID(IID_IWVDevice, 0x244af78c, 0xb1ac, 0x40e4,
@@ -1397,6 +1404,13 @@ DECLARE_INTERFACE_(IWVDevice, IWVOverlap
 		__out WV_GID* pGid
 		) PURE;
 
+	STDMETHOD(FindGid)(
+		THIS_
+		__in UINT8 PortNumber,
+		__in WV_GID* pGid,
+		__out DWORD* pIndex
+		) PURE;
+
 	STDMETHOD(QueryPkey)(
 		THIS_
 		__in UINT8 PortNumber,
@@ -1404,6 +1418,13 @@ DECLARE_INTERFACE_(IWVDevice, IWVOverlap
 		__out NET16* pPkey
 		) PURE;
 
+	STDMETHOD(FindPkey)(
+		THIS_
+		__in UINT8 PortNumber,
+		__in NET16 Pkey,
+		__out DWORD* pIndex
+		) PURE;
+
 	STDMETHOD(CreateCompletionQueue)(
 		THIS_
 		__inout SIZE_T *pEntries,
@@ -1426,9 +1447,9 @@ DECLARE_INTERFACE_(IWVDevice, IWVOverlap
 
 #undef INTERFACE
 #define INTERFACE IWVProvider
-// {6901010c-17af-4894-a1dc-794d3611f262}
-DEFINE_GUID(IID_IWVProvider, 0x6901010c, 0x17af, 0x4894,
-			0xa1, 0xdc, 0x79, 0x4d, 0x36, 0x11, 0xf2, 0x62);
+// {060E95D6-EC54-43b2-83FC-B578FD037259}
+DEFINE_GUID(IID_IWVProvider, 0x60e95d6, 0xec54, 0x43b2,
+			0x83, 0xfc, 0xb5, 0x78, 0xfd, 0x3, 0x72, 0x59);
 
 DECLARE_INTERFACE_(IWVProvider, IUnknown)
 {
@@ -1464,10 +1485,10 @@ DECLARE_INTERFACE_(IWVProvider, IUnknown
 		__out WV_DEVICE_ATTRIBUTES* pAttributes
 		) PURE;
 
-	STDMETHOD(QueryAddressList)(
+	STDMETHOD(TranslateAddress)(
 		THIS_
-		__inout_bcount_part_opt(*pBufferSize, *pBufferSize) WV_ADDRESS_LIST* pAddressList,
-		__inout SIZE_T* pBufferSize
+		__in SOCKADDR* pAddress,
+		__out WV_DEVICE_ADDRESS* pDeviceAddress
 		) PURE;
 
 	STDMETHOD(OpenDevice)(
@@ -1485,13 +1506,6 @@ DECLARE_INTERFACE_(IWVProvider, IUnknown
 		THIS_
 		__deref_out IWVDatagramEndpoint** ppDatagramEndpoint
 		) PURE;
-
-	STDMETHOD(CreateListen)(
-		THIS_
-		__in const struct sockaddr* pAddress,
-		__in SIZE_T Backlog,
-		__deref_out IWVListen** ppListen
-		) PURE;
 };
 
 __declspec(dllexport) HRESULT WvGetObject(REFIID riid, LPVOID FAR* ppvObj);
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/core/winverbs/user/SOURCES branches\winverbs/core/winverbs/user/SOURCES
--- trunk/core/winverbs/user/SOURCES	2008-06-18 16:15:37.997617300 -0700
+++ branches\winverbs/core/winverbs/user/SOURCES	2009-01-05 15:10:21.549145400 -0800
@@ -14,7 +14,7 @@ DLLDEF = $(OBJ_PATH)\$O\wv_exports.def
 !endif
 
 DLLENTRY = DllMain
-USE_NTDLL = 1
+USE_MSVCRT = 1
 
 SOURCES = \
 	winverbs.rc		\
@@ -23,7 +23,6 @@ SOURCES = \
 	wv_cq.cpp		\
 	wv_device.cpp	\
 	wv_ep.cpp		\
-	wv_listen.cpp	\
 	wv_pd.cpp		\
 	wv_provider.cpp	\
 	wv_qp.cpp		\
@@ -36,4 +35,5 @@ USER_C_FLAGS = $(USER_C_FLAGS) -DEXPORT_
 
 TARGETLIBS = \
 	$(SDK_LIB_PATH)\kernel32.lib	\
-	$(SDK_LIB_PATH)\uuid.lib
+	$(SDK_LIB_PATH)\uuid.lib		\
+	$(SDK_LIB_PATH)\ws2_32.lib
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/core/winverbs/user/wv_cq.cpp branches\winverbs/core/winverbs/user/wv_cq.cpp
--- trunk/core/winverbs/user/wv_cq.cpp	2008-07-16 22:31:21.406250000 -0700
+++ branches\winverbs/core/winverbs/user/wv_cq.cpp	2008-11-25 11:43:16.843750000 -0800
@@ -99,7 +99,7 @@ CWVCompletionQueue::~CWVCompletionQueue(
 	DWORD	bytes;
 	HRESULT	hr;
 
-	if (m_Id != NULL) {
+	if (m_Id != 0) {
 		m_pVerbs->pre_destroy_cq(m_hVerbsCq);
 		hr = WvDeviceIoControl(m_hFile, WV_IOCTL_CQ_DESTROY, &m_Id, sizeof m_Id,
 							   NULL, 0, &bytes, NULL) ?
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/core/winverbs/user/wv_device.cpp
branches\winverbs/core/winverbs/user/wv_device.cpp
--- trunk/core/winverbs/user/wv_device.cpp	2008-07-21 08:56:48.180269700 -0700
+++ branches\winverbs/core/winverbs/user/wv_device.cpp	2009-01-12 15:26:02.603875400 -0800
@@ -293,7 +293,7 @@ out:
 }
 
 STDMETHODIMP CWVDevice::
-FindGidIndex(UINT8 PortNumber, WV_GID *pGid, UINT16 *pIndex)
+FindGid(UINT8 PortNumber, WV_GID *pGid, DWORD *pIndex)
 {
 	WV_GID	gid;
 	DWORD	index;
@@ -302,16 +302,16 @@ FindGidIndex(UINT8 PortNumber, WV_GID *p
 	for (index = 0; true; index++) {
 		hr = QueryGid(PortNumber, index, &gid);
 		if (FAILED(hr)) {
-			break;
+			return hr;
 		}
 
-		if (RtlCompareMemory(pGid, &gid, sizeof(gid)) == sizeof(gid)) {
+		if (RtlEqualMemory(pGid, &gid, sizeof(gid))) {
 			*pIndex = (UINT16) index;
-			break;
+			return WV_SUCCESS;
 		}
 	}
 
-	return hr;
+	return WV_INVALID_ADDRESS;
 }
 
 STDMETHODIMP CWVDevice::
@@ -353,6 +353,28 @@ out:
 }
 
 STDMETHODIMP CWVDevice::
+FindPkey(UINT8 PortNumber, NET16 Pkey, DWORD *pIndex)
+{
+	NET16	key;
+	DWORD	index;
+	HRESULT	hr;
+
+	for (index = 0; true; index++) {
+		hr = QueryPkey(PortNumber, index, &key);
+		if (FAILED(hr)) {
+			return hr;
+		}
+
+		if (Pkey == key) {
+			*pIndex = (UINT16) index;
+			return WV_SUCCESS;
+		}
+	}
+
+	return WV_INVALID_ADDRESS;
+}
+
+STDMETHODIMP CWVDevice::
 CreateCompletionQueue(SIZE_T *pEntries, IWVCompletionQueue** ppCq)
 {
 	return CWVCompletionQueue::CreateInstance(this, pEntries, ppCq);
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/core/winverbs/user/wv_device.h
branches\winverbs/core/winverbs/user/wv_device.h
--- trunk/core/winverbs/user/wv_device.h	2008-07-18 02:12:53.593750000 -0700
+++ branches\winverbs/core/winverbs/user/wv_device.h	2008-12-01 23:13:44.756625000 -0800
@@ -55,7 +55,9 @@ public:
 	STDMETHODIMP Query(WV_DEVICE_ATTRIBUTES* pAttributes);
 	STDMETHODIMP QueryPort(UINT8 PortNumber, WV_PORT_ATTRIBUTES* pAttributes);
 	STDMETHODIMP QueryGid(UINT8 PortNumber, DWORD Index, WV_GID* pGid);
+	STDMETHODIMP FindGid(UINT8 PortNumber, WV_GID *pGid, DWORD *pIndex);
 	STDMETHODIMP QueryPkey(UINT8 PortNumber, DWORD Index, NET16* pPkey);
+	STDMETHODIMP FindPkey(UINT8 PortNumber, NET16 Pkey, DWORD *pIndex);
 	STDMETHODIMP CreateCompletionQueue(SIZE_T *pEntries, IWVCompletionQueue** ppCq);
 	STDMETHODIMP AllocateProtectionDomain(IWVProtectionDomain** ppPd);
 	STDMETHODIMP Notify(UINT8 PortNumber, OVERLAPPED* pOverlapped, DWORD* pFlags);
@@ -94,7 +96,6 @@ public:
 		*ppDevice = NULL;
 		return hr;
 	}
-	STDMETHODIMP FindGidIndex(UINT8 PortNumber, WV_GID *pGid, UINT16 *pIndex);
 
 	CWVProvider		*m_pProvider;
 	uvp_interface_t	m_Verbs;
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/core/winverbs/user/wv_ep.cpp branches\winverbs/core/winverbs/user/wv_ep.cpp
--- trunk/core/winverbs/user/wv_ep.cpp	2008-06-04 23:14:01.953125000 -0700
+++ branches\winverbs/core/winverbs/user/wv_ep.cpp	2009-01-08 15:21:20.479092200 -0800
@@ -30,16 +30,58 @@
 #include "wv_memory.h"
 #include "wv_ep.h"
 #include "wv_ioctl.h"
+#include "wv_qp.h"
+
+static void WvIoConvertConnParam(WV_IO_CONNECT_PARAM *pIoParam,
+								 WV_CONNECT_PARAM *pParam)
+{
+	pIoParam->DataLength = (UINT8) pParam->DataLength;
+	pIoParam->ResponderResources = pParam->ResponderResources;
+	pIoParam->InitiatorDepth = pParam->InitiatorDepth;
+	pIoParam->RetryCount = pParam->RetryCount;
+	pIoParam->RnrRetryCount = pParam->RnrRetryCount;
+	RtlZeroMemory(pIoParam->Reserved, sizeof pIoParam->Reserved);
+	RtlCopyMemory(pIoParam->Data, pParam->Data, pParam->DataLength);
+}
 
 CWVConnectEndpoint::CWVConnectEndpoint(CWVProvider *pProvider)
 {
 	pProvider->AddRef();
 	m_pProvider = pProvider;
 	m_hFile = pProvider->m_hFile;
+	m_Socket = INVALID_SOCKET;
+}
+
+STDMETHODIMP CWVConnectEndpoint::
+Allocate(void)
+{
+	UINT64			EpType;
+	DWORD			bytes;
+	HRESULT			hr;
+
+	EpType = WV_IO_EP_TYPE_CONNECT;
+	if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_CREATE, &EpType, sizeof EpType,
+						  &m_Id, sizeof m_Id, &bytes, NULL)) {
+		hr = WV_SUCCESS;
+	} else {
+		hr = HRESULT_FROM_WIN32(GetLastError());
+	}
+
+	return hr;
 }
 
 CWVConnectEndpoint::~CWVConnectEndpoint()
 {
+	DWORD	bytes;
+
+	if (m_Id != 0) {
+		WvDeviceIoControl(m_hFile, WV_IOCTL_EP_DESTROY, &m_Id, sizeof m_Id,
+						  NULL, 0, &bytes, NULL);
+	}
+
+	if (m_Socket != INVALID_SOCKET) {
+		closesocket(m_Socket);
+	}
 	m_pProvider->Release();
 }
 
@@ -88,64 +130,263 @@ GetOverlappedResult(OVERLAPPED *pOverlap
 }
 
 STDMETHODIMP CWVConnectEndpoint::
-BindAddress(const struct sockaddr* pAddress)
+Modify(DWORD Option, const VOID* pOptionData, SIZE_T OptionLength)
 {
-	UNREFERENCED_PARAMETER(pAddress);
+	WV_IO_ID			*pId;
+	DWORD				bytes;
+	HRESULT				hr;
+	CWVBuffer			buf;
+
+	bytes = sizeof WV_IO_ID + OptionLength;
+	pId = (WV_IO_ID *) buf.Get(bytes);
+	if (pId == NULL) {
+		return WV_NO_MEMORY;
+	}
 
-	return E_NOTIMPL;
+	pId->Id = m_Id;
+	pId->Data = Option;
+	RtlCopyMemory(pId + 1, pOptionData, OptionLength);
+
+	if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_MODIFY, pId, bytes,
+						  NULL, 0, &bytes, NULL)) {
+		hr = WV_SUCCESS;
+	} else {
+		hr = HRESULT_FROM_WIN32(GetLastError());
+	}
+
+	buf.Put();
+	return hr;
 }
 
 STDMETHODIMP CWVConnectEndpoint::
-Reject(const VOID* pPrivateData, SIZE_T PrivateDataLength)
+BindAddress(SOCKADDR* pAddress)
 {
-	UNREFERENCED_PARAMETER(pPrivateData);
-	UNREFERENCED_PARAMETER(PrivateDataLength);
+	WV_IO_EP_BIND		attr;
+	BOOLEAN				any;
+	DWORD				bytes;
+	HRESULT				hr;
+
+	if (pAddress->sa_family == AF_INET) {
+		any = (((SOCKADDR_IN *) pAddress)->sin_addr.S_un.S_addr == INADDR_ANY);
+		bytes = sizeof(SOCKADDR_IN);
+	} else {
+		any = IN6ADDR_ISANY((SOCKADDR_IN6 *) pAddress);
+		bytes = sizeof(SOCKADDR_IN6);
+	}
 
-	return E_NOTIMPL;
+	if (any) {
+		RtlZeroMemory(&attr.Device, sizeof attr.Device);
+	} else {
+		hr = m_pProvider->TranslateAddress(pAddress, (WV_DEVICE_ADDRESS *) &attr.Device);
+		if (FAILED(hr)) {
+			return hr;
+		}
+	}
+
+	m_Socket = socket(pAddress->sa_family, SOCK_STREAM, IPPROTO_TCP);
+	if (m_Socket == INVALID_SOCKET) {
+		return WSAGetLastError();
+	}
+
+	hr = bind(m_Socket, pAddress, bytes);
+	if (FAILED(hr)) {
+		goto err;
+	}
+
+	attr.Id = m_Id;
+	RtlCopyMemory(&attr.Address, pAddress, bytes);
+
+	if (!WvDeviceIoControl(m_hFile, WV_IOCTL_EP_BIND, &attr, sizeof attr,
+						   &attr, sizeof attr, &bytes, NULL)) {
+		hr = HRESULT_FROM_WIN32(GetLastError());
+		goto err;
+	}
+
+	return WV_SUCCESS;
+
+err:
+	closesocket(m_Socket);
+	m_Socket = INVALID_SOCKET;
+	return hr;
 }
 
 STDMETHODIMP CWVConnectEndpoint::
-Connect(IWVConnectQueuePair* pQp, WV_CONNECT_PARAM* pParam, OVERLAPPED* pOverlapped)
+Listen(SIZE_T Backlog)
 {
-	UNREFERENCED_PARAMETER(pQp);
-	UNREFERENCED_PARAMETER(pParam);
-	UNREFERENCED_PARAMETER(pOverlapped);
+	WV_IO_EP_LISTEN		attr;
+	DWORD				bytes;
+	HRESULT				hr;
+
+	attr.Id = m_Id;
+	attr.Backlog = Backlog;
+
+	if (!WvDeviceIoControl(m_hFile, WV_IOCTL_EP_LISTEN, &attr, sizeof attr,
+						   &attr, sizeof attr, &bytes, NULL)) {
+		hr = HRESULT_FROM_WIN32(GetLastError());
+	} else {
+		hr = WV_SUCCESS;
+	}
 
-	return E_NOTIMPL;
+	return hr;
+}
+
+STDMETHODIMP CWVConnectEndpoint::
+Reject(const VOID* pUserData, SIZE_T UserDataLength)
+{
+	WV_IO_ID			*pId;
+	DWORD				bytes;
+	HRESULT				hr;
+	CWVBuffer			buf;
+
+	bytes = sizeof WV_IO_ID + UserDataLength;
+	pId = (WV_IO_ID *) buf.Get(bytes);
+	if (pId == NULL) {
+		return WV_NO_MEMORY;
+	}
+
+	pId->Id = m_Id;
+	RtlCopyMemory(pId + 1, pUserData, UserDataLength);
+
+	if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_REJECT, pId, bytes,
+						  NULL, 0, &bytes, NULL)) {
+		hr = WV_SUCCESS;
+	} else {
+		hr = HRESULT_FROM_WIN32(GetLastError());
+	}
+
+	buf.Put();
+	return hr;
+}
+
+STDMETHODIMP CWVConnectEndpoint::
+GetRequest(IWVConnectEndpoint* pEndpoint, OVERLAPPED* pOverlapped)
+{
+	WV_IO_EP_GET_REQUEST	req;
+	DWORD					bytes;
+	HRESULT					hr;
+
+	req.Id = m_Id;
+	req.EpId = ((CWVConnectEndpoint *) pEndpoint)->m_Id;
+	if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_GET_REQUEST,
+						  &req, sizeof req, NULL, 0, &bytes, pOverlapped)) {
+		hr = WV_SUCCESS;
+	} else {
+		hr = HRESULT_FROM_WIN32(GetLastError());
+	}
+
+	return hr;
+}
+
+STDMETHODIMP CWVConnectEndpoint::
+Connect(IWVConnectQueuePair* pQp, const SOCKADDR* pAddress,
+		WV_CONNECT_PARAM* pParam, OVERLAPPED* pOverlapped)
+{
+	WV_IO_EP_CONNECT	attr;
+	DWORD				bytes;
+	HRESULT				hr;
+
+	attr.Id = m_Id;
+	attr.QpId = ((CWVConnectQueuePair *) pQp)->m_Id;
+
+	if (pAddress->sa_family == AF_INET) {
+		RtlCopyMemory(&attr.PeerAddress, pAddress, sizeof(SOCKADDR_IN));
+	} else {
+		RtlCopyMemory(&attr.PeerAddress, pAddress, sizeof(SOCKADDR_IN6));
+	}
+	WvIoConvertConnParam(&attr.Param, pParam);
+
+	if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_CONNECT, &attr, sizeof attr,
+						  NULL, 0, &bytes, pOverlapped)) {
+		hr = WV_SUCCESS;
+	} else {
+		hr = HRESULT_FROM_WIN32(GetLastError());
+	}
+
+	return hr;
 }
 
 STDMETHODIMP CWVConnectEndpoint::
 Accept(IWVConnectQueuePair* pQp, WV_CONNECT_PARAM* pParam, OVERLAPPED* pOverlapped)
 {
-	UNREFERENCED_PARAMETER(pQp);
-	UNREFERENCED_PARAMETER(pParam);
-	UNREFERENCED_PARAMETER(pOverlapped);
+	CWVConnectQueuePair	*qp = (CWVConnectQueuePair *) pQp;
+	WV_IO_EP_ACCEPT		attr;
+	DWORD				bytes;
+	HRESULT				hr;
+	void				*pout;
+	DWORD				size;
+
+	attr.Id = m_Id;
+	attr.QpId = qp->m_Id;
+	qp->m_pVerbs->nd_modify_qp(qp->m_hVerbsQp, &pout, &size);
+	WvIoConvertConnParam(&attr.Param, pParam);
+
+	if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_ACCEPT, &attr, sizeof attr,
+						  pout, size, &bytes, pOverlapped)) {
+		hr = WV_SUCCESS;
+	} else {
+		hr = HRESULT_FROM_WIN32(GetLastError());
+	}
 
-	return E_NOTIMPL;
+	return hr;
 }
 
 STDMETHODIMP CWVConnectEndpoint::
-Disconnect(OVERLAPPED* pOverlapped)
+Disconnect(void)
 {
-	UNREFERENCED_PARAMETER(pOverlapped);
+	DWORD		bytes;
+	HRESULT		hr;
 
-	return E_NOTIMPL;
+	if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_DISCONNECT,
+						  &m_Id, sizeof m_Id, NULL, 0, &bytes, NULL)) {
+		hr = WV_SUCCESS;
+	} else {
+		hr = HRESULT_FROM_WIN32(GetLastError());
+	}
+
+	return hr;
 }
 
 STDMETHODIMP CWVConnectEndpoint::
 NotifyDisconnect(OVERLAPPED* pOverlapped)
 {
-	UNREFERENCED_PARAMETER(pOverlapped);
+	DWORD		bytes;
+	HRESULT		hr;
 
-	return E_NOTIMPL;
+	if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_DISCONNECT_NOTIFY,
+						  &m_Id, sizeof m_Id, NULL, 0, &bytes, pOverlapped)) {
+		hr = WV_SUCCESS;
+	} else {
+		hr = HRESULT_FROM_WIN32(GetLastError());
+	}
+
+	return hr;
 }
 
 STDMETHODIMP CWVConnectEndpoint::
 Query(WV_CONNECT_ATTRIBUTES* pAttributes)
 {
-	UNREFERENCED_PARAMETER(pAttributes);
+	WV_IO_EP_ATTRIBUTES	attr;
+	DWORD				bytes;
+	HRESULT				hr;
+
+	if (!WvDeviceIoControl(m_hFile, WV_IOCTL_EP_QUERY, &m_Id, sizeof m_Id,
+						   &attr, sizeof attr, &bytes, NULL)) {
+		return HRESULT_FROM_WIN32(GetLastError());
+	}
 
-	return E_NOTIMPL;
+	RtlCopyMemory(&pAttributes->LocalAddress, &attr.LocalAddress,
+				  sizeof pAttributes->LocalAddress);
+	RtlCopyMemory(&pAttributes->PeerAddress, &attr.PeerAddress,
+				  sizeof pAttributes->PeerAddress);
+	RtlCopyMemory(&pAttributes->Device, &attr.Device, sizeof pAttributes->Device);
+	pAttributes->Param.DataLength = attr.Param.Connect.DataLength;
+	pAttributes->Param.ResponderResources = (SIZE_T) attr.Param.Connect.ResponderResources;
+	pAttributes->Param.InitiatorDepth = (SIZE_T) attr.Param.Connect.InitiatorDepth;
+	pAttributes->Param.RetryCount = attr.Param.Connect.RetryCount;
+	pAttributes->Param.RnrRetryCount = attr.Param.Connect.RnrRetryCount;
+	RtlCopyMemory(pAttributes->Param.Data, attr.Param.Connect.Data, attr.Param.Connect.DataLength);
+
+	return WV_SUCCESS;
 }
 
 
@@ -155,9 +396,33 @@ CWVDatagramEndpoint::CWVDatagramEndpoint
 	m_pProvider = pProvider;
 	m_hFile = pProvider->m_hFile;
 }
+	
+STDMETHODIMP CWVDatagramEndpoint::
+Allocate(void)
+{
+	UINT64			EpType;
+	DWORD			bytes;
+	HRESULT			hr;
+
+	EpType = WV_IO_EP_TYPE_DATAGRAM;
+	if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_CREATE, &EpType, sizeof EpType,
+						  &m_Id, sizeof m_Id, &bytes, NULL)) {
+		hr = WV_SUCCESS;
+	} else {
+		hr = HRESULT_FROM_WIN32(GetLastError());
+	}
+
+	return hr;
+}
 
 CWVDatagramEndpoint::~CWVDatagramEndpoint()
 {
+	DWORD	bytes;
+
+	if (m_Id != 0) {
+		WvDeviceIoControl(m_hFile, WV_IOCTL_EP_DESTROY, &m_Id, sizeof m_Id,
+						  NULL, 0, &bytes, NULL);
+	}
 	m_pProvider->Release();
 }
 
@@ -206,7 +471,17 @@ GetOverlappedResult(OVERLAPPED *pOverlap
 }
 
 STDMETHODIMP CWVDatagramEndpoint::
-BindAddress(const struct sockaddr* pAddress)
+Modify(DWORD Option, const VOID* pOptionData, SIZE_T OptionLength)
+{
+	UNREFERENCED_PARAMETER(Option);
+	UNREFERENCED_PARAMETER(pOptionData);
+	UNREFERENCED_PARAMETER(OptionLength);
+
+	return E_NOTIMPL;
+}
+
+STDMETHODIMP CWVDatagramEndpoint::
+BindAddress(SOCKADDR* pAddress)
 {
 	UNREFERENCED_PARAMETER(pAddress);
 
@@ -214,21 +489,38 @@ BindAddress(const struct sockaddr* pAddr
 }
 
 STDMETHODIMP CWVDatagramEndpoint::
-Reject(const VOID* pPrivateData, SIZE_T PrivateDataLength)
+Listen(SIZE_T Backlog)
 {
-	UNREFERENCED_PARAMETER(pPrivateData);
-	UNREFERENCED_PARAMETER(PrivateDataLength);
+	UNREFERENCED_PARAMETER(Backlog);
+
+	return E_NOTIMPL;
+}
+
+STDMETHODIMP CWVDatagramEndpoint::
+Reject(const VOID* pUserData, SIZE_T UserDataLength)
+{
+	UNREFERENCED_PARAMETER(pUserData);
+	UNREFERENCED_PARAMETER(UserDataLength);
+
+	return E_NOTIMPL;
+}
+
+STDMETHODIMP CWVDatagramEndpoint::
+GetRequest(IWVDatagramEndpoint* pEndpoint, OVERLAPPED* pOverlapped)
+{
+	UNREFERENCED_PARAMETER(pEndpoint);
+	UNREFERENCED_PARAMETER(pOverlapped);
 
 	return E_NOTIMPL;
 }
 
 STDMETHODIMP CWVDatagramEndpoint::
-Lookup(const struct sockaddr* pAddress, const VOID* pPrivateData,
-	   SIZE_T PrivateDataLength, OVERLAPPED* pOverlapped)
+Lookup(const SOCKADDR* pAddress, const VOID* pUserData,
+	   SIZE_T UserDataLength, OVERLAPPED* pOverlapped)
 {
 	UNREFERENCED_PARAMETER(pAddress);
-	UNREFERENCED_PARAMETER(pPrivateData);
-	UNREFERENCED_PARAMETER(PrivateDataLength);
+	UNREFERENCED_PARAMETER(pUserData);
+	UNREFERENCED_PARAMETER(UserDataLength);
 	UNREFERENCED_PARAMETER(pOverlapped);
 
 	return E_NOTIMPL;
@@ -244,7 +536,7 @@ Accept(WV_DATAGRAM_PARAM* pParam, OVERLA
 }
 
 STDMETHODIMP CWVDatagramEndpoint::
-JoinMulticast(const struct sockaddr* pAddress, OVERLAPPED* pOverlapped)
+JoinMulticast(const SOCKADDR* pAddress, OVERLAPPED* pOverlapped)
 {
 	UNREFERENCED_PARAMETER(pAddress);
 	UNREFERENCED_PARAMETER(pOverlapped);
@@ -253,7 +545,7 @@ JoinMulticast(const struct sockaddr* pAd
 }
 
 STDMETHODIMP CWVDatagramEndpoint::
-LeaveMulticast(const struct sockaddr* pAddress, OVERLAPPED* pOverlapped)
+LeaveMulticast(const SOCKADDR* pAddress, OVERLAPPED* pOverlapped)
 {
 	UNREFERENCED_PARAMETER(pAddress);
 	UNREFERENCED_PARAMETER(pOverlapped);
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/core/winverbs/user/wv_ep.h branches\winverbs/core/winverbs/user/wv_ep.h
--- trunk/core/winverbs/user/wv_ep.h	2008-06-04 22:50:09.781250000 -0700
+++ branches\winverbs/core/winverbs/user/wv_ep.h	2008-12-01 12:41:07.938683200 -0800
@@ -50,15 +50,18 @@ public:
 									 DWORD *pNumberOfBytesTransferred, BOOL bWait);
 
 	// IWVEndpoint methods
-	STDMETHODIMP BindAddress(const struct sockaddr* pAddress);
-	STDMETHODIMP Reject(const VOID* pPrivateData, SIZE_T PrivateDataLength);
+	STDMETHODIMP Modify(DWORD Option, const VOID* pOptionData, SIZE_T OptionLength);
+	STDMETHODIMP BindAddress(SOCKADDR* pAddress);
+	STDMETHODIMP Listen(SIZE_T Backlog);
+	STDMETHODIMP Reject(const VOID* pUserData, SIZE_T UserDataLength);
 
 	// IWVConnectEndpoint methods
-	STDMETHODIMP Connect(IWVConnectQueuePair* pQp, WV_CONNECT_PARAM* pParam,
-						 OVERLAPPED* pOverlapped);
+	STDMETHODIMP GetRequest(IWVConnectEndpoint* pEndpoint, OVERLAPPED* pOverlapped);
+	STDMETHODIMP Connect(IWVConnectQueuePair* pQp, const SOCKADDR* pAddress,
+						 WV_CONNECT_PARAM* pParam, OVERLAPPED* pOverlapped);
 	STDMETHODIMP Accept(IWVConnectQueuePair* pQp, WV_CONNECT_PARAM* pParam,
 						OVERLAPPED* pOverlapped);
-	STDMETHODIMP Disconnect(OVERLAPPED* pOverlapped);
+	STDMETHODIMP Disconnect();
 	STDMETHODIMP NotifyDisconnect(OVERLAPPED* pOverlapped);
 	STDMETHODIMP Query(WV_CONNECT_ATTRIBUTES* pAttributes);
 
@@ -82,6 +85,11 @@ public:
 			goto err2;
 		}
 
+		hr = ep->Allocate();
+		if (FAILED(hr)) {
+			goto err2;
+		}
+
 		*ppConnectEndpoint = ep;
 		return WV_SUCCESS;
 
@@ -93,6 +101,11 @@ public:
 	}
 
 	CWVProvider		*m_pProvider;
+
+protected:
+	SOCKET			m_Socket;
+
+	STDMETHODIMP Allocate();
 };
 
 class CWVDatagramEndpoint : IWVDatagramEndpoint, public CWVBase
@@ -109,16 +122,19 @@ public:
 									 DWORD *pNumberOfBytesTransferred, BOOL bWait);
 
 	// IWVEndpoint methods
-	STDMETHODIMP BindAddress(const struct sockaddr* pAddress);
-	STDMETHODIMP Reject(const VOID* pPrivateData, SIZE_T PrivateDataLength);
+	STDMETHODIMP Modify(DWORD Option, const VOID* pOptionData, SIZE_T OptionLength);
+	STDMETHODIMP BindAddress(SOCKADDR* pAddress);
+	STDMETHODIMP Listen(SIZE_T Backlog);
+	STDMETHODIMP Reject(const VOID* pUserData, SIZE_T UserDataLength);
 
 	// IWVDatagramEndpoint methods
-	STDMETHODIMP Lookup(const struct sockaddr* pAddress, const VOID* pPrivateData,
-						SIZE_T PrivateDataLength, OVERLAPPED* pOverlapped);
+	STDMETHODIMP GetRequest(IWVDatagramEndpoint* pEndpoint, OVERLAPPED* pOverlapped);
+	STDMETHODIMP Lookup(const SOCKADDR* pAddress, const VOID* pUserData,
+						SIZE_T UserDataLength, OVERLAPPED* pOverlapped);
 	STDMETHODIMP Accept(WV_DATAGRAM_PARAM* pParam, OVERLAPPED* pOverlapped);
-	STDMETHODIMP JoinMulticast(const struct sockaddr* pAddress,
+	STDMETHODIMP JoinMulticast(const SOCKADDR* pAddress,
 							   OVERLAPPED* pOverlapped);
-	STDMETHODIMP LeaveMulticast(const struct sockaddr* pAddress,
+	STDMETHODIMP LeaveMulticast(const SOCKADDR* pAddress,
 								OVERLAPPED* pOverlapped);
 	STDMETHODIMP Query(WV_DATAGRAM_ATTRIBUTES* pAttributes);
 
@@ -142,6 +158,11 @@ public:
 			goto err2;
 		}
 
+		hr = ep->Allocate();
+		if (FAILED(hr)) {
+			goto err2;
+		}
+
 		*ppDatagramEndpoint = ep;
 		return WV_SUCCESS;
 
@@ -153,6 +174,9 @@ public:
 	}
 
 	CWVProvider		*m_pProvider;
+
+protected:
+	STDMETHODIMP Allocate();
 };
 
 #endif // _WV_EP_H_
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/core/winverbs/user/wv_listen.cpp
branches\winverbs/core/winverbs/user/wv_listen.cpp
--- trunk/core/winverbs/user/wv_listen.cpp	2008-06-04 23:14:01.875000000 -0700
+++ branches\winverbs/core/winverbs/user/wv_listen.cpp	2008-11-25 11:57:35.328125000 -0800
@@ -30,16 +30,28 @@
 #include "wv_memory.h"
 #include "wv_listen.h"
 #include "wv_ioctl.h"
+#include "wv_ep.h"
 
 CWVListen::CWVListen(CWVProvider *pProvider)
 {
 	pProvider->AddRef();
 	m_pProvider = pProvider;
 	m_hFile = pProvider->m_hFile;
+	m_Socket = INVALID_SOCKET;
 }
 
 CWVListen::~CWVListen()
 {
+	DWORD	bytes;
+
+	if (m_Id != 0) {
+		WvDeviceIoControl(m_hFile, WV_IOCTL_EP_DESTROY, &m_Id, sizeof m_Id,
+						  NULL, 0, &bytes, NULL);
+	}
+
+	if (m_Socket != INVALID_SOCKET) {
+		closesocket(m_Socket);
+	}
 	m_pProvider->Release();
 }
 
@@ -73,7 +85,7 @@ CancelOverlappedRequests(void)
 {
 	DWORD	bytes;
 
-	return WvDeviceIoControl(m_hFile, WV_IOCTL_LISTEN_CANCEL, &m_Id, sizeof m_Id,
+	return WvDeviceIoControl(m_hFile, WV_IOCTL_EP_CANCEL, &m_Id, sizeof m_Id,
 							 NULL, 0, &bytes, NULL) ?
 							 WV_SUCCESS : HRESULT_FROM_WIN32(GetLastError());
 }
@@ -87,19 +99,139 @@ GetOverlappedResult(OVERLAPPED *pOverlap
 }
 
 STDMETHODIMP CWVListen::
-Listen(const struct sockaddr* pAddress, SIZE_T Backlog)
+Allocate(UINT64 EpType)
 {
-	UNREFERENCED_PARAMETER(pAddress);
-	UNREFERENCED_PARAMETER(Backlog);
+	DWORD	bytes;
+	HRESULT	hr;
 
-	return E_NOTIMPL;
+	if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_CREATE, &EpType, sizeof EpType,
+						  &m_Id, sizeof m_Id, &bytes, NULL)) {
+		hr = WV_SUCCESS;
+	} else {
+		hr = HRESULT_FROM_WIN32(GetLastError());
+	}
+
+	return hr;
+}
+
+STDMETHODIMP CWVListen::
+Bind(SOCKADDR* pAddress, WV_EP_TYPE EpType)
+{
+	WV_IO_EP_BIND		attr;
+	BOOLEAN				any;
+	DWORD				bytes;
+	HRESULT				hr;
+
+	if (pAddress->sa_family == AF_INET) {
+		any = (((SOCKADDR_IN *) pAddress)->sin_addr.S_un.S_addr == INADDR_ANY);
+		bytes = sizeof(SOCKADDR_IN);
+	} else {
+		any = IN6ADDR_ISANY((SOCKADDR_IN6 *) pAddress);
+		bytes = sizeof(SOCKADDR_IN6);
+	}
+
+	if (any == FALSE) {
+		hr = m_pProvider->TranslateAddress(pAddress,
+										   (WV_DEVICE_ADDRESS *) &attr.Device);
+		if (FAILED(hr)) {
+			return hr;
+		}
+	}
+
+	m_Socket = (EpType == WvEpTypeConnect) ?
+			   socket(pAddress->sa_family, SOCK_STREAM, IPPROTO_TCP) :
+			   socket(pAddress->sa_family, SOCK_DGRAM, IPPROTO_UDP);
+	if (m_Socket == INVALID_SOCKET) {
+		return WSAGetLastError();
+	}
+
+	hr = bind(m_Socket, pAddress, bytes);
+	if (FAILED(hr)) {
+		goto err;
+	}
+
+	attr.Id = m_Id;
+	RtlCopyMemory(&attr.Address, pAddress, bytes);
+
+	if (!WvDeviceIoControl(m_hFile, WV_IOCTL_EP_BIND, &attr, sizeof attr,
+						   &attr, sizeof attr, &bytes, NULL)) {
+		hr = HRESULT_FROM_WIN32(GetLastError());
+		goto err;
+	}
+
+	return WV_SUCCESS;
+
+err:
+	closesocket(m_Socket);
+	m_Socket = INVALID_SOCKET;
+	return hr;
+}
+
+STDMETHODIMP CWVListen::
+Listen(SOCKADDR* pAddress, WV_EP_TYPE EpType, SIZE_T Backlog)
+{
+	WV_IO_EP_LISTEN		attr;
+	BOOLEAN				any;
+	DWORD				bytes;
+	HRESULT				hr;
+
+	hr = Allocate((UINT64) EpType);
+	if (FAILED(hr)) {
+		return hr;
+	}
+
+	hr = Bind(pAddress, EpType);
+	if (FAILED(hr)) {
+		return hr;
+	}
+
+	attr.Id = m_Id;
+	attr.Backlog = Backlog;
+
+	if (!WvDeviceIoControl(m_hFile, WV_IOCTL_EP_LISTEN, &attr, sizeof attr,
+						   &attr, sizeof attr, &bytes, NULL)) {
+		hr = HRESULT_FROM_WIN32(GetLastError());
+	}
+
+	return hr;
 }
 
 STDMETHODIMP CWVListen::
 GetRequest(IWVEndpoint* pEndpoint, OVERLAPPED* pOverlapped)
 {
-	UNREFERENCED_PARAMETER(pEndpoint);
-	UNREFERENCED_PARAMETER(pOverlapped);
+	WV_IO_EP_GET_REQUEST	req;
+	DWORD					bytes;
+	HRESULT					hr;
+
+	req.Id = m_Id;
+	req.EpId = ((CWVBase *) pEndpoint)->m_Id;
+
+	if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_GET_REQUEST,
+						  &req, sizeof req, NULL, 0, &bytes, NULL)) {
+		hr = WV_SUCCESS;
+	} else {
+		hr = HRESULT_FROM_WIN32(GetLastError());
+	}
 
-	return E_NOTIMPL;
+	return hr;
+}
+
+STDMETHODIMP CWVListen::
+Query(WV_LISTEN_ATTRIBUTES* pAttributes)
+{
+	WV_IO_EP_ATTRIBUTES	attr;
+	DWORD				bytes;
+	HRESULT				hr;
+
+	if (!WvDeviceIoControl(m_hFile, WV_IOCTL_EP_QUERY, &m_Id, sizeof m_Id,
+						   &attr, sizeof attr, &bytes, NULL)) {
+		return HRESULT_FROM_WIN32(GetLastError());
+	}
+
+	RtlCopyMemory(&pAttributes->LocalAddress, &attr.LocalAddress,
+				  sizeof pAttributes->LocalAddress);
+	RtlCopyMemory(&pAttributes->Device, &attr.Device, sizeof pAttributes->Device);
+	pAttributes->Backlog = attr.Param.Backlog;
+
+	return WV_SUCCESS;
 }
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/core/winverbs/user/wv_pd.cpp branches\winverbs/core/winverbs/user/wv_pd.cpp
--- trunk/core/winverbs/user/wv_pd.cpp	2008-07-18 12:27:20.946519800 -0700
+++ branches\winverbs/core/winverbs/user/wv_pd.cpp	2008-12-01 23:16:23.475375000 -0800
@@ -97,9 +97,9 @@ CWVProtectionDomain::~CWVProtectionDomai
 	DWORD	bytes;
 	HRESULT	hr;
 
-	if (m_Id != NULL) {
+	if (m_Id != 0) {
 		m_pVerbs->pre_deallocate_pd(m_hVerbsPd);
-		hr = WvDeviceIoControl(m_hFile, WV_IOCTL_PD_ALLOCATE, &m_Id, sizeof m_Id,
+		hr = WvDeviceIoControl(m_hFile, WV_IOCTL_PD_DEALLOCATE, &m_Id, sizeof m_Id,
 							   NULL, 0, &bytes, NULL) ?
 							   WV_SUCCESS : HRESULT_FROM_WIN32(GetLastError());
 		m_pVerbs->post_deallocate_pd(m_hVerbsPd, (ib_api_status_t) hr);
@@ -271,7 +271,7 @@ CWVMemoryWindow::~CWVMemoryWindow()
 	DWORD	bytes;
 	HRESULT	hr;
 
-	if (m_Id != NULL) {
+	if (m_Id != 0) {
 		m_pVerbs->pre_destroy_mw(m_hVerbsMw);
 		hr = WvDeviceIoControl(m_hFile, WV_IOCTL_MW_DEALLOCATE,
 							   &m_Id, sizeof m_Id, NULL, 0, &bytes, NULL) ?
@@ -384,7 +384,7 @@ CWVAddressHandle::~CWVAddressHandle()
 	HRESULT			hr;
 	ib_api_status_t	stat;
 
-	if (m_Id != NULL) {
+	if (m_Id != 0) {
 		stat = m_pVerbs->pre_destroy_av(m_hVerbsAh);
 		if (stat != IB_VERBS_PROCESSING_DONE) {
 			hr = WvDeviceIoControl(m_hFile, WV_IOCTL_AH_DESTROY,
@@ -424,16 +424,17 @@ Release(void)
 STDMETHODIMP CWVAddressHandle::
 ConvertAv(ib_av_attr_t *pVerbsAv, WV_ADDRESS_VECTOR *pAv)
 {
+	DWORD index;
 	HRESULT hr;
 
 	pVerbsAv->grh_valid = pAv->Route.Valid;
 	if (pVerbsAv->grh_valid) {
-		hr = m_pPd->m_pDevice->FindGidIndex(pAv->PortNumber, &pAv->Route.SGid,
-											&pVerbsAv->grh.resv1);
+		hr = m_pPd->m_pDevice->FindGid(pAv->PortNumber, &pAv->Route.SGid, &index);
 		if (FAILED(hr)) {
 			return hr;
 		}
 
+		pVerbsAv->grh.resv1 = (UINT16) index;
 		pVerbsAv->grh.ver_class_flow =
 			_byteswap_ulong(_byteswap_ulong(pAv->Route.FlowLabel) |
 							 (pAv->Route.TrafficClass << 20));
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/core/winverbs/user/wv_provider.cpp
branches\winverbs/core/winverbs/user/wv_provider.cpp
--- trunk/core/winverbs/user/wv_provider.cpp	2008-07-17 16:16:36.515625000 -0700
+++ branches\winverbs/core/winverbs/user/wv_provider.cpp	2008-12-01 13:05:16.214438800 -0800
@@ -28,12 +28,12 @@
  */
 
 #include <iba\ib_al.h>
+#include <iba\ib_at_ioctl.h>
 
 #include "wv_memory.h"
 #include "wv_provider.h"
 #include "wv_device.h"
 #include "wv_ep.h"
-#include "wv_listen.h"
 #include "wv_ioctl.h"
 
 CWVProvider::CWVProvider()
@@ -45,7 +45,9 @@ CWVProvider::CWVProvider()
 CWVProvider::~CWVProvider()
 {
 	CloseHandle(m_hFile);
-	InterlockedDecrement(&WvRef);
+	if (InterlockedDecrement(&WvRef) == 0) {
+		WSACleanup();
+	}
 }
 
 STDMETHODIMP CWVProvider::
@@ -132,12 +134,44 @@ out:
 }
 
 STDMETHODIMP CWVProvider::
-QueryAddressList(WV_ADDRESS_LIST* pAddressList, SIZE_T* pBufferSize)
+TranslateAddress(SOCKADDR* pAddress, WV_DEVICE_ADDRESS* pDeviceAddress)
 {
-	UNREFERENCED_PARAMETER(pAddressList);
-	UNREFERENCED_PARAMETER(pBufferSize);
+	HANDLE hIbat;
+	IOCTL_IBAT_IP_TO_PORT_IN addr;
+	IBAT_PORT_RECORD port;
+	DWORD bytes;
+	HRESULT hr;
+
+	hIbat = CreateFileW(IBAT_WIN32_NAME, GENERIC_READ | GENERIC_WRITE,
+						FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+						OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+	if (hIbat == INVALID_HANDLE_VALUE) {
+		return HRESULT_FROM_WIN32(GetLastError());
+	}
+
+	addr.Version = IBAT_IOCTL_VERSION;
+	if (pAddress->sa_family == AF_INET) {
+		addr.Address.IpVersion = 4;
+		RtlCopyMemory(addr.Address.Address + 12,
+					  &((SOCKADDR_IN *)pAddress)->sin_addr, 4);
+	} else {
+		addr.Address.IpVersion = 6;
+		RtlCopyMemory(addr.Address.Address,
+					  &((SOCKADDR_IN6 *)pAddress)->sin6_addr, 16);
+	}
+
+	if (DeviceIoControl(hIbat, IOCTL_IBAT_IP_TO_PORT,
+						&addr, sizeof addr, &port, sizeof port, &bytes, NULL)) {
+		hr = WV_SUCCESS;
+		pDeviceAddress->DeviceGuid = port.CaGuid;
+		pDeviceAddress->Pkey = port.PKey;
+		pDeviceAddress->PortNumber = port.PortNum;
+	} else {
+		hr = HRESULT_FROM_WIN32(GetLastError());
+	}
 
-	return E_NOTIMPL;
+	CloseHandle(hIbat);
+	return hr;
 }
 
 STDMETHODIMP CWVProvider::
@@ -157,9 +191,3 @@ CreateDatagramEndpoint(IWVDatagramEndpoi
 {
 	return CWVDatagramEndpoint::CreateInstance(this, ppDatagramEndpoint);
 }
-
-STDMETHODIMP CWVProvider::
-CreateListen(const struct sockaddr* pAddress, SIZE_T Backlog, IWVListen** ppListen)
-{
-	return CWVListen::CreateInstance(this, pAddress, Backlog, ppListen);
-}
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/core/winverbs/user/wv_provider.h
branches\winverbs/core/winverbs/user/wv_provider.h
--- trunk/core/winverbs/user/wv_provider.h	2008-07-17 16:02:45.406250000 -0700
+++ branches\winverbs/core/winverbs/user/wv_provider.h	2008-12-01 13:04:01.212232800 -0800
@@ -49,23 +49,30 @@ public:
 	STDMETHODIMP_(HANDLE) GetFileHandle();
 	STDMETHODIMP QueryDeviceList(NET64* pGuidList, SIZE_T* pBufferSize);
 	STDMETHODIMP QueryDevice(NET64 Guid, WV_DEVICE_ATTRIBUTES* pAttributes);
-	STDMETHODIMP QueryAddressList(WV_ADDRESS_LIST* pAddressList, SIZE_T* pBufferSize);
+	STDMETHODIMP TranslateAddress(SOCKADDR* pAddress,
+								  WV_DEVICE_ADDRESS* pDeviceAddress);
 
 	STDMETHODIMP OpenDevice(NET64 Guid, IWVDevice** ppDevice);
 
 	STDMETHODIMP CreateConnectEndpoint(IWVConnectEndpoint** ppConnectEndpoint);
 	STDMETHODIMP CreateDatagramEndpoint(IWVDatagramEndpoint** ppDatagramEndpoint);
-	STDMETHODIMP CreateListen(const struct sockaddr* pAddress,
-							  SIZE_T backlog, IWVListen** ppListen);
 
 	CWVProvider();
 	~CWVProvider();
 	void Delete() {delete this;}
 	static STDMETHODIMP CreateInstance(IWVProvider** ppProvider)
 	{
+		WSADATA wsadata;
 		HRESULT hr;
 		CWVProvider *wv;
 
+		if (WvRef == 0) {
+			hr = WSAStartup(MAKEWORD(2, 2), &wsadata);
+			if (FAILED(hr)) {
+				return hr;
+			}
+		}
+
 		wv = new CWVProvider;
 		if (wv == NULL) {
 			hr = WV_NO_MEMORY;
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/core/winverbs/user/wv_qp.cpp branches\winverbs/core/winverbs/user/wv_qp.cpp
--- trunk/core/winverbs/user/wv_qp.cpp	2008-07-18 12:47:20.144325800 -0700
+++ branches\winverbs/core/winverbs/user/wv_qp.cpp	2008-11-25 11:43:16.625000000 -0800
@@ -194,6 +194,7 @@ static void WvIoConvertQpAttr(WV_IO_QP_A
 
 	pIoAttr->AccessFlags = (UINT8) pAttr->AccessFlags;
 	pIoAttr->QpFlags = (UINT8) pAttr->QpFlags;
+	RtlZeroMemory(pIoAttr->Reserved, sizeof pIoAttr->Reserved);
 }
 
 CWVQueuePair::CWVQueuePair(CWVProtectionDomain *pPd)
@@ -298,7 +299,7 @@ CWVQueuePair::~CWVQueuePair()
 	DWORD	bytes;
 	HRESULT	hr;
 
-	if (m_Id != NULL) {
+	if (m_Id != 0) {
 		m_pVerbs->pre_destroy_qp(m_hVerbsQp);
 		hr = WvDeviceIoControl(m_hFile, WV_IOCTL_QP_DESTROY, &m_Id, sizeof m_Id,
 							   NULL, 0, &bytes, NULL) ?
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/core/winverbs/user/wv_srq.cpp
branches\winverbs/core/winverbs/user/wv_srq.cpp
--- trunk/core/winverbs/user/wv_srq.cpp	2008-07-16 22:31:21.187500000 -0700
+++ branches\winverbs/core/winverbs/user/wv_srq.cpp	2008-11-25 11:43:16.406250000 -0800
@@ -73,6 +73,7 @@ Create(SIZE_T MaxWr, SIZE_T MaxSge, SIZE
 	pattr->MaxSge = attr.max_sge;
 	pattr->MaxWr = attr.max_wr;
 	pattr->SrqLimit = attr.srq_limit;
+	pattr->Reserved = 0;
 	RtlCopyMemory(pattr + 1, (void *) (ULONG_PTR) verbsData.p_inout_buf,
 				  verbsData.input_size);
 
@@ -102,7 +103,7 @@ CWVSharedReceiveQueue::~CWVSharedReceive
 	DWORD	bytes;
 	HRESULT	hr;
 
-	if (m_Id != NULL) {
+	if (m_Id != 0) {
 		m_pVerbs->pre_destroy_srq(m_hVerbsSrq);
 		hr = WvDeviceIoControl(m_hFile, WV_IOCTL_SRQ_DESTROY, &m_Id, sizeof m_Id,
 							   NULL, 0, &bytes, NULL) ?
@@ -180,6 +181,7 @@ Query(SIZE_T* pMaxWr, SIZE_T* pMaxSge, S
 
 	pattr->Id.Id = m_Id;
 	pattr->Id.VerbInfo = verbsData.command;
+	pattr->Reserved = 0;
 	RtlCopyMemory(pattr + 1, (void *) (ULONG_PTR) verbsData.p_inout_buf,
 				  verbsData.input_size);
 
@@ -241,6 +243,7 @@ Modify(SIZE_T MaxWr, SIZE_T SrqLimit)
 	pattr->Id.VerbInfo = verbsData.command;
 	pattr->MaxWr = attr.max_wr;
 	pattr->SrqLimit = attr.srq_limit;
+	pattr->Reserved = 0;
 	RtlCopyMemory(pattr + 1, (void *) (ULONG_PTR) verbsData.p_inout_buf,
 				  verbsData.input_size);
 
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/inc/user/rdma/wvstatus.h branches\winverbs/inc/user/rdma/wvstatus.h
--- trunk/inc/user/rdma/wvstatus.h	2008-06-16 11:32:19.390625000 -0700
+++ branches\winverbs/inc/user/rdma/wvstatus.h	2009-01-14 16:41:53.214664100 -0800
@@ -83,6 +83,7 @@
 #define WV_DEVICE_BUSY					((HRESULT)0x80000011L)
 #define WV_NO_MORE_ENTRIES				((HRESULT)0x8000001AL)
 #define WV_IO_PENDING					((HRESULT)0x800703E5L)
+#define WV_REJECTED						((HRESULT)0x80070047L)
 #define WV_UNSUCCESSFUL					((HRESULT)0xC0000001L)
 #define WV_ACCESS_VIOLATION				((HRESULT)0xC0000005L)
 #define WV_INVALID_HANDLE				((HRESULT)0xC0000008L)





More information about the ofw mailing list