[Openib-windows] RE: Anything new about the IPOIB arp check-in?

Fab Tillier ftillier at silverstorm.com
Wed Nov 30 22:50:10 PST 2005


Here's the code for getting the local port GUIDs and assigned IP addresses.

It's changed slightly from what you had in that it will return partial results
if the output buffer isn't large enough.  I've also eliminated the copy of the
input parameters as most of the cases didn't require it.  Other than that, the
functionality is as you had it though the code is restructured somewhat.

Let me know if you see any issues or not.  I should be able to have the other
two IOCTLs implemented tomorrow, and will test and hopefully get a patch out for
review by the end of the week before committing.

Thanks!

- Fab

static NTSTATUS
__ibat_get_ports(
    IN              IRP                         *pIrp,
    IN              IO_STACK_LOCATION           *pIoStack )
{
    IOCTL_IBAT_PORTS_IN     *pIn;
    IOCTL_IBAT_PORTS_OUT    *pOut;
    KLOCK_QUEUE_HANDLE      hdl;
    cl_list_item_t          *pItem;
    ipoib_adapter_t         *pAdapter;
    LONG                    nPorts;

    IPOIB_ENTER(IPOIB_DBG_IOCTL);

    if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=
        sizeof(IOCTL_IBAT_PORTS_IN) )
    {
        IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR, ("Invalid input buffer size.\n") );
        return STATUS_INVALID_PARAMETER;
    }
    
    if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength <
        sizeof(IOCTL_IBAT_PORTS_OUT) )
    {
        IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR, ("Invalid output buffer size.\n") );
        return STATUS_INVALID_PARAMETER;
    }

    pIn = pIrp->AssociatedIrp.SystemBuffer;
    pOut = pIrp->AssociatedIrp.SystemBuffer;

    if( pIn->Version != IBAT_IOCTL_VERSION )
    {
        IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR, ("Invalid version.\n") );
        return STATUS_INVALID_PARAMETER;
    }

    KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );
    nPorts = (LONG)cl_qlist_count( &g_ipoib.adapter_list );
    switch( nPorts )
    {
    case 0:
        cl_memclr( pOut->Ports, sizeof(pOut->Ports) );
        /* Fall through */
    case 1:
        pOut->Size = sizeof(IOCTL_IBAT_PORTS_OUT);
        break;

    default:
        pOut->Size = sizeof(IOCTL_IBAT_PORTS_OUT) + 
            (sizeof(IBAT_PORT_RECORD) * (nPorts - 1));
        break;
    }

    pIrp->IoStatus.Information = pOut->Size;

    if( pOut->Size > pIoStack->Parameters.DeviceIoControl.OutputBufferLength )
    {
        nPorts = 1 +
            (pIoStack->Parameters.DeviceIoControl.OutputBufferLength -
            sizeof(IOCTL_IBAT_PORTS_OUT)) / sizeof(IBAT_PORT_RECORD);

        pIrp->IoStatus.Information = sizeof(IOCTL_IBAT_PORTS_OUT) +
            ((nPorts - 1) * sizeof(IBAT_PORT_RECORD));
    }

    pOut->NumPorts = 0;
    pItem = cl_qlist_head( &g_ipoib.adapter_list );
    while( pOut->NumPorts != nPorts )
    {
        pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );
        pOut->Ports[pOut->NumPorts].CaGuid = pAdapter->guids.ca_guid;
        pOut->Ports[pOut->NumPorts].PortGuid = pAdapter->guids.port_guid;
        pOut->NumPorts++;

        pItem = cl_qlist_next( pItem );
    }

    KeReleaseInStackQueuedSpinLock( &hdl );
    return STATUS_SUCCESS;
}


static NTSTATUS
__ibat_get_ips(
    IN              IRP                         *pIrp,
    IN              IO_STACK_LOCATION           *pIoStack )
{
    IOCTL_IBAT_IP_ADDRESSES_IN  *pIn;
    IOCTL_IBAT_IP_ADDRESSES_OUT *pOut;
    KLOCK_QUEUE_HANDLE          hdl;
    cl_list_item_t              *pItem;
    ipoib_adapter_t             *pAdapter;
    LONG                        nIps, maxIps;
    size_t                      idx;
    net_address_item_t          *pAddr;
    UINT64                      PortGuid;

    IPOIB_ENTER(IPOIB_DBG_IOCTL);

    if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=
        sizeof(IOCTL_IBAT_IP_ADDRESSES_IN) )
    {
        IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR, ("Invalid input buffer size.\n") );
        return STATUS_INVALID_PARAMETER;
    }
    
    if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength <
        sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT) )
    {
        IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR, ("Invalid output buffer size.\n") );
        return STATUS_INVALID_PARAMETER;
    }

    pIn = pIrp->AssociatedIrp.SystemBuffer;
    pOut = pIrp->AssociatedIrp.SystemBuffer;

    if( pIn->Version != IBAT_IOCTL_VERSION )
    {
        IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR, ("Invalid version.\n") );
        return STATUS_INVALID_PARAMETER;
    }

    PortGuid = pIn->PortGuid;

    nIps = 0;
    pOut->AddressCount = 0;
    maxIps = 1 +
        ((pIoStack->Parameters.DeviceIoControl.OutputBufferLength -
        sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT)) / sizeof(IP_ADDRESS));

    KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );
    for( pItem = cl_qlist_head( &g_ipoib.adapter_list );
        pItem != cl_qlist_end( &g_ipoib.adapter_list );
        pItem = cl_qlist_next( pItem ) )
    {
        pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );
        if( PortGuid && pAdapter->guids.port_guid != PortGuid )
            continue;

        cl_obj_lock( &pAdapter->obj );
        nIps += cl_vector_get_size( &pAdapter->ip_vector );

        for( idx = 0;
            idx < cl_vector_get_size( &pAdapter->ip_vector );
            idx++ )
        {
            if( pOut->AddressCount == maxIps )
                break;

            pAddr = (net_address_item_t*)
                cl_vector_get_ptr( &pAdapter->ip_vector, idx );

            pOut->Address[pOut->AddressCount].IpVersion = 4;
            cl_memclr( &pOut->Address[pOut->AddressCount].Address,
                sizeof(IB_ADDRESS) );
            cl_memcpy( &pOut->Address[pOut->AddressCount].Address[12],
                pAddr->address, IPV4_ADDR_SIZE );

            pOut->AddressCount++;
        }
        cl_obj_lock( &pAdapter->obj );
    }

    pOut->Size = sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT);
    if( --nIps )
        pOut->Size += sizeof(IP_ADDRESS) * nIps;

    KeReleaseInStackQueuedSpinLock( &hdl );
    return STATUS_SUCCESS;
}




More information about the ofw mailing list