<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META content="text/html; charset=us-ascii" http-equiv=Content-Type>
<META name=GENERATOR content="MSHTML 8.00.6001.18702"></HEAD>
<BODY>
<DIV><FONT size=2 face=Arial><SPAN class=632185917-15102009>The following code
allows WSD to load new apm paths after a failure in an existing
path.</SPAN></FONT></DIV>
<DIV><FONT size=2 face=Arial><SPAN
class=632185917-15102009></SPAN></FONT> </DIV>
<DIV><FONT size=2 face=Arial><SPAN
class=632185917-15102009>Thanks</SPAN></FONT></DIV>
<DIV><FONT size=2 face=Arial><SPAN
class=632185917-15102009>Tzachi</SPAN></FONT></DIV>
<DIV><FONT size=2 face=Arial></FONT> </DIV>
<DIV><FONT size=2 face=Arial></FONT> </DIV>
<DIV><FONT size=2 face=Arial></FONT> </DIV>
<DIV><FONT size=2 face=Arial>Index:
ib_cm.c<BR>===================================================================<BR>---
ib_cm.c (revision 4959)<BR>+++ ib_cm.c (working copy)<BR>@@ -43,7
+43,7 @@<BR> static void AL_API cm_rej_callback(IN ib_cm_rej_rec_t *
p_cm_rej_rec);<BR> static void AL_API cm_mra_callback(IN ib_cm_mra_rec_t *
p_cm_mra_rec);<BR> static void AL_API cm_dreq_callback(IN ib_cm_dreq_rec_t
* p_cm_dreq_rec);<BR>-static void AL_API cm_apr_callback(IN ib_cm_apr_rec_t *
p_cm_apr_rec);<BR>+void AL_API cm_apr_callback(IN ib_cm_apr_rec_t *
p_cm_apr_rec);<BR> <BR> <BR> /* Computes a service ID for a port.
*/<BR>@@ -585,19 +585,32 @@<BR> * A user-specified callback that is
invoked after receiving a load<BR> * alternate path response
message.<BR> */<BR>-static void AL_API<BR>+void
AL_API<BR> cm_apr_callback(<BR> IN ib_cm_apr_rec_t *p_cm_apr_rec
)<BR> {<BR>- /* TODO */<BR>+ struct ibsp_socket_info *socket_info
=<BR>+ (struct ibsp_socket_info
*)p_cm_apr_rec->qp_context;<BR>+<BR> IBSP_ENTER( IBSP_DBG_CM
);<BR> <BR>- UNUSED_PARAM( p_cm_apr_rec
);<BR>+ IBSP_PRINT_EXIT(TRACE_LEVEL_INFORMATION, IBSP_DBG_APM,
("cm_apr_callback called p_cm_apr_rec->cm_status = %d\n",
p_cm_apr_rec->cm_status) );<BR> <BR>- IBSP_ERROR( ("not
implemented") );<BR>+ cl_spinlock_acquire( &g_ibsp.socket_info_mutex
);<BR>+ CL_ASSERT(socket_info->apm_state ==
APM_LAP_SENT);<BR> <BR>- CL_ASSERT( 0 );<BR>+ if
((p_cm_apr_rec->cm_status == IB_SUCCESS) &&
<BR>+ (p_cm_apr_rec->apr_status ==
IB_SUCCESS)){<BR>+ socket_info->apm_state =
APM_ARMED;<BR>+ socket_info->SuccesfulMigrations++;<BR>+ }
else {<BR>+ socket_info->apm_state =
APM_MIGRATED;<BR>+ }<BR>+ cl_spinlock_release(
&g_ibsp.socket_info_mutex
);<BR> <BR>+<BR>+<BR>+<BR> IBSP_EXIT( IBSP_DBG_CM
);<BR> }<BR> <BR>@@ -612,15 +625,31
@@<BR> cm_lap_callback(<BR> IN ib_cm_lap_rec_t *p_cm_lap_rec
)<BR> {<BR>- /* TODO */<BR>+ ib_cm_apr_t cm_apr;<BR>+ struct
ibsp_socket_info *socket_info =<BR>+ (struct ibsp_socket_info
*)p_cm_lap_rec->qp_context;<BR>+ <BR>+ ib_api_status_t status;<BR>+<BR> IBSP_ENTER(
IBSP_DBG_CM );<BR> <BR>- UNUSED_PARAM( p_cm_lap_rec
);<BR>+ IBSP_PRINT_EXIT(TRACE_LEVEL_INFORMATION, IBSP_DBG_APM, ("called
\n") );<BR> <BR>- IBSP_ERROR( ("not implemented")
);<BR> <BR>- CL_ASSERT( 0 );<BR>+ cl_memclr(&cm_apr,
sizeof(cm_apr));<BR>+ cm_apr.qp_type =
IB_QPT_RELIABLE_CONN;<BR>+ cm_apr.h_qp =
socket_info->qp;<BR> <BR>+<BR>+ status =
ib_cm_apr(p_cm_lap_rec->h_cm_lap, &cm_apr);<BR>+ if( status !=
IB_SUCCESS ) {<BR>+ // Actually not much that we can do at this
stage.<BR>+ // The other side will get timeout and
retry<BR>+ CL_ASSERT(FALSE);<BR>+ IBSP_ERROR( ("ib_cm_apr
returned %s\n", ib_get_err_str( status ))
);<BR>+ }<BR>+<BR>+<BR> IBSP_EXIT( IBSP_DBG_CM
);<BR> }<BR> <BR>Index:
ibsp_iblow.c<BR>===================================================================<BR>---
ibsp_iblow.c (revision 4959)<BR>+++ ibsp_iblow.c (working copy)<BR>@@
-1054,7 +1054,7 @@<BR> qp_create.sq_signaled =
TRUE;<BR> <BR> status = ib_create_qp( socket_info->hca_pd,
&qp_create, socket_info, /* context */<BR>- NULL, /*
async handler */<BR>+ qp_event_handler, /* async handler
*/<BR> &socket_info->qp );<BR> if( status
)<BR> {<BR>Index:
ibsp_ip.c<BR>===================================================================<BR>---
ibsp_ip.c (revision 4959)<BR>+++ ibsp_ip.c (working copy)<BR>@@ -418,7
+418,7 @@<BR> return
0;<BR> <BR> error:<BR>- IBSP_ERROR_EXIT( ("query_ip_address
failed\n") );<BR>+ IBSP_ERROR_EXIT( ("query_pr failed\n")
);<BR> return 1;<BR> }<BR> <BR>Index:
ibsp_mngt.c<BR>===================================================================<BR>---
ibsp_mngt.c (revision 4959)<BR>+++ ibsp_mngt.c (working copy)<BR>@@
-1,289 +0,0 @@<BR>-/* <BR>- * FileName: ibsp_mngt.c<BR>- * <BR>- *
Copyright (c)<BR>- * <BR>- * Abstract: Hardware ressource management (HCA and
ports).<BR>- * <BR>- * Author:<BR>- * <BR>- * Revision History:<BR>- * <BR>-
*/<BR>-<BR>-#include "ibspdll.h"<BR>-<BR>-/* Build a list of IP addresses
associated with a port */<BR>-int<BR>-build_port_ip_list(IN struct ibsp_port
*port)<BR>-{<BR>- struct ibsp_ip_addr *ip_addr;<BR>- cl_list_item_t
*item;<BR>- int ret;<BR>-<BR>- CL_ENTER(IBSP_DBG_HW,
gdbg_lvl);<BR>- CL_TRACE(IBSP_DBG_HW, gdbg_lvl,<BR>-
("build_port_ip_list for port %UI64x\n",
cl_ntoh64(port->guid)));<BR>-<BR>- cl_qlist_init(&port->ip_list);<BR>-<BR>- ret
= query_ip_address(port, &port->ip_list);<BR>- if (ret)
{<BR>- CL_ERROR(IBSP_DBG_HW, gdbg_lvl, ("query_ip_address failed
(%d)\n", ret));<BR>- goto
error;<BR>- }<BR>-<BR>- CL_EXIT(IBSP_DBG_HW,
gdbg_lvl);<BR>- return 0;<BR>-<BR>- error:<BR>- /* Free the list
*/<BR>- while((item = cl_qlist_remove_head(&port->ip_list)) !=
cl_qlist_end(&port->ip_list)) {<BR>-<BR>- ip_addr =
PARENT_STRUCT(item, struct ibsp_ip_addr,
item);<BR>-<BR>- HeapFree(g_ibsp.heap, 0,
ip_addr);<BR>- }<BR>-<BR>- CL_EXIT_ERROR(IBSP_DBG_HW,
gdbg_lvl,<BR>- ("Failed to build list of IP addr
for port %016UI64x\n",<BR>-
CL_HTON64(port->guid)));<BR>-<BR>- return 1;<BR>-}<BR>-<BR>-/* Get the
info from a port. Link it to the parent HCA. */<BR>-int<BR>-build_port_info(IN
struct ibsp_hca *hca,<BR>- IN ib_net64_t
port_guid,<BR>- IN uint8_t port_num, OUT struct ibsp_port
**port_out)<BR>-{<BR>- int ret;<BR>- struct ibsp_port
*port;<BR>- cl_list_item_t *item_ip;<BR>-<BR>- CL_ENTER(IBSP_DBG_HW,
gdbg_lvl);<BR>-<BR>- port = HeapAlloc(g_ibsp.heap, HEAP_ZERO_MEMORY,
sizeof(struct ibsp_port));<BR>-<BR>- if (port == NULL)
{<BR>- CL_ERROR(IBSP_DBG_HW, gdbg_lvl,<BR>-
("HeapAlloc failed (%d)\n", sizeof(struct ibsp_port)));<BR>- ret =
WSAEPROVIDERFAILEDINIT;<BR>- goto
done;<BR>- }<BR>-<BR>- port->guid =
port_guid;<BR>- port->port_num = port_num;<BR>- port->hca =
hca;<BR>-<BR>- ret = build_port_ip_list(port);<BR>-<BR>- if (ret)
{<BR>- CL_ERROR(IBSP_DBG_HW, gdbg_lvl, ("build_port_ip_list failed
(%d)\n", ret));<BR>- ret =
WSAEPROVIDERFAILEDINIT;<BR>- goto done;<BR>- }<BR>-<BR>- /*
Insert the new list of IP into the global list of IP addresses.
*/<BR>- for(item_ip =
cl_qlist_head(&port->ip_list);<BR>- item_ip !=
cl_qlist_end(&port->ip_list); item_ip = cl_qlist_next(item_ip))
{<BR>-<BR>- struct ibsp_ip_addr *ip = PARENT_STRUCT(item_ip, struct
ibsp_ip_addr,
item);<BR>-<BR>- cl_qlist_insert_tail(&g_ibsp.ip_list,
&ip->item_global);<BR>- }<BR>-<BR>- *port_out =
port;<BR>-<BR>- CL_EXIT(IBSP_DBG_HW, gdbg_lvl);<BR>-<BR>- ret =
0;<BR>-<BR>- done:<BR>- if (ret)
{<BR>- HeapFree(g_ibsp.heap, 0,
port);<BR>- }<BR>-<BR>- CL_EXIT(IBSP_DBG_HW,
gdbg_lvl);<BR>-<BR>- return ret;<BR>-}<BR>-<BR>-/* Open and query the HCA
for its ports */<BR>-int<BR>-build_hca_info(IN ib_net64_t hca_guid, OUT struct
ibsp_hca **hca_out)<BR>-{<BR>- struct ibsp_hca *hca =
NULL;<BR>- ib_ca_attr_t *ca_attr = NULL;<BR>- size_t ca_attr_size =
0;<BR>- uint8_t port_num;<BR>- int ret;<BR>- ib_api_status_t
status;<BR>-<BR>- CL_ENTER(IBSP_DBG_HW, gdbg_lvl);<BR>-<BR>- hca =
HeapAlloc(g_ibsp.heap, HEAP_ZERO_MEMORY, sizeof(struct ibsp_hca));<BR>- if
(hca == NULL) {<BR>- CL_ERROR(IBSP_DBG_HW,
gdbg_lvl,<BR>- ("can't get enough memory (%d)\n",
sizeof(struct ibsp_hca)));<BR>- ret =
WSAEPROVIDERFAILEDINIT;<BR>- goto
done;<BR>- }<BR>-<BR>- hca->guid =
hca_guid;<BR>- cl_qlist_init(&hca->ports_list);<BR>-<BR>- status
= ib_open_ca(g_ibsp.al_handle, hca->guid, NULL, /* event handler
*/<BR>- NULL, /* context
*/<BR>- &hca->hca_handle);<BR>-<BR>- if
(status != IB_SUCCESS) {<BR>- CL_ERROR(IBSP_DBG_HW, gdbg_lvl,
("ib_open_ca failed (%d)\n", status));<BR>- ret =
WSAEPROVIDERFAILEDINIT;<BR>- goto done;<BR>- }<BR>-<BR>- /*
Build the list of ports of each HCAs */<BR>-
query_ca_again:<BR>- status = ib_query_ca(hca->hca_handle, ca_attr,
&ca_attr_size);<BR>-<BR>- if (status == IB_INSUFFICIENT_MEMORY)
{<BR>-<BR>- CL_TRACE(IBSP_DBG_HW, gdbg_lvl, ("ib_query_ca needs %d
bytes\n", ca_attr_size));<BR>-<BR>- /* Allocate more memory
*/<BR>- if (ca_attr) {<BR>- HeapFree(g_ibsp.heap, 0,
ca_attr);<BR>- }<BR>-<BR>- ca_attr =
HeapAlloc(g_ibsp.heap, 0, ca_attr_size);<BR>-<BR>- if
(ca_attr)<BR>- goto query_ca_again;<BR>- else
{<BR>- CL_ERROR(IBSP_DBG_HW, gdbg_lvl, ("HeapAlloc
failed\n"));<BR>- ret =
WSAEPROVIDERFAILEDINIT;<BR>- goto
done;<BR>- }<BR>- } else if (status != IB_SUCCESS)
{<BR>- CL_ERROR(IBSP_DBG_HW, gdbg_lvl, ("ib_query_ca failed (%d)\n",
status));<BR>- ret = WSAEPROVIDERFAILEDINIT;<BR>- goto
done;<BR>- }<BR>-<BR>- CL_TRACE(IBSP_DBG_HW, gdbg_lvl, ("found %d port
on that HCA\n", ca_attr->num_ports));<BR>-<BR>- for(port_num = 0;
port_num < ca_attr->num_ports; port_num++) {<BR>- struct
ibsp_port *port;<BR>-<BR>- ret = build_port_info(hca,
ca_attr->p_port_attr[port_num].port_guid, port_num + 1, /* TODO: correct
or should query port info?
*/<BR>-
&port);<BR>- if (ret)
{<BR>- CL_ERROR(IBSP_DBG_HW, gdbg_lvl, ("build_port_info failed
(%d)\n", ret));<BR>- goto
done;<BR>- }<BR>-<BR>- cl_qlist_insert_tail(&hca->ports_list,
&port->item);<BR>- }<BR>-<BR>- *hca_out =
hca;<BR>-<BR>- ret = 0;<BR>-<BR>- done:<BR>- if (ca_attr)
{<BR>- HeapFree(g_ibsp.heap, 0,
ca_attr);<BR>- }<BR>-<BR>- if (ret) {<BR>- if (hca)
{<BR>-<BR>- if (hca->hca_handle)
{<BR>- status = ib_close_ca(hca->hca_handle,
NULL);<BR>-<BR>- if (status != IB_SUCCESS)
{<BR>- CL_ERROR(IBSP_DBG_HW,
gdbg_lvl,<BR>- ("ib_close_ca failed
(%d)\n",
status));<BR>- }<BR>- }<BR>-<BR>- HeapFree(g_ibsp.heap,
0, hca);<BR>- }<BR>- }<BR>-<BR>- CL_TRACE_EXIT(IBSP_DBG_HW,
gdbg_lvl, ("return code is %d\n", ret));<BR>-<BR>- return
ret;<BR>-}<BR>-<BR>-/* Build the HCA tree. This allows for hotplug. Each HCA
is<BR>- * discovered, as well as each ports.
*/<BR>-int<BR>-build_hca_tree(void)<BR>-{<BR>- ib_net64_t *guid_list =
NULL;<BR>- ib_api_status_t status;<BR>- int ret;<BR>- unsigned
int hca_num;<BR>- size_t
adapter_count;<BR>-<BR>- CL_ENTER(IBSP_DBG_HW, gdbg_lvl);<BR>-<BR>- /*
Get the GUIDS of the adapters, so we can open them */<BR>- status =
ib_get_ca_guids(g_ibsp.al_handle, NULL, &adapter_count);<BR>- if
(status != IB_INSUFFICIENT_MEMORY) {<BR>- CL_ERROR(IBSP_DBG_HW,
gdbg_lvl, ("first ib_get_ca_guids failed\n"));<BR>- ret =
WSAEPROVIDERFAILEDINIT;<BR>- goto done;<BR>- }<BR>-<BR>- /*
Make sure we have a reasonable number of HCAs
*/<BR>- CL_ASSERT(adapter_count < 10);<BR>-<BR>- guid_list =
HeapAlloc(g_ibsp.heap, 0, sizeof(ib_net64_t) * adapter_count);<BR>- if
(guid_list == NULL) {<BR>- CL_ERROR(IBSP_DBG_HW,
gdbg_lvl,<BR>- ("can't get enough memory (%d, %d)\n",
sizeof(ib_net64_t),<BR>-
adapter_count));<BR>- ret =
WSAEPROVIDERFAILEDINIT;<BR>- goto
done;<BR>- }<BR>-<BR>- status = ib_get_ca_guids(g_ibsp.al_handle,
guid_list, &adapter_count);<BR>- if (status != IB_SUCCESS)
{<BR>- CL_ERROR(IBSP_DBG_HW, gdbg_lvl, ("second ib_get_ca_guids
failed (%d)\n", status));<BR>- ret =
WSAEPROVIDERFAILEDINIT;<BR>- goto
done;<BR>- }<BR>-<BR>- CL_TRACE(IBSP_DBG_HW, gdbg_lvl, ("got %d
adapter guid(s)\n", adapter_count));<BR>-<BR>- for(hca_num = 0; hca_num
< adapter_count; hca_num++) {<BR>-<BR>- struct ibsp_hca
*hca;<BR>-<BR>- ret = build_hca_info(guid_list[hca_num],
&hca);<BR>- if (ret)
{<BR>- CL_ERROR(IBSP_DBG_HW, gdbg_lvl, ("build_hca_info failed
(%d)\n", ret));<BR>- goto
done;<BR>- }<BR>-<BR>- cl_qlist_insert_tail(&g_ibsp.hca_list,
&hca->item);<BR>- }<BR>-<BR>- CL_ASSERT(adapter_count ==
cl_qlist_count(&g_ibsp.hca_list));<BR>-<BR>- CL_EXIT(IBSP_DBG_HW,
gdbg_lvl);<BR>-<BR>- ret = 0;<BR>-<BR>- done:<BR>- if
(guid_list) {<BR>- HeapFree(g_ibsp.heap, 0,
guid_list);<BR>- }<BR>-<BR>- CL_EXIT(IBSP_DBG_HW,
gdbg_lvl);<BR>-<BR>- return ret;<BR>-}<BR>Index:
ibspdebug.h<BR>===================================================================<BR>---
ibspdebug.h (revision 4959)<BR>+++ ibspdebug.h (working copy)<BR>@@
-70,10 +70,10 @@<BR> WPP_DEFINE_BIT( IBSP_DBG_HW)
\<BR> WPP_DEFINE_BIT( IBSP_DBG_IO) \<BR> WPP_DEFINE_BIT(
IBSP_DBG_DUP) \<BR>- WPP_DEFINE_BIT(
IBSP_DBG_PERFMON))<BR>+ WPP_DEFINE_BIT( IBSP_DBG_PERFMON)
\<BR>+ WPP_DEFINE_BIT(
IBSP_DBG_APM))<BR> <BR> <BR>-<BR> #define
WPP_LEVEL_FLAGS_ENABLED(lvl, flags) (WPP_LEVEL_ENABLED(flags) &&
WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl)<BR> #define
WPP_LEVEL_FLAGS_LOGGER(lvl,flags) WPP_LEVEL_LOGGER(flags)<BR> #define
WPP_FLAG_ENABLED(flags)(WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_
## flags).Level >= TRACE_LEVEL_VERBOSE)<BR>@@ -123,10 +123,11
@@<BR> #define IBSP_DBG_CONN 0x00000100 /* connections
*/<BR> #define IBSP_DBG_OPT 0x00000200 /* socket options
*/<BR> #define IBSP_DBG_NEV 0x00000400 /* network events
*/<BR>-#define IBSP_DBG_HW 0x00000800 /* Hardware */<BR>+#define
IBSP_DBG_HW 0x00000800 /* Hardware */<BR> #define
IBSP_DBG_IO 0x00001000 /* Overlapped I/O request
*/<BR> #define IBSP_DBG_DUP 0x00002000 /* Socket
Duplication */<BR> #define IBSP_DBG_PERFMON 0x00004000 /*
Performance Monitoring */<BR>+#define IBSP_DBG_APM 0x00008000 /*
APM handeling */<BR> <BR> #define
IBSP_DBG_ERROR (CL_DBG_ERROR | IBSP_DBG_ERR)<BR> <BR>Index:
ibspdll.c<BR>===================================================================<BR>---
ibspdll.c (revision 4959)<BR>+++ ibspdll.c (working copy)<BR>@@ -73,6
+73,9 @@<BR> uint32_t g_ibsp_dbg_level =
TRACE_LEVEL_ERROR;<BR> uint32_t g_ibsp_dbg_flags =
0x1;<BR> <BR>+BOOL InitApmLib();<BR>+VOID
ShutDownApmLib();<BR>+<BR> /*<BR> * Function: DllMain<BR> *
<BR>@@ -228,6 +231,11 @@<BR> if( init_globals()
)<BR> return FALSE;<BR> <BR>+ if
(g_use_APM)<BR>+ {<BR>+ InitApmLib();<BR>+ //
We continue weather it succeeded or not<BR>+ }<BR> #ifdef
PERFMON_ENABLED<BR> IBSPPmInit();<BR> #endif<BR>@@ -827,6
+835,8 @@<BR> IBSP_PRINT(TRACE_LEVEL_INFORMATION,
IBSP_DBG_CONN,<BR> ("lpCallerData=%p, lpCalleeData=%p\n",
lpCallerData, lpCalleeData)
);<BR> <BR>+<BR>+ socket_info->active_side =
TRUE;<BR> /* Sanity checks */<BR> if( lpCallerData
)<BR> {<BR>@@ -872,6 +882,7 @@<BR> *lpErrno =
g_connect_err;<BR> return
SOCKET_ERROR;<BR> }<BR>+ socket_info->dest_port_guid =
dest_port_guid;<BR> <BR> IBSP_PRINT(TRACE_LEVEL_INFORMATION,
IBSP_DBG_CONN, ("got GUID %I64x for IP %s\n",<BR> CL_NTOH64(
dest_port_guid ), inet_ntoa( addr->sin_addr )) );<BR>@@ -1766,6 +1777,19
@@<BR> }<BR> <BR> <BR>+void print_cur_apm_state(ib_qp_handle_t
h_qp)<BR>+{<BR>+ ib_qp_attr_t qp_attr;<BR>+ char *apm_states[] = {
"IB_APM_MIGRATED", "IB_APM_REARM", "IB_APM_ARMED" };<BR>+<BR>+ if
(!ib_query_qp(h_qp, &qp_attr)) {<BR>+ IBSP_ERROR(("Querying QP
returned that APM FSM is %s (%d)\n",
<BR>+ (qp_attr.apm_state<1 || qp_attr.apm_state>3) ?
"UNKNOWN" : <BR>+ apm_states[qp_attr.apm_state-1],
qp_attr.apm_state));<BR>+ }<BR>+ Sleep(10);<BR>+}<BR>+<BR> /*
Function: IBSPSend<BR> *<BR> * Description:<BR>@@ -2230,6
+2254,7 @@<BR> if( g_ibsp.entry_count == 0
)<BR> {<BR> IBSP_PRINT(TRACE_LEVEL_INFORMATION,
IBSP_DBG_INIT, ("entry_count is 0 => cleaning up\n")
);<BR>+ ShutDownApmLib();<BR> ib_release();<BR> <BR> #ifdef
PERFMON_ENABLED<BR>@@ -2350,4 +2375,220 @@<BR> }<BR> <BR> <BR>+//
TRUE means that all is well with socket, no need to recall it<BR>+BOOL
rearm_socket(struct ibsp_socket_info
*socket_info)<BR>+{<BR> <BR>+<BR>+ ib_path_rec_t
path_rec;<BR>+ ib_cm_lap_t cm_lap;<BR>+ int
ret;<BR>+ ib_api_status_t status;<BR>+<BR>+ ib_net64_t
dest_port_guid; <BR>+ ib_net64_t
src_port_guid;<BR>+<BR>+ CL_ASSERT(socket_info->active_side ==
TRUE);<BR>+ // Try to send the LAP message:<BR>+<BR>+<BR>+ if
((socket_info->SuccesfulMigrations & 1) ==
0)<BR>+ {<BR>+ src_port_guid =
socket_info->port->guid;<BR>+ dest_port_guid =
socket_info->dest_port_guid;<BR>+ }<BR>+ else
<BR>+ {<BR>+ src_port_guid =
GetOtherPortGuid(socket_info->port->guid);<BR>+ dest_port_guid
=
GetOtherPortGuid(socket_info->dest_port_guid);<BR>+ }<BR>+ /*
Get the path record */<BR>+ ret = query_pr( src_port_guid, dest_port_guid,
socket_info->port->hca->dev_id, &path_rec );<BR>+ if(ret !=
IB_SUCCESS)<BR>+ {<BR>+ IBSP_ERROR( ("query_pr for apm
failed\n") );<BR>+ return
FALSE;<BR>+ }<BR>+<BR>+ cl_memclr(&cm_lap,
sizeof(cm_lap));<BR>+ cm_lap.qp_type =
IB_QPT_RELIABLE_CONN;<BR>+ cm_lap.h_qp =
socket_info->qp;<BR>+ cm_lap.remote_resp_timeout = ib_path_rec_pkt_life(
&path_rec ) + CM_REMOTE_TIMEOUT;<BR>+ cm_lap.p_alt_path =
&path_rec;<BR>+ cm_lap.pfn_cm_apr_cb =
cm_apr_callback;<BR>+ status = ib_cm_lap(&cm_lap);<BR>+ if( status
!= IB_SUCCESS )<BR>+ {<BR>+ /* Note: a REJ has been
automatically sent. */<BR>+ IBSP_ERROR( ("ib_cm_lap returned %s\n",
ib_get_err_str( status )) );<BR>+ return FALSE;<BR>+ }
<BR>+ else
<BR>+ {<BR>+ IBSP_PRINT_EXIT(TRACE_LEVEL_INFORMATION,
IBSP_DBG_APM, ("ib_cm_lap returned succesfuly\n")
);<BR>+ socket_info->apm_state =
APM_LAP_SENT;<BR>+ }<BR>+ <BR>+<BR>+ // Actually we always
return false, since we need to make sure that the lap <BR>+ // was realy
successfull.<BR>+ return FALSE;<BR>+}<BR>+<BR>+<BR>+<BR>+VOID
APMCallback(struct ibsp_socket_info
*apm_socket_info)<BR>+{<BR>+ cl_list_item_t *socket_item =
NULL;<BR>+ BOOL found = FALSE;<BR>+<BR>+ if (g_ibsp.apm_data.hEvent==
0) {<BR>+ // This means that we have failed to start our timer, not
much<BR>+ // that we can
do.<BR>+ return;<BR>+ }<BR>+<BR>+ <BR>+ // Find our
socket and mark it as needs to load a new path.<BR>+ // Avoid race by
searching in the list<BR>+ // BUGBUG: Need to have a better solution than
this<BR>+ cl_spinlock_acquire( &g_ibsp.socket_info_mutex
);<BR>+ for( socket_item = cl_qlist_head( &g_ibsp.socket_info_list
);<BR>+ socket_item != cl_qlist_end( &g_ibsp.socket_info_list
);<BR>+ socket_item = cl_qlist_next( socket_item )
)<BR>+ {<BR>+ struct ibsp_socket_info *socket_info =
NULL;<BR>+ socket_info = PARENT_STRUCT(socket_item, struct
ibsp_socket_info, item);<BR>+ if (apm_socket_info == socket_info)
{<BR>+ if (apm_socket_info->active_side)
{<BR>+ CL_ASSERT(apm_socket_info->apm_state ==
APM_ARMED);<BR>+ apm_socket_info->apm_state =
APM_MIGRATED ;<BR>+ }<BR>+ found =
TRUE;<BR>+ break;<BR>+ }<BR>+ }<BR>+ CL_ASSERT(found
== TRUE); // The case that we are not found is very
rare<BR>+
// and is probably a
bug<BR>+<BR>+ SetEvent(g_ibsp.apm_data.hEvent);<BR>+<BR>+ cl_spinlock_release(
&g_ibsp.socket_info_mutex );<BR>+<BR>+}<BR>+<BR>+DWORD WINAPI
ApmThreadProc(<BR>+ LPVOID lpParameter<BR>+)<BR>+{<BR>+ DWORD
dwTimeOut = INFINITE;<BR>+ DWORD ret;<BR>+ cl_list_item_t *socket_item
=
NULL;<BR>+<BR>+ UNREFERENCED_PARAMETER(lpParameter);<BR>+<BR>+ for(;;)
{<BR>+ BOOL AllSocketsDone = TRUE;<BR>+ ret =
WaitForSingleObject(g_ibsp.apm_data.hEvent, dwTimeOut);<BR>+ if
(g_ibsp.apm_data.ThreadExit) {<BR>+ return
0;<BR>+ } <BR>+ cl_spinlock_acquire(
&g_ibsp.socket_info_mutex );<BR>+ for( socket_item =
cl_qlist_head( &g_ibsp.socket_info_list );<BR>+ socket_item
!= cl_qlist_end( &g_ibsp.socket_info_list
);<BR>+ socket_item = cl_qlist_next( socket_item )
)<BR>+ {<BR>+ struct ibsp_socket_info *socket_info =
NULL;<BR>+ socket_info = PARENT_STRUCT(socket_item, struct
ibsp_socket_info, item);<BR>+ if(socket_info->apm_state ==
APM_MIGRATED)<BR>+ {<BR>+ AllSocketsDone
&= rearm_socket(socket_info);<BR>+ } else
if(socket_info->apm_state == APM_LAP_SENT)
{<BR>+ AllSocketsDone =
FALSE;<BR>+ }<BR>+ }<BR>+ if
(AllSocketsDone) <BR>+ {<BR>+ dwTimeOut =
INFINITE;<BR>+ } <BR>+ else
<BR>+ {<BR>+ dwTimeOut =
2000;<BR>+ }<BR>+<BR>+ cl_spinlock_release(
&g_ibsp.socket_info_mutex
);<BR>+<BR>+ <BR>+ }<BR>+}<BR>+<BR>+<BR>+void
qp_event_handler(ib_async_event_rec_t *p_event)<BR>+{<BR>+<BR>+ if
(p_event->code == IB_AE_QP_APM) <BR>+ {<BR>+ struct
ibsp_socket_info *socket_info = (struct
ibsp_socket_info *)p_event->context;<BR>+ IBSP_PRINT_EXIT(TRACE_LEVEL_INFORMATION,
IBSP_DBG_APM,("Received an APM
event\n"));<BR>+ APMCallback(socket_info);<BR>+ }<BR>+}<BR>+<BR>+<BR>+<BR>+BOOL
InitApmLib()<BR>+{<BR>+ IBSP_PRINT_EXIT(TRACE_LEVEL_INFORMATION,
IBSP_DBG_APM,("called\n"));<BR>+<BR>+ g_ibsp.apm_data.hEvent =
CreateEvent(NULL, FALSE, FALSE, NULL);<BR>+ if (g_ibsp.apm_data.hEvent ==
NULL) {<BR>+ IBSP_ERROR_EXIT( ("CreateEvent failed with error %d\n",
GetLastError()));<BR>+ return
FALSE;<BR>+ }<BR>+<BR>+ g_ibsp.apm_data.hThread =
CreateThread(<BR>+ NULL,
// Default security
attributes<BR>+ 0,<BR>+ ApmThreadProc,<BR>+ NULL,<BR>+ 0,<BR>+ NULL<BR>+ );
<BR>+ if (g_ibsp.apm_data.hThread == NULL)
{<BR>+ IBSP_ERROR_EXIT( ("CreateThread failed with error %d\n",
GetLastError()));<BR>+ CloseHandle(g_ibsp.apm_data.hEvent);<BR>+ g_ibsp.apm_data.hEvent
= NULL;<BR>+ return FALSE;<BR>+ }<BR>+<BR>+<BR>+ return
TRUE;<BR>+<BR>+<BR>+<BR>+}<BR>+<BR>+<BR>+VOID
ShutDownApmLib()<BR>+{<BR>+ DWORD dwRet;<BR>+<BR>+ if
(g_ibsp.apm_data.hEvent== 0) {<BR>+ // This means that we have failed
to start our timer, not much<BR>+ // that we can
do.<BR>+ return;<BR>+ }<BR>+<BR>+ g_ibsp.apm_data.ThreadExit
= TRUE;<BR>+ SetEvent(g_ibsp.apm_data.hEvent);<BR>+<BR>+ dwRet =
WaitForSingleObject(g_ibsp.apm_data.hThread,
INFINITE);<BR>+ CL_ASSERT(dwRet == WAIT_OBJECT_0);<BR>+<BR>+ dwRet =
CloseHandle(g_ibsp.apm_data.hThread);<BR>+ CL_ASSERT(dwRet !=
0);<BR>+<BR>+ dwRet =
CloseHandle(g_ibsp.apm_data.hEvent);<BR>+ CL_ASSERT(dwRet !=
0);<BR>+}<BR>+<BR>Index:
ibspproto.h<BR>===================================================================<BR>---
ibspproto.h (revision 4959)<BR>+++ ibspproto.h (working copy)<BR>@@
-304,4 +304,8 @@<BR> return DestPortGuid ^
0x300000000000000;<BR> <BR> }<BR>+void AL_API
cm_apr_callback(<BR>+ IN ib_cm_apr_rec_t *p_cm_apr_rec
);<BR> <BR>+<BR>+void qp_event_handler(ib_async_event_rec_t
*p_event);<BR>Index:
ibspstruct.h<BR>===================================================================<BR>---
ibspstruct.h (revision 4959)<BR>+++ ibspstruct.h (working copy)<BR>@@
-220,6 +220,15 @@<BR> struct ibsp_hca *hca; /* HCA to
which this cq belongs. */<BR> };<BR> <BR>+<BR>+enum APM_STATE
{<BR>+ APM_ARMED,<BR>+ APM_MIGRATED,<BR>+ APM_LAP_SENT<BR>+<BR>+};<BR>+<BR>+<BR> /*
Structure representing the context information stored for each<BR> *
socket created */<BR> struct ibsp_socket_info<BR>@@ -322,6 +331,10
@@<BR> GUID identifier; /* Unique identifier
*/<BR> DWORD dwProcessId;<BR> }
duplicate;<BR>+ BOOL active_side; // Tell if we have started this
call<BR>+ enum APM_STATE apm_state;<BR>+ UINT
SuccesfulMigrations;<BR>+ ib_net64_t
dest_port_guid;<BR> <BR> #ifdef
IBSP_LOGGING<BR> DataLogger SendDataLogger;<BR>@@ -413,6
+426,13 @@<BR> struct cq_thread_info
*cq_tinfo;<BR> };<BR> <BR>+struct
apm_data_t<BR>+{<BR>+ HANDLE hThread;<BR>+ HANDLE hEvent;<BR>+ BOOL
ThreadExit;<BR>+};<BR>+<BR> /* There is only one instance of that
structure. */<BR> struct ibspdll_globals<BR> {<BR>@@ -442,6 +462,8
@@<BR> cl_fmap_t ip_map; /* list of all
IP addresses supported by all the ports.
*/<BR> cl_spinlock_t ip_mutex;<BR> <BR>+ struct
apm_data_t apm_data;<BR>+<BR> #ifdef _DEBUG_<BR> /* Statistics
*/<BR> atomic32_t qp_num;<BR></DIV></FONT></BODY></HTML>