<!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>