[WSD] Add fall back to wsd (extended APM).
authortzachid <tzachid@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Sun, 18 Oct 2009 11:20:08 +0000 (11:20 +0000)
committertzachid <tzachid@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Sun, 18 Oct 2009 11:20:08 +0000 (11:20 +0000)
git-svn-id: svn://openib.tc.cornell.edu/gen1/trunk@2488 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

ulp/wsd/user/ib_cm.c
ulp/wsd/user/ibsp_iblow.c
ulp/wsd/user/ibsp_ip.c
ulp/wsd/user/ibsp_mngt.c [deleted file]
ulp/wsd/user/ibspdebug.h
ulp/wsd/user/ibspdll.c
ulp/wsd/user/ibspproto.h
ulp/wsd/user/ibspstruct.h

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