#define AL_DEVICE_NAME L"\\Device\\ibal"\r
#define ALDEV_KEY (0x3B) /* Matches FILE_DEVICE_INFINIBAND from wdm.h */\r
\r
-#define AL_IOCTL_VERSION (10)\r
+#define AL_IOCTL_VERSION (11)\r
\r
/* max number of devices with non-default pkey */\r
#define MAX_NUM_PKEY 16\r
\r
p_irp->Tail.Overlay.DriverContext[1] = NULL;\r
\r
- if( h_qp->p_irp_queue->state != NDI_CM_CONNECTING_QPR_SENT )\r
+ if( h_qp->p_irp_queue->state != NDI_CM_CONNECTING_QPR_SENT &&\r
+ h_qp->p_irp_queue->state != NDI_CM_IDLE )\r
{\r
AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
("Unexpected state: %d\n", h_qp->p_irp_queue->state) );\r
- return STATUS_CONNECTION_ABORTED;\r
+ return STATUS_CONNECTION_ACTIVE;\r
}\r
\r
/* Get a CEP and bind it to the QP. */\r
ual_ndi_req_cm_ioctl_in_t *p_req = \r
(ual_ndi_req_cm_ioctl_in_t*)cl_ioctl_in_buf( p_irp );\r
ib_qp_handle_t h_qp = (ib_qp_handle_t)p_irp->Tail.Overlay.DriverContext[0];\r
+ ib_gid_pair_t gids;\r
\r
AL_ENTER( AL_DBG_NDI );\r
\r
return STATUS_CONNECTION_ACTIVE;\r
}\r
\r
+ gids.src_gid = p_req->path.sgid;\r
+ gids.dest_gid = p_req->path.dgid;\r
+\r
query_req.query_type = IB_QUERY_PATH_REC_BY_GIDS;\r
- query_req.p_query_input = &p_req->gids;\r
+ query_req.p_query_input = &gids;\r
query_req.port_guid = p_req->guid;\r
query_req.timeout_ms = g_sa_timeout;\r
query_req.retry_cnt = g_sa_retries;\r
\r
AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,\r
("Query for path from %I64x to %I64x\n",\r
- p_req->guid, ib_gid_get_guid( &p_req->gids.dest_gid )) );\r
+ p_req->guid, ib_gid_get_guid( &p_req->path.dgid )) );\r
\r
ref_al_obj( &h_qp->obj ); /* take path query reference */\r
status = ib_query( qp_get_al( h_qp ), &query_req, &h_qp->p_irp_queue->h_query );\r
)\r
{\r
NTSTATUS status;\r
+ ual_ndi_req_cm_ioctl_in_t *p_req = \r
+ (ual_ndi_req_cm_ioctl_in_t*)cl_ioctl_in_buf( p_irp );\r
\r
AL_ENTER( AL_DBG_NDI );\r
\r
p_irp->Tail.Overlay.DriverContext[0] = (ib_qp_t*)h_qp;\r
\r
- status = IoCsqInsertIrpEx(\r
- &h_qp->p_irp_queue->csq,\r
- p_irp,\r
- NULL,\r
- (VOID*)(ULONG_PTR)NDI_CM_CONNECTING_QPR_SENT\r
- );\r
+ if( p_req->path.dlid != 0 )\r
+ {\r
+ /* fix packet life */\r
+ uint8_t pkt_life = ib_path_rec_pkt_life( &p_req->path ) + g_pkt_life_modifier;\r
+ if( pkt_life > 0x1F )\r
+ pkt_life = 0x1F;\r
+\r
+ p_req->path.pkt_life &= IB_PATH_REC_SELECTOR_MASK;\r
+ p_req->path.pkt_life |= pkt_life;\r
+\r
+ p_irp->Tail.Overlay.DriverContext[1] = &p_req->path;\r
+ status = IoCsqInsertIrpEx(\r
+ &h_qp->p_irp_queue->csq,\r
+ p_irp,\r
+ NULL,\r
+ (VOID*)(ULONG_PTR)NDI_CM_CONNECTING_REQ_SENT\r
+ );\r
+ }\r
+ else\r
+ {\r
+ status = IoCsqInsertIrpEx(\r
+ &h_qp->p_irp_queue->csq,\r
+ p_irp,\r
+ NULL,\r
+ (VOID*)(ULONG_PTR)NDI_CM_CONNECTING_QPR_SENT\r
+ );\r
+ }\r
if( status == STATUS_SUCCESS )\r
status = STATUS_PENDING;\r
\r
// IBAT: InfiniBand Address Translation\r
//\r
// Description:\r
-// Maps remote IP addresses (IPv4 and IPv6) to the remote GID.\r
+// Maps source & remote IP addresses (IPv4 and IPv6) to a path record.\r
//\r
// The mapping requires two steps:\r
// 1. Mapping the remote IP address to the remote Ethernet MAC address\r
-// 2. Retrieve the remote GID given the remote Ethernet MAC address\r
-// from IPoIB\r
+// 2. Retrieve the path given the remote Ethernet MAC address from IPoIB\r
//\r
// The first step is accomplished as follows on Windows Server 2008:\r
// 1. Lookup the desired MAC from the OS using GetIpNetEntry2\r
// 3. If the remote IP isn't found, resolve the remote IP address using\r
// SendARP.\r
//\r
-// The second step is accomplished by asking IPoIB for the remote GID\r
-// given the remote MAC.\r
+// The second step is accomplished by asking IPoIB for the path\r
+// given the remote MAC. IPoIB creates the path internally without going to\r
+// the SA.\r
\r
#pragma warning( push, 3 )\r
#include <windows.h>\r
#include <iphlpapi.h>\r
#include "iba/ib_at_ioctl.h"\r
\r
+C_ASSERT( sizeof(IBAT_PATH_BLOB) == sizeof(ib_path_rec_t) );\r
\r
namespace IBAT\r
{\r
Resolve(\r
__in const struct sockaddr* pSrcAddr,\r
__in const struct sockaddr* pDestAddr,\r
- __out IN6_ADDR* pSrcGid,\r
- __out IN6_ADDR* pDestGid,\r
- __out USHORT* pPkey\r
+ __out IBAT_PATH_BLOB* pPath\r
)\r
{\r
if( pSrcAddr->sa_family != pDestAddr->sa_family )\r
return HRESULT_FROM_WIN32( GetLastError() );\r
\r
// Check for loopback.\r
- if( fLoopback )\r
- {\r
- *pSrcGid = x_DefaultGid;\r
- RtlCopyMemory(\r
- &pSrcGid->u.Byte[8],\r
- &port_out.PortGuid,\r
- sizeof(port_out.PortGuid) );\r
- *pDestGid = *pSrcGid;\r
- *pPkey = port_out.PKey;\r
- return S_OK;\r
- }\r
-\r
- NET_LUID luid;\r
- DWORD ret;\r
- do\r
+ IOCTL_IBAT_MAC_TO_PATH_IN mac_in = {0};\r
+ mac_in.Version = IBAT_IOCTL_VERSION;\r
+ mac_in.PortGuid = port_out.PortGuid;\r
+ if( !fLoopback )\r
{\r
- DWORD iIf;\r
- ret = GetBestInterfaceEx( (struct sockaddr*)pSrcAddr, &iIf );\r
- if( ret != NO_ERROR )\r
- return HRESULT_FROM_WIN32( ret );\r
-\r
- // Interface indexes are not constant, so get the LUID mapping for the\r
- // returned interface for use in the rest of the function.\r
- ret = ConvertInterfaceIndexToLuid( iIf, &luid );\r
+ NET_LUID luid;\r
+ DWORD ret;\r
+ do\r
+ {\r
+ DWORD iIf;\r
+ ret = GetBestInterfaceEx( (struct sockaddr*)pSrcAddr, &iIf );\r
+ if( ret != NO_ERROR )\r
+ return HRESULT_FROM_WIN32( ret );\r
\r
- } while( ret != NO_ERROR );\r
+ // Interface indexes are not constant, so get the LUID mapping for the\r
+ // returned interface for use in the rest of the function.\r
+ ret = ConvertInterfaceIndexToLuid( iIf, &luid );\r
\r
- SOCKADDR_INET src;\r
- MIB_IPNET_ROW2 net = {0};\r
- net.InterfaceLuid = luid;\r
- switch( pDestAddr->sa_family )\r
- {\r
- case AF_INET:\r
- net.Address.si_family = src.si_family = AF_INET;\r
- net.Address.Ipv4 = *(struct sockaddr_in*)pDestAddr;\r
- src.Ipv4 = *(struct sockaddr_in*)pSrcAddr;\r
- break;\r
+ } while( ret != NO_ERROR );\r
\r
- case AF_INET6:\r
- net.Address.si_family = src.si_family = AF_INET6;\r
- net.Address.Ipv6 = *(struct sockaddr_in6*)pDestAddr;\r
- src.Ipv6 = *(struct sockaddr_in6*)pSrcAddr;\r
- break;\r
+ SOCKADDR_INET src;\r
+ MIB_IPNET_ROW2 net = {0};\r
+ net.InterfaceLuid = luid;\r
+ switch( pDestAddr->sa_family )\r
+ {\r
+ case AF_INET:\r
+ net.Address.si_family = src.si_family = AF_INET;\r
+ net.Address.Ipv4 = *(struct sockaddr_in*)pDestAddr;\r
+ src.Ipv4 = *(struct sockaddr_in*)pSrcAddr;\r
+ break;\r
\r
- default:\r
- return E_INVALIDARG;\r
- }\r
+ case AF_INET6:\r
+ net.Address.si_family = src.si_family = AF_INET6;\r
+ net.Address.Ipv6 = *(struct sockaddr_in6*)pDestAddr;\r
+ src.Ipv6 = *(struct sockaddr_in6*)pSrcAddr;\r
+ break;\r
\r
- bool fRetry = true;\r
-retry:\r
- ret = GetIpNetEntry2( &net );\r
- if( ret != NO_ERROR )\r
- return HRESULT_FROM_WIN32( ret );\r
+ default:\r
+ return E_INVALIDARG;\r
+ }\r
\r
- switch( net.State )\r
- {\r
- default:\r
- case NlnsUnreachable:\r
- ret = ResolveIpNetEntry2( &net, &src );\r
- if( ret == ERROR_BAD_NET_NAME && fRetry )\r
+ bool fRetry = true;\r
+ retry:\r
+ ret = GetIpNetEntry2( &net );\r
+ if( ret == ERROR_NOT_FOUND )\r
{\r
- fRetry = false;\r
- goto retry;\r
+ net.State = NlnsUnreachable;\r
}\r
else if( ret != NO_ERROR )\r
{\r
return HRESULT_FROM_WIN32( ret );\r
}\r
- break;\r
\r
- case NlnsReachable:\r
- case NlnsPermanent:\r
- break;\r
+ switch( net.State )\r
+ {\r
+ default:\r
+ case NlnsUnreachable:\r
+ ret = ResolveIpNetEntry2( &net, &src );\r
+ if( ret == ERROR_BAD_NET_NAME && fRetry )\r
+ {\r
+ fRetry = false;\r
+ goto retry;\r
+ }\r
+ else if( ret != NO_ERROR )\r
+ {\r
+ return HRESULT_FROM_WIN32( ret );\r
+ }\r
+ break;\r
\r
- case NlnsIncomplete:\r
- return E_PENDING;\r
- }\r
+ case NlnsReachable:\r
+ case NlnsPermanent:\r
+ break;\r
\r
- if( net.PhysicalAddressLength > 6 )\r
- return E_UNEXPECTED;\r
+ case NlnsIncomplete:\r
+ return E_PENDING;\r
+ }\r
\r
- IOCTL_IBAT_MAC_TO_GID_IN mac_in;\r
- mac_in.Version = IBAT_IOCTL_VERSION;\r
- mac_in.PortGuid = port_out.PortGuid;\r
- RtlCopyMemory( mac_in.DestMac, net.PhysicalAddress, IBAT_MAC_LEN );\r
+ if( net.PhysicalAddressLength > 6 )\r
+ return E_UNEXPECTED;\r
+\r
+ RtlCopyMemory( mac_in.DestMac, net.PhysicalAddress, IBAT_MAC_LEN );\r
+ }\r
\r
- fSuccess = DeviceIoControl( hIbatDev, IOCTL_IBAT_MAC_TO_GID,\r
- &mac_in, sizeof(mac_in), pDestGid, sizeof(*pDestGid), &size, NULL );\r
+ fSuccess = DeviceIoControl( hIbatDev, IOCTL_IBAT_MAC_TO_PATH,\r
+ &mac_in, sizeof(mac_in), pPath, sizeof(*pPath), &size, NULL );\r
if( !fSuccess )\r
return HRESULT_FROM_WIN32( GetLastError() );\r
\r
- // Use the same subnet prefix as the destination.\r
- *pSrcGid = *pDestGid;\r
- RtlCopyMemory( &pSrcGid->u.Byte[8], &port_out.PortGuid, sizeof(port_out.PortGuid) );\r
- *pPkey = port_out.PKey;\r
return S_OK;\r
}\r
#else // Back compatibility with Windows Server 2003\r
Resolve(\r
__in const struct sockaddr* pSrcAddr,\r
__in const struct sockaddr* pDestAddr,\r
- __out IN6_ADDR* pSrcGid,\r
- __out IN6_ADDR* pDestGid,\r
- __out USHORT* pPkey\r
+ __out IBAT_PATH_BLOB* pPath\r
)\r
{\r
if( pDestAddr->sa_family != AF_INET )\r
return HRESULT_FROM_WIN32( GetLastError() );\r
\r
// Check for loopback.\r
- if( ((struct sockaddr_in*)pDestAddr)->sin_addr.s_addr ==\r
- ((struct sockaddr_in*)pSrcAddr)->sin_addr.s_addr )\r
- {\r
- *pSrcGid = x_DefaultGid;\r
- RtlCopyMemory(\r
- &pSrcGid->u.Byte[8],\r
- &port_out.PortGuid,\r
- sizeof(port_out.PortGuid) );\r
- *pDestGid = *pSrcGid;\r
- *pPkey = port_out.PKey;\r
- return S_OK;\r
- }\r
-\r
- IOCTL_IBAT_MAC_TO_GID_IN mac_in;\r
+ IOCTL_IBAT_MAC_TO_GID_IN mac_in = {0};\r
mac_in.Version = IBAT_IOCTL_VERSION;\r
mac_in.PortGuid = port_out.PortGuid;\r
- HRESULT hr = GetDestMac( (struct sockaddr_in*)pDestAddr, mac_in.DestMac );\r
- if( FAILED( hr ) )\r
+\r
+ if( ((struct sockaddr_in*)pDestAddr)->sin_addr.s_addr !=\r
+ ((struct sockaddr_in*)pSrcAddr)->sin_addr.s_addr )\r
{\r
- ULONG len = sizeof(mac_in.DestMac);\r
- DWORD ret = SendARP(\r
- ((struct sockaddr_in*)pDestAddr)->sin_addr.s_addr,\r
- ((struct sockaddr_in*)pSrcAddr)->sin_addr.s_addr,\r
- (ULONG*)mac_in.DestMac,\r
- &len\r
- );\r
- if( ret != NO_ERROR )\r
- return HRESULT_FROM_WIN32( ret );\r
+ HRESULT hr = GetDestMac( (struct sockaddr_in*)pDestAddr, mac_in.DestMac );\r
+ if( FAILED( hr ) )\r
+ {\r
+ ULONG len = sizeof(mac_in.DestMac);\r
+ DWORD ret = SendARP(\r
+ ((struct sockaddr_in*)pDestAddr)->sin_addr.s_addr,\r
+ ((struct sockaddr_in*)pSrcAddr)->sin_addr.s_addr,\r
+ (ULONG*)mac_in.DestMac,\r
+ &len\r
+ );\r
+ if( ret != NO_ERROR )\r
+ return HRESULT_FROM_WIN32( ret );\r
+ }\r
}\r
\r
- fSuccess = DeviceIoControl( hIbatDev, IOCTL_IBAT_MAC_TO_GID,\r
- &mac_in, sizeof(mac_in), pDestGid, sizeof(*pDestGid), &size, NULL );\r
+ fSuccess = DeviceIoControl( hIbatDev, IOCTL_IBAT_MAC_TO_PATH,\r
+ &mac_in, sizeof(mac_in), pPath, sizeof(*pPath), &size, NULL );\r
if( !fSuccess )\r
return HRESULT_FROM_WIN32( GetLastError() );\r
\r
- // Use the same subnet prefix as the destination.\r
- *pSrcGid = *pDestGid;\r
- RtlCopyMemory( &pSrcGid->u.Byte[8], &port_out.PortGuid, sizeof(port_out.PortGuid) );\r
- *pPkey = port_out.PKey;\r
return S_OK;\r
}\r
\r
IbatResolve(\r
__in const struct sockaddr* pSrcAddr,\r
__in const struct sockaddr* pDestAddr,\r
- __out IN6_ADDR* pSrcGid,\r
- __out IN6_ADDR* pDestGid,\r
- __out USHORT* pPkey\r
+ __out IBAT_PATH_BLOB* pPath\r
)\r
{\r
- return IBAT::Resolve( pSrcAddr, pDestAddr, pSrcGid, pDestGid, pPkey );\r
+ return IBAT::Resolve( pSrcAddr, pDestAddr, pPath );\r
}\r
\r
} /* extern "C" */\r
*/\r
typedef struct _ual_ndi_req_cm_ioctl_in\r
{\r
- ib_gid_pair_t gids;\r
+ ib_path_rec_t path;\r
uint64_t h_qp;\r
net64_t guid;\r
uint16_t dst_port;\r
- uint16_t pkey;\r
uint8_t resp_res;\r
uint8_t init_depth;\r
uint8_t prot;\r
* dst_port\r
* Destination port number.\r
*\r
-* pkey\r
-* Partition key.\r
+* path\r
+* Path record for the connection.\r
*\r
* resp_res\r
* Responder resources for the QP.\r
} IOCTL_IBAT_IP_TO_PORT_OUT;\r
\r
\r
+/** This IRP is used to convert a remote MAC addresses to a remote GID */\r
+#define IOCTL_IBAT_MAC_TO_PATH IOCTL_IBAT( 5 )\r
+\r
+typedef struct _IOCTL_IBAT_MAC_TO_PATH_IN\r
+{\r
+ ULONG Version;\r
+ UINT64 PortGuid;\r
+ UCHAR DestMac[IBAT_MAC_LEN];\r
+\r
+} IOCTL_IBAT_MAC_TO_PATH_IN;\r
+\r
+typedef struct _IOCTL_IBAT_MAC_TO_PATH_OUT\r
+{\r
+ ib_path_rec_t Path;\r
+\r
+} IOCTL_IBAT_MAC_TO_PATH_OUT;\r
+\r
+\r
#define IBAT_DEV_NAME L"\\Device\\ibat"\r
#define IBAT_DOS_DEV_NAME L"\\DosDevices\\Global\\ibat"\r
#define IBAT_WIN32_NAME L"\\\\.\\ibat"\r
#include <winsock2.h>\r
#include <ws2tcpip.h>\r
\r
+typedef struct _IBAT_PATH_BLOB\r
+{\r
+ UINT8 byte[64];\r
+\r
+} IBAT_PATH_BLOB;\r
+\r
#ifdef __cplusplus\r
namespace IBAT\r
{\r
Resolve(\r
__in const struct sockaddr* pSrcAddr,\r
__in const struct sockaddr* pDestAddr,\r
- __out IN6_ADDR* pSrcGid,\r
- __out IN6_ADDR* pDestGid,\r
- __out USHORT* pPkey\r
+ __out IBAT_PATH_BLOB* pPath\r
);\r
\r
}\r
IbatResolve(\r
__in const struct sockaddr* pSrcAddr,\r
__in const struct sockaddr* pDestAddr,\r
- __out IN6_ADDR* pSrcGid,\r
- __out IN6_ADDR* pDestGid,\r
- __out USHORT* pPkey\r
+ __out IBAT_PATH_BLOB* pPath\r
);\r
\r
#endif /* __cplusplus */\r
*/\r
\r
\r
-#include "iba/ibat.h"\r
#include "stdlib.h"\r
#include "stdio.h"\r
+#include "iba/ib_types.h"\r
+#include "iba/ibat.h"\r
\r
\r
inline LONGLONG GetElapsedTime()\r
destAddr.sin_family = AF_INET;\r
destAddr.sin_addr.s_addr = inet_addr( argv[2] );\r
\r
- IN6_ADDR srcGid;\r
- IN6_ADDR destGid;\r
- USHORT pkey;\r
-\r
+ ib_path_rec_t path;\r
HRESULT hr = IBAT::Resolve(\r
(struct sockaddr*)&srcAddr,\r
(struct sockaddr*)&destAddr,\r
- &srcGid,\r
- &destGid,\r
- &pkey\r
+ (IBAT_PATH_BLOB*)&path\r
);\r
if( FAILED( hr ) )\r
{\r
printf(\r
"I B at:\n"\r
"partition %x\n"\r
- "source GID %x:%x:%x:%x:%x:%x:%x:%x\n"\r
- "destination GID %x:%x:%x:%x:%x:%x:%x:%x\n",\r
- pkey,\r
- srcGid.u.Word[0], srcGid.u.Word[1], srcGid.u.Word[2], srcGid.u.Word[3],\r
- srcGid.u.Word[4], srcGid.u.Word[5], srcGid.u.Word[6], srcGid.u.Word[7],\r
- destGid.u.Word[0], destGid.u.Word[1], destGid.u.Word[2], destGid.u.Word[3],\r
- destGid.u.Word[4], destGid.u.Word[5], destGid.u.Word[6], destGid.u.Word[7]\r
+ "source GID %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x\n"\r
+ "destination GID %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x\n",\r
+ path.pkey,\r
+ path.sgid.raw[0], path.sgid.raw[1], path.sgid.raw[2], path.sgid.raw[3],\r
+ path.sgid.raw[4], path.sgid.raw[5], path.sgid.raw[6], path.sgid.raw[7],\r
+ path.sgid.raw[8], path.sgid.raw[9], path.sgid.raw[10], path.sgid.raw[11],\r
+ path.sgid.raw[12], path.sgid.raw[13], path.sgid.raw[14], path.sgid.raw[15],\r
+ path.dgid.raw[0], path.dgid.raw[1], path.dgid.raw[2], path.dgid.raw[3],\r
+ path.dgid.raw[4], path.dgid.raw[5], path.dgid.raw[6], path.dgid.raw[7],\r
+ path.dgid.raw[8], path.dgid.raw[9], path.dgid.raw[10], path.dgid.raw[11],\r
+ path.dgid.raw[12], path.dgid.raw[13], path.dgid.raw[14], path.dgid.raw[15]\r
);\r
\r
LONGLONG StartTime = GetElapsedTime();\r
HRESULT hr = IBAT::Resolve(\r
(struct sockaddr*)&srcAddr,\r
(struct sockaddr*)&destAddr,\r
- &srcGid,\r
- &destGid,\r
- &pkey\r
+ (IBAT_PATH_BLOB*)&path\r
);\r
if( FAILED( hr ) )\r
{\r
return status;\r
}\r
p_endpt->h_mcast = p_mcast_rec->h_mcast;\r
+ p_endpt->dlid = p_mcast_rec->p_member_rec->mlid;\r
\r
IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
return IB_SUCCESS;\r
{\r
ib_api_status_t status;\r
ipoib_port_t *p_port;\r
- ib_query_req_t query;\r
- ib_user_query_t info;\r
- ib_path_rec_t path;\r
+ ib_av_attr_t av_attr;\r
+ net32_t flow_lbl;\r
\r
IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
\r
return NDIS_STATUS_SUCCESS;\r
}\r
\r
- if( p_endpt->h_query ||\r
- p_endpt->qpn == CL_HTON32(0x00FFFFFF) )\r
+ if( p_endpt->qpn == CL_HTON32(0x00FFFFFF) )\r
{\r
+ /*\r
+ * Handle a race between the mcast callback and a receive/send. The QP\r
+ * is joined to the MC group before the MC callback is received, so it\r
+ * can receive packets, and NDIS can try to respond. We need to delay\r
+ * a response until the MC callback runs and sets the AV.\r
+ */\r
ipoib_endpt_deref( p_endpt );\r
IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
return NDIS_STATUS_PENDING;\r
}\r
\r
- /* This is the first packet for this endpoint. Query the SA. */\r
+ /* This is the first packet for this endpoint. Create the AV. */\r
p_port = __endpt_parent( p_endpt );\r
\r
- IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
-\r
- info.method = IB_MAD_METHOD_GETTABLE;\r
- info.attr_id = IB_MAD_ATTR_PATH_RECORD;\r
- info.attr_size = sizeof(ib_path_rec_t);\r
- info.comp_mask = IB_PR_COMPMASK_DGID | IB_PR_COMPMASK_SGID |\r
- IB_PR_COMPMASK_REVERSIBLE | IB_PR_COMPMASK_NUM_PATH;\r
- info.p_attr = &path;\r
-\r
- cl_memclr( &path, sizeof(ib_path_rec_t) );\r
- path.dgid = p_endpt->dgid;\r
- ib_gid_set_default( &path.sgid, p_port->p_adapter->guids.port_guid.guid );\r
- path.num_path = 0x1;\r
-\r
- cl_memclr( &query, sizeof(ib_query_req_t) );\r
- query.query_type = IB_QUERY_USER_DEFINED;\r
- query.p_query_input = &info;\r
- query.port_guid = p_port->p_adapter->guids.port_guid.guid;\r
- query.timeout_ms = p_port->p_adapter->params.sa_timeout;\r
- query.retry_cnt = p_port->p_adapter->params.sa_retry_cnt;\r
-\r
- query.query_context = p_endpt;\r
- query.pfn_query_cb = __path_query_cb;\r
-\r
- status = p_port->p_adapter->p_ifc->query(\r
- p_port->p_adapter->h_al, &query, &p_endpt->h_query );\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ENDPT,\r
- ("ib_query for path returned %s\n", \r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- ipoib_endpt_deref( p_endpt );\r
- /* Flag the adapter as hung. */\r
- p_port->p_adapter->hung = TRUE;\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
- return NDIS_STATUS_PENDING;\r
-}\r
-\r
-\r
-static void\r
-__path_query_cb(\r
- IN ib_query_rec_t *p_query_rec )\r
-{\r
- ib_api_status_t status;\r
- ipoib_endpt_t *p_endpt;\r
- ipoib_port_t *p_port;\r
- ib_av_attr_t av_attr;\r
- ib_path_rec_t *p_path;\r
- net32_t flow_lbl;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
-\r
- p_endpt = (ipoib_endpt_t*)p_query_rec->query_context;\r
- p_port = __endpt_parent( p_endpt );\r
-\r
- cl_obj_lock( &p_endpt->obj );\r
- p_endpt->h_query = NULL;\r
- if( p_endpt->obj.state == CL_DESTROYING )\r
- {\r
- cl_obj_unlock( &p_endpt->obj );\r
- ipoib_endpt_deref( p_endpt );\r
- if( p_query_rec->p_result_mad )\r
- p_port->p_adapter->p_ifc->put_mad( p_query_rec->p_result_mad );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Endpoint destroying, aborting.\n") );\r
- return;\r
- }\r
- cl_obj_unlock( &p_endpt->obj );\r
-\r
- if( p_query_rec->status != IB_SUCCESS || !p_query_rec->result_cnt )\r
- {\r
- p_port->p_adapter->hung = TRUE;\r
- ipoib_endpt_deref( p_endpt );\r
- if( p_query_rec->p_result_mad )\r
- p_port->p_adapter->p_ifc->put_mad( p_query_rec->p_result_mad );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Path query failed with %s\n",\r
- p_port->p_adapter->p_ifc->get_err_str( p_query_rec->status )) );\r
- return;\r
- }\r
-\r
- p_path = ib_get_query_path_rec( p_query_rec->p_result_mad, 0 );\r
-\r
cl_memclr( &av_attr, sizeof(ib_av_attr_t) );\r
\r
av_attr.port_num = p_port->port_num;\r
\r
- av_attr.sl = ib_path_rec_sl( p_path );\r
- av_attr.dlid = p_path->dlid;\r
+ ib_member_get_sl_flow_hop(\r
+ p_port->ib_mgr.bcast_rec.sl_flow_hop,\r
+ &av_attr.sl,\r
+ &flow_lbl,\r
+ &av_attr.grh.hop_limit\r
+ );\r
+\r
+ av_attr.dlid = p_endpt->dlid;\r
\r
/*\r
* We always send the GRH so that we preferably lookup endpoints\r
* for which there is no match, something that doesn't work when\r
* using LIDs only.\r
*/\r
- flow_lbl = ib_path_rec_flow_lbl( p_path );\r
av_attr.grh_valid = TRUE;\r
av_attr.grh.ver_class_flow = ib_grh_set_ver_class_flow(\r
- 6, p_path->tclass, flow_lbl );\r
+ 6, p_port->ib_mgr.bcast_rec.tclass, flow_lbl );\r
av_attr.grh.resv1 = 0;\r
av_attr.grh.resv2 = 0;\r
- av_attr.grh.hop_limit = ib_path_rec_hop_limit( p_path );\r
- av_attr.grh.src_gid = p_path->sgid;\r
- av_attr.grh.dest_gid = p_path->dgid;\r
- \r
- cl_obj_lock( &p_port->obj );\r
- if( !p_endpt->dlid )\r
- {\r
- cl_map_item_t *p_qitem;\r
+ ib_gid_set_default( &av_attr.grh.src_gid, p_port->p_adapter->guids.port_guid.guid );\r
+ av_attr.grh.dest_gid = p_endpt->dgid;\r
\r
- /* This is a subnet local endpoint that does not have its LID set. */\r
- p_endpt->dlid = p_path->dlid;\r
- /*\r
- * Insert the item in the LID map so that locally routed unicast\r
- * traffic will resolve it properly.\r
- */\r
- p_qitem = cl_qmap_insert( &p_port->endpt_mgr.lid_endpts,\r
- p_endpt->dlid, &p_endpt->lid_item );\r
- CL_ASSERT( p_qitem == &p_endpt->lid_item );\r
- }\r
- cl_obj_unlock( &p_port->obj );\r
- av_attr.static_rate = ib_path_rec_rate( p_path );\r
+ av_attr.static_rate = p_port->ib_mgr.bcast_rec.rate;\r
av_attr.path_bits = 0;\r
\r
- /* Done with the path record. Release the MAD. */\r
- p_port->p_adapter->p_ifc->put_mad( p_query_rec->p_result_mad );\r
-\r
/* Create the AV. */\r
status = p_port->p_adapter->p_ifc->create_av(\r
p_port->ib_mgr.h_pd, &av_attr, &p_endpt->h_av );\r
IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
("ib_create_av failed with %s\n", \r
p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- return;\r
+ return NDIS_STATUS_FAILURE;\r
}\r
\r
- /* Try to send all pending sends. */\r
- ipoib_port_resume( p_port );\r
-\r
- /* Release the reference taken for the SA query. */\r
- ipoib_endpt_deref( p_endpt );\r
IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+ return NDIS_STATUS_SUCCESS;\r
}\r
}\r
\r
\r
+static NTSTATUS\r
+__ibat_mac_to_path(\r
+ IN IRP *pIrp,\r
+ IN IO_STACK_LOCATION *pIoStack )\r
+{\r
+ NTSTATUS status = STATUS_INVALID_PARAMETER;\r
+ IOCTL_IBAT_MAC_TO_PATH_IN *pIn;\r
+ IOCTL_IBAT_MAC_TO_PATH_OUT *pOut;\r
+ KLOCK_QUEUE_HANDLE hdl;\r
+ cl_list_item_t *pItem;\r
+ ipoib_adapter_t *pAdapter;\r
+\r
+ IPOIB_ENTER(IPOIB_DBG_IOCTL);\r
+\r
+ if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=\r
+ sizeof(IOCTL_IBAT_MAC_TO_PATH_IN) )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Invalid input buffer size.\n") );\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+ \r
+ if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength !=\r
+ sizeof(IOCTL_IBAT_MAC_TO_PATH_OUT) )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Invalid output buffer size.\n") );\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+\r
+ pIn = pIrp->AssociatedIrp.SystemBuffer;\r
+ pOut = pIrp->AssociatedIrp.SystemBuffer;\r
+\r
+ if( pIn->Version != IBAT_IOCTL_VERSION )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Invalid version.\n") );\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+\r
+ KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+\r
+ for( pItem = cl_qlist_head( &g_ipoib.adapter_list );\r
+ pItem != cl_qlist_end( &g_ipoib.adapter_list );\r
+ pItem = cl_qlist_next( pItem ) )\r
+ {\r
+ pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );\r
+ if( pIn->PortGuid != pAdapter->guids.port_guid.guid )\r
+ continue;\r
+\r
+ /* Found the port - lookup the MAC. */\r
+ cl_obj_lock( &pAdapter->obj );\r
+ if( pAdapter->p_port )\r
+ {\r
+ status = ipoib_mac_to_path(\r
+ pAdapter->p_port, *(mac_addr_t*)pIn->DestMac, &pOut->Path );\r
+\r
+ if( NT_SUCCESS( status ) )\r
+ {\r
+ pIrp->IoStatus.Information =\r
+ sizeof(IOCTL_IBAT_MAC_TO_PATH_OUT);\r
+ }\r
+ }\r
+ cl_obj_unlock( &pAdapter->obj );\r
+ break;\r
+ }\r
+\r
+ KeReleaseInStackQueuedSpinLock( &hdl );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+ return status;\r
+}\r
+\r
+\r
static NTSTATUS\r
__ibat_ip_to_port(\r
IN IRP *pIrp,\r
status = __ibat_ip_to_port( pIrp, pIoStack );\r
break;\r
\r
+ case IOCTL_IBAT_MAC_TO_PATH:\r
+ IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL,\r
+ ("IOCTL_IBAT_MAC_TO_PATH received\n" ));\r
+ status = __ibat_mac_to_path( pIrp, pIoStack );\r
+ break;\r
+\r
default:\r
IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_IOCTL,\r
("unknow IOCTL code = 0x%x\n",\r
#else /* IPOIB_INLINE_RECV */\r
*pp_src = ipoib_endpt_create( &p_desc->p_buf->ib.grh.src_gid,\r
#endif /* IPOIB_INLINE_RECV */\r
- 0, p_wc->recv.ud.remote_qp );\r
+ p_wc->recv.ud.remote_lid, p_wc->recv.ud.remote_qp );\r
if( !*pp_src )\r
{\r
IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
__endpt_mgr_remove( p_port, *pp_src );\r
*pp_src = NULL;\r
}\r
+ else if ( ! ((*pp_src)->dlid)) {\r
+ /* Out of date! Destroy the endpoint and replace it. */\r
+ __endpt_mgr_remove( p_port, *pp_src );\r
+ *pp_src = NULL;\r
+ }\r
else if( ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) )\r
{\r
if( (*pp_src)->qpn !=\r
return status;\r
}\r
/*\r
- * Create the endpoint. Note that the LID is left blank and will be\r
- * resolved by a path query as needed. This is done because the\r
- * remote LID/GID from the work completion may not be the original\r
- * initiator.\r
+ * Create the endpoint.\r
*/\r
*pp_src = ipoib_endpt_create( &p_ib_arp->src_hw.gid,\r
- 0, (p_ib_arp->src_hw.flags_qpn & CL_HTON32(0x00FFFFFF)) );\r
+ p_wc->recv.ud.remote_lid, (p_ib_arp->src_hw.flags_qpn & CL_HTON32(0x00FFFFFF)) );\r
\r
if( !*pp_src )\r
{\r
while( p_port->endpt_rdr )\r
;\r
\r
+#if 0\r
+ __endpt_mgr_remove_all(p_port);\r
+#else\r
+ \r
+ NdisMIndicateStatus( p_port->p_adapter->h_adapter,\r
+ NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0 );\r
+ NdisMIndicateStatusComplete( p_port->p_adapter->h_adapter );\r
+ \r
+ NdisMIndicateStatus( p_port->p_adapter->h_adapter,\r
+ NDIS_STATUS_MEDIA_CONNECT, NULL, 0 );\r
+ NdisMIndicateStatusComplete( p_port->p_adapter->h_adapter );\r
+ \r
+ // IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+ // ("Link DOWN!\n") );\r
+\r
if( p_port->p_local_endpt )\r
{\r
cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts,\r
{\r
cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts,\r
&p_endpt->lid_item );\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+ ("<__endptr_mgr_reset_all: setting p_endpt->dlid to 0\n"));\r
p_endpt->dlid = 0;\r
}\r
\r
}\r
-\r
+#endif\r
cl_obj_unlock( &p_port->obj );\r
\r
\r
}\r
\r
\r
+NTSTATUS\r
+ipoib_mac_to_path(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const mac_addr_t mac,\r
+ OUT ib_path_rec_t* p_path )\r
+{\r
+ ipoib_endpt_t* p_endpt;\r
+ cl_map_item_t *p_item;\r
+ uint64_t key = 0;\r
+ uint8_t sl;\r
+ net32_t flow_lbl;\r
+ uint8_t hop_limit;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+ cl_memcpy( &key, &mac, sizeof(mac_addr_t) );\r
+\r
+ cl_obj_lock( &p_port->obj );\r
+\r
+ if( p_port->p_local_endpt == NULL )\r
+ {\r
+ cl_obj_unlock( &p_port->obj );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("No local endpoint.\n") );\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+\r
+ if( mac.addr[0] == 0 && mac.addr[1] == 0 && mac.addr[2] == 0 &&\r
+ mac.addr[3] == 0 && mac.addr[4] == 0 && mac.addr[5] == 0 )\r
+ {\r
+ p_endpt = p_port->p_local_endpt;\r
+ }\r
+ else\r
+ {\r
+ p_item = cl_qmap_get( &p_port->endpt_mgr.mac_endpts, key );\r
+ if( p_item == cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) )\r
+ {\r
+ cl_obj_unlock( &p_port->obj );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed endpoint lookup.\n") );\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+\r
+ p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
+ }\r
+\r
+ p_path->resv0 = 0;\r
+ p_path->dgid = p_endpt->dgid;\r
+ p_path->sgid = p_port->p_local_endpt->dgid;\r
+ p_path->dlid = p_endpt->dlid;\r
+ p_path->slid = p_port->p_local_endpt->dlid;\r
+\r
+ ib_member_get_sl_flow_hop(\r
+ p_port->ib_mgr.bcast_rec.sl_flow_hop,\r
+ &sl,\r
+ &flow_lbl,\r
+ &hop_limit\r
+ );\r
+ ib_path_rec_set_hop_flow_raw( p_path, hop_limit, flow_lbl, FALSE );\r
+\r
+ p_path->tclass = p_port->ib_mgr.bcast_rec.tclass;\r
+ p_path->num_path = 1;\r
+ p_path->pkey = p_port->ib_mgr.bcast_rec.pkey;\r
+ p_path->mtu = p_port->ib_mgr.bcast_rec.mtu;\r
+ p_path->rate = p_port->ib_mgr.bcast_rec.rate;\r
+ if( p_path->slid == p_path->dlid )\r
+ p_path->pkt_life = 0;\r
+ else\r
+ p_path->pkt_life = p_port->ib_mgr.bcast_rec.pkt_life;\r
+ p_path->preference = 0;\r
+ p_path->resv1 = 0;\r
+ p_path->resv2 = 0;\r
+\r
+ cl_obj_unlock( &p_port->obj );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+\r
static inline NDIS_STATUS\r
__endpt_mgr_ref(\r
IN ipoib_port_t* const p_port,\r
cl_obj_destroy( &p_endpt->obj );\r
#if DBG\r
cl_atomic_dec( &p_port->ref[ref_endpt_track] );\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ,\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
("ref type %d ref_cnt %d\n", ref_endpt_track, p_port->obj.ref_cnt) );\r
#endif\r
\r
cl_memclr( &av_attr, sizeof(ib_av_attr_t) );\r
av_attr.port_num = p_port->port_num;\r
av_attr.sl = 0;\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ENDPT,\r
+ ("<__endpt_mgr_add_local>: av_attr.dlid = p_port_info->base_lid = %d\n",p_port_info->base_lid));\r
av_attr.dlid = p_port_info->base_lid;\r
av_attr.static_rate = ib_port_info_compute_rate( p_port_info );\r
av_attr.path_bits = 0;\r
IN const mac_addr_t mac,\r
OUT ib_gid_t* p_gid );\r
\r
+NTSTATUS\r
+ipoib_mac_to_path(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const mac_addr_t mac,\r
+ OUT ib_path_rec_t* p_path );\r
+\r
inline void ipoib_port_ref(\r
IN ipoib_port_t * p_port, \r
IN int type);\r
IN const struct sockaddr *p_dest_addr,\r
OUT ib_net64_t *port_guid )\r
{\r
- ib_gid_pair_t gids;\r
- uint16_t pkey;\r
+ ib_path_rec_t path;\r
HRESULT hr;\r
\r
IBSP_ENTER( IBSP_DBG_HW );\r
hr = IbatResolve(\r
p_src_addr,\r
p_dest_addr,\r
- (IN6_ADDR*)&gids.src_gid,\r
- (IN6_ADDR*)&gids.dest_gid,\r
- &pkey\r
+ (IBAT_PATH_BLOB*)&path\r
);\r
\r
if( hr != E_PENDING )\r
break;\r
\r
- Sleep( 100 );\r
+ Sleep( 100 );\r
}\r
if( hr == S_OK )\r
{\r
- *port_guid = gids.dest_gid.unicast.interface_id;\r
+ *port_guid = path.dgid.unicast.interface_id;\r
}\r
else\r
{\r