|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
|
|
Packit |
13e616 |
* Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
|
|
Packit |
13e616 |
* Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* This software is available to you under a choice of one of two
|
|
Packit |
13e616 |
* licenses. You may choose to be licensed under the terms of the GNU
|
|
Packit |
13e616 |
* General Public License (GPL) Version 2, available from the file
|
|
Packit |
13e616 |
* COPYING in the main directory of this source tree, or the
|
|
Packit |
13e616 |
* OpenIB.org BSD license below:
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* Redistribution and use in source and binary forms, with or
|
|
Packit |
13e616 |
* without modification, are permitted provided that the following
|
|
Packit |
13e616 |
* conditions are met:
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* - Redistributions of source code must retain the above
|
|
Packit |
13e616 |
* copyright notice, this list of conditions and the following
|
|
Packit |
13e616 |
* disclaimer.
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* - Redistributions in binary form must reproduce the above
|
|
Packit |
13e616 |
* copyright notice, this list of conditions and the following
|
|
Packit |
13e616 |
* disclaimer in the documentation and/or other materials
|
|
Packit |
13e616 |
* provided with the distribution.
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
Packit |
13e616 |
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
Packit |
13e616 |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
Packit |
13e616 |
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
Packit |
13e616 |
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
Packit |
13e616 |
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
Packit |
13e616 |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
Packit |
13e616 |
* SOFTWARE.
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
#if HAVE_CONFIG_H
|
|
Packit |
13e616 |
# include <config.h>
|
|
Packit |
13e616 |
#endif /* HAVE_CONFIG_H */
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
#include <string.h>
|
|
Packit |
13e616 |
#include <vendor/osm_vendor_mlx.h>
|
|
Packit |
13e616 |
#include <vendor/osm_vendor_mlx_defs.h>
|
|
Packit |
13e616 |
#include <vendor/osm_vendor_mlx_svc.h>
|
|
Packit |
13e616 |
#include <vendor/osm_vendor_mlx_transport.h>
|
|
Packit |
13e616 |
#include <vendor/osm_vendor_mlx_sender.h>
|
|
Packit |
13e616 |
#include <vendor/osm_pkt_randomizer.h>
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
typedef enum _osmv_disp_route {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSMV_ROUTE_DROP,
|
|
Packit |
13e616 |
OSMV_ROUTE_SIMPLE,
|
|
Packit |
13e616 |
OSMV_ROUTE_RMPP,
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
} osmv_disp_route_t;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/**
|
|
Packit |
13e616 |
* FORWARD REFERENCES TO PRIVATE FUNCTIONS
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static osmv_disp_route_t
|
|
Packit |
13e616 |
__osmv_dispatch_route(IN osm_bind_handle_t h_bind,
|
|
Packit |
13e616 |
IN const ib_mad_t * p_mad, OUT osmv_txn_ctx_t ** pp_txn);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void
|
|
Packit |
13e616 |
__osmv_dispatch_simple_mad(IN osm_bind_handle_t h_bind,
|
|
Packit |
13e616 |
IN const ib_mad_t * p_mad,
|
|
Packit |
13e616 |
IN osmv_txn_ctx_t * p_txn,
|
|
Packit |
13e616 |
IN const osm_mad_addr_t * p_mad_addr);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void
|
|
Packit |
13e616 |
__osmv_dispatch_rmpp_mad(IN osm_bind_handle_t h_bind,
|
|
Packit |
13e616 |
IN const ib_mad_t * p_mad,
|
|
Packit |
13e616 |
IN osmv_txn_ctx_t * p_txn,
|
|
Packit |
13e616 |
IN const osm_mad_addr_t * p_mad_addr);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void
|
|
Packit |
13e616 |
__osmv_dispatch_rmpp_snd(IN osm_bind_handle_t h_bind,
|
|
Packit |
13e616 |
IN const ib_mad_t * p_mad,
|
|
Packit |
13e616 |
IN osmv_txn_ctx_t * p_txn,
|
|
Packit |
13e616 |
IN const osm_mad_addr_t * p_mad_addr);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static ib_api_status_t
|
|
Packit |
13e616 |
__osmv_dispatch_rmpp_rcv(IN osm_bind_handle_t h_bind,
|
|
Packit |
13e616 |
IN const ib_mad_t * p_mad,
|
|
Packit |
13e616 |
IN osmv_txn_ctx_t * p_txn,
|
|
Packit |
13e616 |
IN const osm_mad_addr_t * p_mad_addr);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static ib_api_status_t
|
|
Packit |
13e616 |
__osmv_dispatch_accept_seg(IN osm_bind_handle_t h_bind,
|
|
Packit |
13e616 |
IN osmv_txn_ctx_t * p_txn,
|
|
Packit |
13e616 |
IN const ib_mad_t * p_mad);
|
|
Packit |
13e616 |
static void
|
|
Packit |
13e616 |
__osmv_dispatch_send_ack(IN osm_bind_handle_t h_bind,
|
|
Packit |
13e616 |
IN const ib_mad_t * p_req_mad,
|
|
Packit |
13e616 |
IN osmv_txn_ctx_t * p_txn,
|
|
Packit |
13e616 |
IN const osm_mad_addr_t * p_mad_addr);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* NAME
|
|
Packit |
13e616 |
* osmv_dispatch_mad
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* DESCRIPTION
|
|
Packit |
13e616 |
* Lower-level MAD dispatcher.
|
|
Packit |
13e616 |
* Implements a switch between the following MAD consumers:
|
|
Packit |
13e616 |
* (1) Non-RMPP consumer (DATA)
|
|
Packit |
13e616 |
* (2) RMPP receiver (DATA/ABORT/STOP)
|
|
Packit |
13e616 |
* (3) RMPP sender (ACK/ABORT/STOP)
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* PARAMETERS
|
|
Packit |
13e616 |
* h_bind The bind handle
|
|
Packit |
13e616 |
* p_mad_buf The 256 byte buffer of individual MAD
|
|
Packit |
13e616 |
* p_mad_addr The MAD originator's address
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
ib_api_status_t
|
|
Packit |
13e616 |
osmv_dispatch_mad(IN osm_bind_handle_t h_bind,
|
|
Packit |
13e616 |
IN const void *p_mad_buf,
|
|
Packit |
13e616 |
IN const osm_mad_addr_t * p_mad_addr)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
ib_api_status_t ret = IB_SUCCESS;
|
|
Packit |
13e616 |
const ib_mad_t *p_mad = (ib_mad_t *) p_mad_buf;
|
|
Packit |
13e616 |
osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
|
|
Packit |
13e616 |
osmv_txn_ctx_t *p_txn = NULL;
|
|
Packit |
13e616 |
osm_log_t *p_log = p_bo->p_vendor->p_log;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(p_bo->p_vendor->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(NULL != h_bind && NULL != p_mad && NULL != p_mad_addr);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osmv_txn_lock(p_bo);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (TRUE == p_bo->is_closing) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"The bind handle %p is being closed. "
|
|
Packit |
13e616 |
"The MAD will not be dispatched.\n", p_bo);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
ret = IB_INTERRUPTED;
|
|
Packit |
13e616 |
goto dispatch_mad_done;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
Add call for packet drop randomizer.
|
|
Packit |
13e616 |
This is a testing feature. If run_randomizer flag is set to TRUE,
|
|
Packit |
13e616 |
the randomizer will be called, and randomally will drop
|
|
Packit |
13e616 |
a packet. This is used for simulating unstable fabric.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if (p_bo->p_vendor->run_randomizer == TRUE) {
|
|
Packit |
13e616 |
/* Try the randomizer */
|
|
Packit |
13e616 |
if (osm_pkt_randomizer_mad_drop(p_bo->p_vendor->p_log,
|
|
Packit |
13e616 |
p_bo->p_vendor->
|
|
Packit |
13e616 |
p_pkt_randomizer,
|
|
Packit |
13e616 |
p_mad) == TRUE) {
|
|
Packit |
13e616 |
osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"The MAD will not be dispatched.\n");
|
|
Packit |
13e616 |
goto dispatch_mad_done;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
switch (__osmv_dispatch_route(h_bind, p_mad, &p_txn)) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
case OSMV_ROUTE_DROP:
|
|
Packit |
13e616 |
break; /* Do nothing */
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
case OSMV_ROUTE_SIMPLE:
|
|
Packit |
13e616 |
__osmv_dispatch_simple_mad(h_bind, p_mad, p_txn, p_mad_addr);
|
|
Packit |
13e616 |
break;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
case OSMV_ROUTE_RMPP:
|
|
Packit |
13e616 |
__osmv_dispatch_rmpp_mad(h_bind, p_mad, p_txn, p_mad_addr);
|
|
Packit |
13e616 |
break;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
default:
|
|
Packit |
13e616 |
CL_ASSERT(FALSE);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
dispatch_mad_done:
|
|
Packit |
13e616 |
osmv_txn_unlock(p_bo);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_EXIT(p_log);
|
|
Packit |
13e616 |
return ret;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* NAME __osmv_dispatch_route()
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* DESCRIPTION Decide which way to handle the received MAD: simple txn/RMPP/drop
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static osmv_disp_route_t
|
|
Packit |
13e616 |
__osmv_dispatch_route(IN osm_bind_handle_t h_bind,
|
|
Packit |
13e616 |
IN const ib_mad_t * p_mad, OUT osmv_txn_ctx_t ** pp_txn)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
ib_api_status_t ret;
|
|
Packit |
13e616 |
osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
|
|
Packit |
13e616 |
boolean_t is_resp = ib_mad_is_response(p_mad);
|
|
Packit |
13e616 |
boolean_t is_txn;
|
|
Packit |
13e616 |
uint64_t key = cl_ntoh64(p_mad->trans_id);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(NULL != pp_txn);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
ret = osmv_txn_lookup(h_bind, key, pp_txn);
|
|
Packit |
13e616 |
is_txn = (IB_SUCCESS == ret);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (FALSE == is_txn && TRUE == is_resp) {
|
|
Packit |
13e616 |
osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Received a response to a non-started/aged-out transaction (tid=0x%" PRIx64 "). "
|
|
Packit |
13e616 |
"Dropping the MAD.\n", key);
|
|
Packit |
13e616 |
return OSMV_ROUTE_DROP;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (TRUE == osmv_mad_is_rmpp(p_mad)) {
|
|
Packit |
13e616 |
/* An RMPP transaction. The filtering is more delicate there */
|
|
Packit |
13e616 |
return OSMV_ROUTE_RMPP;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (TRUE == is_txn && FALSE == is_resp) {
|
|
Packit |
13e616 |
/* Does this MAD try to start a transaction with duplicate tid? */
|
|
Packit |
13e616 |
osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Duplicate TID 0x%" PRIx64 " received (not a response). "
|
|
Packit |
13e616 |
"Dropping the MAD.\n", key);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
return OSMV_ROUTE_DROP;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
return OSMV_ROUTE_SIMPLE;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* NAME __osmv_dispatch_simple_mad()
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* DESCRIPTION Handle a MAD that is part of non-RMPP transfer
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void
|
|
Packit |
13e616 |
__osmv_dispatch_simple_mad(IN osm_bind_handle_t h_bind,
|
|
Packit |
13e616 |
IN const ib_mad_t * p_mad,
|
|
Packit |
13e616 |
IN osmv_txn_ctx_t * p_txn,
|
|
Packit |
13e616 |
IN const osm_mad_addr_t * p_mad_addr)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_madw_t *p_madw;
|
|
Packit |
13e616 |
ib_mad_t *p_mad_buf;
|
|
Packit |
13e616 |
osm_madw_t *p_req_madw = NULL;
|
|
Packit |
13e616 |
osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(p_bo->p_vendor->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Build the MAD wrapper to be returned to the user.
|
|
Packit |
13e616 |
* The actual storage for the MAD is allocated there.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
p_madw =
|
|
Packit |
13e616 |
osm_mad_pool_get(p_bo->p_osm_pool, h_bind, MAD_BLOCK_SIZE,
|
|
Packit |
13e616 |
p_mad_addr);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (NULL == p_madw) {
|
|
Packit |
13e616 |
osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
|
|
Packit |
13e616 |
"__osmv_dispatch_simple_mad: ERR 6501: "
|
|
Packit |
13e616 |
"Out Of Memory - could not allocate a buffer of size %d\n",
|
|
Packit |
13e616 |
MAD_BLOCK_SIZE);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
goto dispatch_simple_mad_done;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_mad_buf = osm_madw_get_mad_ptr(p_madw);
|
|
Packit |
13e616 |
/* Copy the payload to the MAD buffer */
|
|
Packit |
13e616 |
memcpy((void *)p_mad_buf, (void *)p_mad, MAD_BLOCK_SIZE);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (NULL != p_txn) {
|
|
Packit |
13e616 |
/* This is a RESPONSE MAD. Pair it with the REQUEST MAD, pass upstream */
|
|
Packit |
13e616 |
p_req_madw = p_txn->p_madw;
|
|
Packit |
13e616 |
CL_ASSERT(NULL != p_req_madw);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_mad_buf->trans_id = cl_hton64(osmv_txn_get_tid(p_txn));
|
|
Packit |
13e616 |
osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Restoring the original TID to 0x%" PRIx64 "\n",
|
|
Packit |
13e616 |
cl_ntoh64(p_mad_buf->trans_id));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Reply matched, transaction complete */
|
|
Packit |
13e616 |
osmv_txn_done(h_bind, osmv_txn_get_key(p_txn), FALSE);
|
|
Packit |
13e616 |
} else {
|
|
Packit |
13e616 |
/* This is a REQUEST MAD. Don't create a context, pass upstream */
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Do the job ! */
|
|
Packit |
13e616 |
p_bo->recv_cb(p_madw, p_bo->cb_context, p_req_madw);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
dispatch_simple_mad_done:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(p_bo->p_vendor->p_log);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* NAME __osmv_dispatch_rmpp_mad()
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* DESCRIPTION Handle a MAD that is part of RMPP transfer
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void
|
|
Packit |
13e616 |
__osmv_dispatch_rmpp_mad(IN osm_bind_handle_t h_bind,
|
|
Packit |
13e616 |
IN const ib_mad_t * p_mad,
|
|
Packit |
13e616 |
IN osmv_txn_ctx_t * p_txn,
|
|
Packit |
13e616 |
IN const osm_mad_addr_t * p_mad_addr)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
ib_api_status_t status = IB_SUCCESS;
|
|
Packit |
13e616 |
uint64_t key = cl_ntoh64(p_mad->trans_id);
|
|
Packit |
13e616 |
boolean_t is_init_by_peer = FALSE;
|
|
Packit |
13e616 |
osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
|
|
Packit |
13e616 |
osm_madw_t *p_madw;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(p_bo->p_vendor->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (NULL == p_txn) {
|
|
Packit |
13e616 |
if (FALSE == osmv_rmpp_is_data(p_mad)
|
|
Packit |
13e616 |
|| FALSE == osmv_rmpp_is_first(p_mad)) {
|
|
Packit |
13e616 |
osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"The MAD does not match any transaction "
|
|
Packit |
13e616 |
"and does not start a sender-initiated RMPP transfer.\n");
|
|
Packit |
13e616 |
goto dispatch_rmpp_mad_done;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* IB Spec 13.6.2.2. This is a Sender Initiated Transfer.
|
|
Packit |
13e616 |
My peer is the requester and RMPP Sender. I am the RMPP Receiver.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
status = osmv_txn_init(h_bind, /*tid==key */ key, key, &p_txn);
|
|
Packit |
13e616 |
if (IB_SUCCESS != status) {
|
|
Packit |
13e616 |
goto dispatch_rmpp_mad_done;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
is_init_by_peer = TRUE;
|
|
Packit |
13e616 |
osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"A new sender-initiated transfer (TID=0x%" PRIx64 ") started\n",
|
|
Packit |
13e616 |
key);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (OSMV_TXN_RMPP_NONE == osmv_txn_get_rmpp_state(p_txn)) {
|
|
Packit |
13e616 |
/* Case 1: Fall through from above.
|
|
Packit |
13e616 |
* Case 2: When the transaction was initiated by me
|
|
Packit |
13e616 |
* (a single request MAD), there was an uncertainty
|
|
Packit |
13e616 |
* whether the reply will be RMPP. Now it's resolved,
|
|
Packit |
13e616 |
* since the reply is RMPP!
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
status =
|
|
Packit |
13e616 |
osmv_txn_init_rmpp_receiver(h_bind, p_txn, is_init_by_peer);
|
|
Packit |
13e616 |
if (IB_SUCCESS != status) {
|
|
Packit |
13e616 |
goto dispatch_rmpp_mad_done;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
switch (osmv_txn_get_rmpp_state(p_txn)) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
case OSMV_TXN_RMPP_RECEIVER:
|
|
Packit |
13e616 |
status =
|
|
Packit |
13e616 |
__osmv_dispatch_rmpp_rcv(h_bind, p_mad, p_txn, p_mad_addr);
|
|
Packit |
13e616 |
if (IB_SUCCESS != status) {
|
|
Packit |
13e616 |
if (FALSE == osmv_txn_is_rmpp_init_by_peer(p_txn)) {
|
|
Packit |
13e616 |
/* This is a requester, still waiting for the reply. Apply the callback */
|
|
Packit |
13e616 |
/* update the status of the p_madw */
|
|
Packit |
13e616 |
p_madw = osmv_txn_get_madw(p_txn);
|
|
Packit |
13e616 |
p_madw->status = status;
|
|
Packit |
13e616 |
p_bo->send_err_cb(p_bo->cb_context, p_madw);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* ABORT/STOP/LOCAL ERROR */
|
|
Packit |
13e616 |
osmv_txn_done(h_bind, osmv_txn_get_key(p_txn), FALSE);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
break;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
case OSMV_TXN_RMPP_SENDER:
|
|
Packit |
13e616 |
__osmv_dispatch_rmpp_snd(h_bind, p_mad, p_txn, p_mad_addr);
|
|
Packit |
13e616 |
/* If an error happens here, it's the sender thread to cleanup the txn */
|
|
Packit |
13e616 |
break;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
default:
|
|
Packit |
13e616 |
CL_ASSERT(FALSE);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
dispatch_rmpp_mad_done:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(p_bo->p_vendor->p_log);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* NAME __osmv_dispatch_rmpp_snd()
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* DESCRIPTION MAD handling by an RMPP sender (ACK/ABORT/STOP)
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void
|
|
Packit |
13e616 |
__osmv_dispatch_rmpp_snd(IN osm_bind_handle_t h_bind,
|
|
Packit |
13e616 |
IN const ib_mad_t * p_mad,
|
|
Packit |
13e616 |
IN osmv_txn_ctx_t * p_txn,
|
|
Packit |
13e616 |
IN const osm_mad_addr_t * p_mad_addr)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osmv_rmpp_send_ctx_t *p_send_ctx = osmv_txn_get_rmpp_send_ctx(p_txn);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
uint32_t old_wl = p_send_ctx->window_last;
|
|
Packit |
13e616 |
uint32_t total_segs = osmv_rmpp_send_ctx_get_num_segs(p_send_ctx);
|
|
Packit |
13e616 |
uint32_t seg_num = cl_ntoh32(((ib_rmpp_mad_t *) p_mad)->seg_num);
|
|
Packit |
13e616 |
uint32_t new_wl = cl_ntoh32(((ib_rmpp_mad_t *) p_mad)->paylen_newwin);
|
|
Packit |
13e616 |
osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(p_bo->p_vendor->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (TRUE == osmv_rmpp_is_abort_stop(p_mad)) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
|
|
Packit |
13e616 |
"__osmv_dispatch_rmpp_snd: ERR 6502: "
|
|
Packit |
13e616 |
"The remote side sent an ABORT/STOP indication.\n");
|
|
Packit |
13e616 |
osmv_rmpp_snd_error(p_send_ctx, IB_REMOTE_ERROR);
|
|
Packit |
13e616 |
goto dispatch_rmpp_snd_done;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (FALSE == osmv_rmpp_is_ack(p_mad)) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Not supposed to receive DATA packets --> dropping the MAD\n");
|
|
Packit |
13e616 |
goto dispatch_rmpp_snd_done;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Continue processing the ACK */
|
|
Packit |
13e616 |
if (seg_num > old_wl) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
|
|
Packit |
13e616 |
"__osmv_dispatch_rmpp_snd: ERR 6503: "
|
|
Packit |
13e616 |
"ACK received for a non-sent segment %d\n", seg_num);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osmv_rmpp_send_nak(h_bind, p_mad, p_mad_addr,
|
|
Packit |
13e616 |
IB_RMPP_TYPE_ABORT, IB_RMPP_STATUS_S2B);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osmv_rmpp_snd_error(p_send_ctx, IB_REMOTE_ERROR);
|
|
Packit |
13e616 |
goto dispatch_rmpp_snd_done;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"__osmv_dispatch_rmpp_snd: "
|
|
Packit |
13e616 |
"New WL = %u Old WL = %u Total Segs = %u\n",
|
|
Packit |
13e616 |
new_wl, old_wl, total_segs);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (new_wl < old_wl) {
|
|
Packit |
13e616 |
osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
|
|
Packit |
13e616 |
"__osmv_dispatch_rmpp_snd: ERR 6508: "
|
|
Packit |
13e616 |
"The receiver requests a smaller WL (%d) than before (%d)\n",
|
|
Packit |
13e616 |
new_wl, old_wl);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osmv_rmpp_send_nak(h_bind, p_mad, p_mad_addr,
|
|
Packit |
13e616 |
IB_RMPP_TYPE_ABORT, IB_RMPP_STATUS_W2S);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osmv_rmpp_snd_error(p_send_ctx, IB_REMOTE_ERROR);
|
|
Packit |
13e616 |
goto dispatch_rmpp_snd_done;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Update the sender's window, and optionally wake up the sender thread
|
|
Packit |
13e616 |
* Note! A single ACK can acknowledge a whole range of segments: [WF..SEG_NUM]
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"ACK for seg_num #%d accepted.\n", seg_num);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (seg_num == old_wl) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"The send window [%d:%d] is totally acknowledged.\n",
|
|
Packit |
13e616 |
p_send_ctx->window_first, old_wl);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_send_ctx->window_first = seg_num + 1;
|
|
Packit |
13e616 |
p_send_ctx->window_last =
|
|
Packit |
13e616 |
(new_wl < total_segs) ? new_wl : total_segs;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Remove the response timeout event for the window */
|
|
Packit |
13e616 |
osmv_txn_remove_timeout_ev(h_bind, osmv_txn_get_key(p_txn));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Wake up the sending thread */
|
|
Packit |
13e616 |
cl_event_signal(&p_send_ctx->event);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
dispatch_rmpp_snd_done:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(p_bo->p_vendor->p_log);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* NAME __osmv_dispatch_rmpp_rcv()
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* DESCRIPTION MAD handling by an RMPP receiver (DATA/ABORT/STOP)
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static ib_api_status_t
|
|
Packit |
13e616 |
__osmv_dispatch_rmpp_rcv(IN osm_bind_handle_t h_bind,
|
|
Packit |
13e616 |
IN const ib_mad_t * p_mad,
|
|
Packit |
13e616 |
IN osmv_txn_ctx_t * p_txn,
|
|
Packit |
13e616 |
IN const osm_mad_addr_t * p_mad_addr)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
ib_api_status_t status = IB_SUCCESS;
|
|
Packit |
13e616 |
osmv_rmpp_recv_ctx_t *p_recv_ctx = osmv_txn_get_rmpp_recv_ctx(p_txn);
|
|
Packit |
13e616 |
osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
|
|
Packit |
13e616 |
boolean_t is_last1 = FALSE, is_last2 = FALSE;
|
|
Packit |
13e616 |
osm_madw_t *p_new_madw = NULL, *p_req_madw = NULL;
|
|
Packit |
13e616 |
ib_mad_t *p_mad_buf;
|
|
Packit |
13e616 |
uint32_t size = 0;
|
|
Packit |
13e616 |
uint64_t key = osmv_txn_get_key(p_txn);
|
|
Packit |
13e616 |
uint64_t tid = osmv_txn_get_tid(p_txn);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(p_bo->p_vendor->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (TRUE == osmv_rmpp_is_ack(p_mad)) {
|
|
Packit |
13e616 |
osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Not supposed to receive ACK's --> dropping the MAD\n");
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
goto dispatch_rmpp_rcv_done;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (TRUE == osmv_rmpp_is_abort_stop(p_mad)) {
|
|
Packit |
13e616 |
osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"__osmv_dispatch_rmpp_rcv: ERR 6504: "
|
|
Packit |
13e616 |
"The Remote Side stopped sending\n");
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
status = IB_REMOTE_ERROR;
|
|
Packit |
13e616 |
goto dispatch_rmpp_rcv_done;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
status = __osmv_dispatch_accept_seg(h_bind, p_txn, p_mad);
|
|
Packit |
13e616 |
switch (status) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
case IB_SUCCESS:
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Check wheter this is the legal last MAD */
|
|
Packit |
13e616 |
/* Criteria #1: the received MAD is marked last */
|
|
Packit |
13e616 |
is_last1 = osmv_rmpp_is_last(p_mad);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Criteria #2: the total accumulated length hits the advertised one */
|
|
Packit |
13e616 |
is_last2 = is_last1;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
size = osmv_rmpp_recv_ctx_get_byte_num_from_first(p_recv_ctx);
|
|
Packit |
13e616 |
if (size > 0) {
|
|
Packit |
13e616 |
is_last2 =
|
|
Packit |
13e616 |
(osmv_rmpp_recv_ctx_get_cur_byte_num(p_recv_ctx) >=
|
|
Packit |
13e616 |
size);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (is_last1 != is_last2) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osmv_rmpp_send_nak(h_bind, p_mad, p_mad_addr,
|
|
Packit |
13e616 |
IB_RMPP_TYPE_ABORT,
|
|
Packit |
13e616 |
IB_RMPP_STATUS_BAD_LEN);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
status = IB_ERROR;
|
|
Packit |
13e616 |
goto dispatch_rmpp_rcv_done;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* TBD Consider an optimization - sending an ACK
|
|
Packit |
13e616 |
* only for the last segment in the window
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
__osmv_dispatch_send_ack(h_bind, p_mad, p_txn, p_mad_addr);
|
|
Packit |
13e616 |
break;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
case IB_INSUFFICIENT_RESOURCES:
|
|
Packit |
13e616 |
/* An out-of-order segment received. Send the ACK anyway */
|
|
Packit |
13e616 |
__osmv_dispatch_send_ack(h_bind, p_mad, p_txn, p_mad_addr);
|
|
Packit |
13e616 |
status = IB_SUCCESS;
|
|
Packit |
13e616 |
goto dispatch_rmpp_rcv_done;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
case IB_INSUFFICIENT_MEMORY:
|
|
Packit |
13e616 |
osmv_rmpp_send_nak(h_bind, p_mad, p_mad_addr,
|
|
Packit |
13e616 |
IB_RMPP_TYPE_STOP, IB_RMPP_STATUS_RESX);
|
|
Packit |
13e616 |
goto dispatch_rmpp_rcv_done;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
default:
|
|
Packit |
13e616 |
/* Illegal return code */
|
|
Packit |
13e616 |
CL_ASSERT(FALSE);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (TRUE != is_last1) {
|
|
Packit |
13e616 |
osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"RMPP MADW assembly continues, TID=0x%" PRIx64 "\n", tid);
|
|
Packit |
13e616 |
goto dispatch_rmpp_rcv_done;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* This is the last packet. */
|
|
Packit |
13e616 |
if (0 == size) {
|
|
Packit |
13e616 |
/* The total size was not advertised in the first packet */
|
|
Packit |
13e616 |
size = osmv_rmpp_recv_ctx_get_byte_num_from_last(p_recv_ctx);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
NOTE: the received mad might not be >= 256 bytes.
|
|
Packit |
13e616 |
some MADs might contain several SA records but still be
|
|
Packit |
13e616 |
less then a full MAD.
|
|
Packit |
13e616 |
We have to use RMPP to send them over since on a regular
|
|
Packit |
13e616 |
"simple" MAD there is no way to know how many records were sent
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Build the MAD wrapper to be returned to the user.
|
|
Packit |
13e616 |
* The actual storage for the MAD is allocated there.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
p_new_madw =
|
|
Packit |
13e616 |
osm_mad_pool_get(p_bo->p_osm_pool, h_bind, size, p_mad_addr);
|
|
Packit |
13e616 |
if (NULL == p_new_madw) {
|
|
Packit |
13e616 |
osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
|
|
Packit |
13e616 |
"__osmv_dispatch_rmpp_rcv: ERR 6506: "
|
|
Packit |
13e616 |
"Out Of Memory - could not allocate %d bytes for the MADW\n",
|
|
Packit |
13e616 |
size);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
status = IB_INSUFFICIENT_MEMORY;
|
|
Packit |
13e616 |
goto dispatch_rmpp_rcv_done;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_req_madw = osmv_txn_get_madw(p_txn);
|
|
Packit |
13e616 |
p_mad_buf = osm_madw_get_mad_ptr(p_new_madw);
|
|
Packit |
13e616 |
status = osmv_rmpp_recv_ctx_reassemble_arbt_mad(p_recv_ctx, size,
|
|
Packit |
13e616 |
(uint8_t *) p_mad_buf);
|
|
Packit |
13e616 |
if (IB_SUCCESS != status) {
|
|
Packit |
13e616 |
osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
|
|
Packit |
13e616 |
"__osmv_dispatch_rmpp_rcv: ERR 6507: "
|
|
Packit |
13e616 |
"Internal error - could not reassemble the result MAD\n");
|
|
Packit |
13e616 |
goto dispatch_rmpp_rcv_done; /* What can happen here? */
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* The MAD is assembled, we are about to apply the callback.
|
|
Packit |
13e616 |
* Delete the transaction context, unless the transaction is double sided */
|
|
Packit |
13e616 |
if (FALSE == osmv_txn_is_rmpp_init_by_peer(p_txn)
|
|
Packit |
13e616 |
|| FALSE == osmv_mad_is_multi_resp(p_mad)) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osmv_txn_done(h_bind, key, FALSE);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"RMPP MADW %p assembly complete, TID=0x%" PRIx64 "\n", p_new_madw,
|
|
Packit |
13e616 |
tid);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_mad_buf->trans_id = cl_hton64(tid);
|
|
Packit |
13e616 |
osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Restoring the original TID to 0x%" PRIx64 "\n",
|
|
Packit |
13e616 |
cl_ntoh64(p_mad_buf->trans_id));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Finally, do the job! */
|
|
Packit |
13e616 |
p_bo->recv_cb(p_new_madw, p_bo->cb_context, p_req_madw);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
dispatch_rmpp_rcv_done:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(p_bo->p_vendor->p_log);
|
|
Packit |
13e616 |
return status;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* NAME __osmv_dispatch_accept_seg()
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* DESCRIPTION Store a DATA segment at the RMPP receiver side,
|
|
Packit |
13e616 |
* if one is received in order.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static ib_api_status_t
|
|
Packit |
13e616 |
__osmv_dispatch_accept_seg(IN osm_bind_handle_t h_bind,
|
|
Packit |
13e616 |
IN osmv_txn_ctx_t * p_txn, IN const ib_mad_t * p_mad)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
ib_api_status_t ret = IB_SUCCESS;
|
|
Packit |
13e616 |
uint32_t seg_num = cl_ntoh32(((ib_rmpp_mad_t *) p_mad)->seg_num);
|
|
Packit |
13e616 |
osmv_rmpp_recv_ctx_t *p_recv_ctx = osmv_txn_get_rmpp_recv_ctx(p_txn);
|
|
Packit |
13e616 |
osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
|
|
Packit |
13e616 |
uint64_t tid = osmv_txn_get_tid(p_txn);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(p_bo->p_vendor->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (seg_num != p_recv_ctx->expected_seg) {
|
|
Packit |
13e616 |
osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"TID 0x%" PRIx64 ": can't accept this segment (%d) - "
|
|
Packit |
13e616 |
"this is a Go-Back-N implementation\n", tid, seg_num);
|
|
Packit |
13e616 |
return IB_INSUFFICIENT_RESOURCES;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Store the packet's copy in the reassembly list.
|
|
Packit |
13e616 |
* Promote the expected segment counter.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
ret = osmv_rmpp_recv_ctx_store_mad_seg(p_recv_ctx, (uint8_t *) p_mad);
|
|
Packit |
13e616 |
if (IB_SUCCESS != ret) {
|
|
Packit |
13e616 |
return ret;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"TID 0x%" PRIx64 ": segment %d accepted\n", tid, seg_num);
|
|
Packit |
13e616 |
p_recv_ctx->expected_seg = seg_num + 1;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_EXIT(p_bo->p_vendor->p_log);
|
|
Packit |
13e616 |
return IB_SUCCESS;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* NAME __osmv_dispatch_send_ack()
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* DESCRIPTION
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* ISSUES
|
|
Packit |
13e616 |
* Consider sending the ACK from an async thread
|
|
Packit |
13e616 |
* if problems with the receiving side processing arise.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void
|
|
Packit |
13e616 |
__osmv_dispatch_send_ack(IN osm_bind_handle_t h_bind,
|
|
Packit |
13e616 |
IN const ib_mad_t * p_req_mad,
|
|
Packit |
13e616 |
IN osmv_txn_ctx_t * p_txn,
|
|
Packit |
13e616 |
IN const osm_mad_addr_t * p_mad_addr)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osmv_rmpp_recv_ctx_t *p_recv_ctx = osmv_txn_get_rmpp_recv_ctx(p_txn);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* ACK the segment # that was accepted */
|
|
Packit |
13e616 |
uint32_t seg_num = cl_ntoh32(((ib_rmpp_mad_t *) p_req_mad)->seg_num);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* NOTE! The receiver can publish the New Window Last (NWL) value
|
|
Packit |
13e616 |
* that is greater than the total number of segments to be sent.
|
|
Packit |
13e616 |
* It's the sender's responsibility to compute the correct number
|
|
Packit |
13e616 |
* of segments to send in the next burst.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
uint32_t nwl = p_recv_ctx->expected_seg + OSMV_RMPP_RECV_WIN - 1;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osmv_rmpp_send_ack(h_bind, p_req_mad, seg_num, nwl, p_mad_addr);
|
|
Packit |
13e616 |
}
|