⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 protocol.c

📁 Vitual Ring Routing 管你知不知道
💻 C
📖 第 1 页 / 共 4 页
字号:
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs)
//
// (c) Microsoft Corporation. All rights reserved. 
//
// This file is part of the Microsoft Virtual Ring Routing distribution.
// You should have received a copy of the Microsoft Research Shared Source
// license agreement (MSR-SSLA) for this software; see the file "license.txt".
// If not, please see http://research.microsoft.com/vrr/license.htm,
// or write to Microsoft Research, One Microsoft Way, Redmond, WA 98052-6399.
//
// This file is derived from the Microsoft Research Mesh Connectivity Layer,
// available under the MSR-SSLA license, and downloadable from
// http://research.microsoft.com/mesh/.
//

#include "headers.h"

//* FindPhysicalAdapterFromIndex
//
//  Given an index, returns the physical adapter.
//
ProtocolAdapter *
FindPhysicalAdapterFromIndex(MiniportAdapter *VA, uint Index)
{
    ProtocolAdapter *PA;
    KIRQL OldIrql;

    KeAcquireSpinLock(&VA->Lock, &OldIrql);
    for (PA = VA->PhysicalAdapters;
         PA != NULL;
         PA = PA->Next) {
        //
        // Is this the desired physical adapter?
        //
        if (PA->Index == Index)
            break;
    }
    KeReleaseSpinLock(&VA->Lock, OldIrql);

    return PA;
}

//* FindFirstPhysicalAdapter
//
//  Returns the first physical adapter.
//
ProtocolAdapter *
FindFirstPhysicalAdapter(MiniportAdapter *VA, VRRIf *Index)
{
    ProtocolAdapter *PA;
    KIRQL OldIrql;
    uint IFIndex;

    KeAcquireSpinLock(&VA->Lock, &OldIrql);
    PA = VA->PhysicalAdapters;
    if (NULL != PA && NULL != Index) {
        VRRASSERT(PA->Index < 0x100);  // Must fit in VRRIf.
        *Index = (VRRIf)PA->Index;
    }
    KeReleaseSpinLock(&VA->Lock, OldIrql);
    if (NULL == PA) KdPrint(("FindFirstPhysicalAdapter(%u) returns NULL\n",*Index));
    
    return PA;
}

//* FindPhysicalAdapterFromGuid
//
//  Given a guid, returns the physical adapter.
//
ProtocolAdapter *
FindPhysicalAdapterFromGuid(MiniportAdapter *VA, const GUID *Guid)
{
    ProtocolAdapter *PA;
    KIRQL OldIrql;

    KeAcquireSpinLock(&VA->Lock, &OldIrql);
    for (PA = VA->PhysicalAdapters;
         PA != NULL;
         PA = PA->Next) {
        //
        // Is this the desired physical adapter?
        //
        if (RtlEqualMemory(Guid, &PA->Guid, sizeof(GUID)))
            break;
    }
    KeReleaseSpinLock(&VA->Lock, OldIrql);

    return PA;
}

//* ProtocolQueueFull
//
//  Returns TRUE if the transmit queue of the specified
//  interface is full.
//
boolint
ProtocolQueueFull(MiniportAdapter *VA, VRRIf OutIf)
{
    ProtocolAdapter *PA;

    PA = FindPhysicalAdapterFromIndex(VA, OutIf);
    return (PA != NULL) && (PA->CountSentOutstanding >= PROTOCOL_MAX_QUEUE);
}

//* ProtocolResetStatistics
//
//  Resets all counters and statistics gathering for the physical adapter.
//
//  The caller must hold a reference for the physical adapter
//  or have the virtual adapter locked.
//
void
ProtocolResetStatistics(ProtocolAdapter *PA)
{
    PA->PacketsSent = 0;
    PA->PacketsReceived = 0;
    PA->PacketsReceivedTD = 0;
    PA->PacketsReceivedFlat = 0;

    PA->CountPacketPoolFailure = 0;

    PA->MaxRecvOutstanding = PA->CountRecvOutstanding;
    PA->MaxSentOutstanding = PA->MaxSentOutstanding;
}

//* ProtocolRequestHelper
//
//  This is a utility routine to submit a general request to an NDIS
//  driver.  The caller specifes the request code (OID), a buffer and
//  a length.  This routine allocates a request structure, fills it in,
//  and submits the request.
//
NDIS_STATUS
ProtocolRequestHelper(
    ProtocolAdapter *PA,
    NDIS_REQUEST_TYPE RT,   // Type of request to be done (Set or Query).
    NDIS_OID OID,           // Value to be set/queried.
    void *Info,             // Pointer to the buffer to be passed.
    uint Length,            // Length of data in above buffer.
    uint *Needed)           // Location to fill in with bytes needed in buffer.
{
    ProtocolRequest Request;
    NDIS_STATUS Status;

    // Now fill it in.
    Request.ContextOnStack = TRUE;
    Request.Request.RequestType = RT;
    if (RT == NdisRequestSetInformation) {
        Request.Request.DATA.SET_INFORMATION.Oid = OID;
        Request.Request.DATA.SET_INFORMATION.InformationBuffer = Info;
        Request.Request.DATA.SET_INFORMATION.InformationBufferLength = Length;
    } else {
        Request.Request.DATA.QUERY_INFORMATION.Oid = OID;
        Request.Request.DATA.QUERY_INFORMATION.InformationBuffer = Info;
        Request.Request.DATA.QUERY_INFORMATION.InformationBufferLength = Length;
    }

    //
    // Note that we can NOT use PA->Event and PA->Status here.
    // There may be multiple concurrent ProtocolRequestHelper calls.
    //

    KeInitializeEvent(&Request.Event, SynchronizationEvent, FALSE);

    NdisRequest(&Status, PA->Handle, &Request.Request);

    if (Status == NDIS_STATUS_PENDING) {
        (void) KeWaitForSingleObject(&Request.Event, UserRequest,
                                     KernelMode, FALSE, NULL);
        Status = Request.Status;
    }

    if (Needed != NULL)
        *Needed = Request.Request.DATA.QUERY_INFORMATION.BytesNeeded;

    return Status;
}

//* ProtocolQuery
//
//  Returns information about the physical adapter.
//
void
ProtocolQuery(
    ProtocolAdapter *PA,
    VRR_INFO_PHYSICAL_ADAPTER *Info)
{
    NDIS_STATUS Status;

    RtlCopyMemory(Info->Address, PA->Address, sizeof(PhysicalAddress));
    Info->MTU = PA->MaxFrameSize;
    Info->Promiscuous = PA->Promiscuous;
    Info->ReceiveOnly = PA->ReceiveOnly;
    Info->Channel = PA->Channel;
    Info->Bandwidth = PA->Bandwidth;
    Info->SupportsQuerySibTable = PA->SupportsQuerySibTable;

    Info->PacketsSent = PA->PacketsSent;
    Info->PacketsReceived = PA->PacketsReceived;
    Info->PacketsReceivedTD = PA->PacketsReceivedTD;
    Info->PacketsReceivedFlat = PA->PacketsReceivedFlat;

    Info->CountPacketPoolFailure = PA->CountPacketPoolFailure;

    Info->CountRecvOutstanding = PA->CountRecvOutstanding;
    Info->MaxRecvOutstanding = PA->MaxRecvOutstanding;
    Info->CountSentOutstanding = PA->CountSentOutstanding;
    Info->MaxSentOutstanding = PA->MaxSentOutstanding;
    Info->NDISPacketPoolUsage = NdisPacketPoolUsage(PA->PacketPool);

    Status = ProtocolRequestHelper(PA, NdisRequestQueryInformation,
                                   OID_802_11_BSSID,
                                   &Info->W.BSSID, sizeof Info->W.BSSID,
                                   NULL);
    if (Status != NDIS_STATUS_SUCCESS)
        goto Ethernet;

    Info->Type = VRR_PHYSICAL_ADAPTER_802_11;

    Status = ProtocolRequestHelper(PA, NdisRequestQueryInformation,
                                   OID_802_11_SSID,
                                   &Info->W.SSID, sizeof Info->W.SSID,
                                   NULL);
    if (Status != NDIS_STATUS_SUCCESS) {
        KdPrint(("VRR!ProtocolQuery: OID_802_11_SSID: %x\n", Status));
        Info->W.SSID.SsidLength = 0;
    }

    Status = ProtocolRequestHelper(PA, NdisRequestQueryInformation,
                                   OID_802_11_INFRASTRUCTURE_MODE,
                                   &Info->W.Mode, sizeof Info->W.Mode,
                                   NULL);
    if (Status != NDIS_STATUS_SUCCESS) {
        KdPrint(("VRR!ProtocolQuery: OID_802_11_INFRASTRUCTURE_MODE: %x\n", Status));
        Info->W.Mode = (NDIS_802_11_NETWORK_INFRASTRUCTURE) -1;
    }

    Status = ProtocolRequestHelper(PA, NdisRequestQueryInformation,
                                   OID_802_11_CONFIGURATION,
                                   &Info->W.Radio, sizeof Info->W.Radio,
                                   NULL);
    if (Status != NDIS_STATUS_SUCCESS) {
        KdPrint(("VRR!ProtocolQuery: OID_802_11_CONFIGURATION: %x\n", Status));
        memset(&Info->W.Radio, 0, sizeof Info->W.Radio);
    }

    Status = ProtocolRequestHelper(PA, NdisRequestQueryInformation,
                                   OID_802_11_POWER_MODE,
                                   &Info->W.PowerMode,
                                   sizeof Info->W.PowerMode,
                                   NULL);
    if (Status != NDIS_STATUS_SUCCESS) {
        KdPrint(("VRR!ProtocolQuery: OID_802_11_POWER_MODE: %x\n", Status));
        Info->W.PowerMode = (NDIS_802_11_POWER_MODE) -1;
    }

    Status = ProtocolRequestHelper(PA, NdisRequestQueryInformation,
                                   OID_802_11_TX_POWER_LEVEL,
                                   &Info->W.TxPowerLevel,
                                   sizeof Info->W.TxPowerLevel,
                                   NULL);
    if (Status != NDIS_STATUS_SUCCESS) {
        KdPrint(("VRR!ProtocolQuery: OID_802_11_TX_POWER_LEVEL: %x\n", Status));
        Info->W.TxPowerLevel = 0;
    }

    Status = ProtocolRequestHelper(PA, NdisRequestQueryInformation,
                                   OID_802_11_RTS_THRESHOLD,
                                   &Info->W.RTSThreshold,
                                   sizeof Info->W.RTSThreshold,
                                   NULL);
    if (Status != NDIS_STATUS_SUCCESS) {
        KdPrint(("VRR!ProtocolQuery: OID_802_11_RTS_THRESHOLDL: %x\n", Status));
        Info->W.RTSThreshold = (NDIS_802_11_RTS_THRESHOLD) -1;
    }

    Status = ProtocolRequestHelper(PA, NdisRequestQueryInformation,
                                   OID_802_11_STATISTICS,
                                   &Info->W.Statistics,
                                   sizeof Info->W.Statistics,
                                   NULL);
    if (Status != NDIS_STATUS_SUCCESS) {
        KdPrint(("VRR!ProtocolQuery: OID_802_11_STATISTICS: %x\n", Status));
        memset(&Info->W.Statistics, 0, sizeof Info->W.Statistics);
    }

    RtlZeroMemory(&Info->W.GenVendorDescription, sizeof Info->W.GenVendorDescription);
    Status = ProtocolRequestHelper(PA, NdisRequestQueryInformation,
                                   OID_GEN_VENDOR_DESCRIPTION,
                                   &Info->W.GenVendorDescription,
                                   sizeof(Info->W.GenVendorDescription) - 1,
                                   NULL);
    if (Status != NDIS_STATUS_SUCCESS) {
        KdPrint(("VRR!ProtocolQuery: OID_GEN_VENDOR_DESCRIPTION: %x\n", Status));
    }

    RtlZeroMemory(&Info->AthMSRC,sizeof(MSRC_OID_Info_Adapter));
    if (PA->SupportsQuerySibTable == TRUE) {
        Status = ProtocolRequestHelper(PA, NdisRequestQueryInformation,
                                       OID_MSRC_QUERY_ADAPTER,
                                       &Info->AthMSRC,
                                       sizeof(MSRC_OID_Info_Adapter),
                                       NULL);
        if (Status != NDIS_STATUS_SUCCESS) {
            KdPrint(("VRR!ProtocolQuery: OID_MSRC_QUERY_ADAPTER: %x\n", Status));
        }
    }

    return;

Ethernet:
    Info->Type = VRR_PHYSICAL_ADAPTER_ETHERNET;
}

//* ProtocolControl
//
//  Sets protocol configuration parameters from the structure.
//
//  Return values:
//      STATUS_INVALID_PARAMETER_3      Bad Channel.
//      STATUS_INVALID_PARAMETER_4      Bad Bandwidth.
//      STATUS_SUCCESS
//
NTSTATUS
ProtocolControl(
    ProtocolAdapter *PA,
    VRR_CONTROL_PHYSICAL_ADAPTER *Control)
{
    //
    // Check parameters before any updates.
    //

    if (Control->Channel != 0) {
        if (Control->Channel >= 256)
            return STATUS_INVALID_PARAMETER_3;
    }

    if (Control->Bandwidth != 0) {
        if (((Control->Bandwidth >> 2) >= 1024) ||
            ((Control->Bandwidth >> 2) == 0))
            return STATUS_INVALID_PARAMETER_4;
    }

    //
    // Update the attributes of the physical adapter.
    //

    ExAcquireFastMutex(&PA->Mutex);

    if (Control->ReceiveOnly != (boolint) -1)
        PA->ReceiveOnly = Control->ReceiveOnly;

    if (Control->Channel != 0) {
        PA->Channel = Control->Channel;
        PA->ChannelConfigured = TRUE;
    }

    if (Control->Bandwidth != 0) {
        PA->Bandwidth = Control->Bandwidth;
        PA->BandwidthConfigured = TRUE;
    }

    ExReleaseFastMutex(&PA->Mutex);
    return STATUS_SUCCESS;
}

//* ProtocolOpenAdapterComplete
//
//  Called by NDIS when an NdisOpenAdapter completes.
//
void
ProtocolOpenAdapterComplete(
    NDIS_HANDLE Handle,       // Binding handle.
    NDIS_STATUS Status,       // Final status of command.
    NDIS_STATUS ErrorStatus)  // Extra status for some errors.
{
    ProtocolAdapter *PA = (ProtocolAdapter *)Handle;

    UNREFERENCED_PARAMETER(ErrorStatus);

    KdPrint(("VRR!ProtocolOpenAdapterComplete(VA %p PA %p)\n",
             PA->VirtualAdapter, PA));

    //
    // Signal whoever is waiting and pass the final status.
    //
    PA->Status = Status;
    KeSetEvent(&PA->Event, 0, FALSE);
}

//* ProtocolCloseAdapterComplete
//
//  Called by NDIS when an NdisCloseAdapter completes.
//
//  At this point, NDIS guarantees that it has no other outstanding
//  calls to us.
//
void
ProtocolCloseAdapterComplete(
    NDIS_HANDLE Handle,  // Binding handle.
    NDIS_STATUS Status)  // Final status of command.
{
    ProtocolAdapter *PA = (ProtocolAdapter *)Handle;
    KdPrint(("VRR!ProtocolCloseAdapterComplete(VA %p PA %p)\n",
             PA->VirtualAdapter, PA));

    //
    // Signal whoever is waiting and pass the final status.
    //
    PA->Status = Status;
    KeSetEvent(&PA->Event, 0, FALSE);
}

//* ProtocolTransmitComplete
//
//  Called by NDIS when a send completes.
//
void
ProtocolTransmitComplete(
    NDIS_HANDLE Handle,   // Binding handle.
    PNDIS_PACKET Packet,  // Packet that was sent.
    NDIS_STATUS Status)   // Final status of send.
{
    ProtocolAdapter *PA = (ProtocolAdapter *)Handle;

    VRRASSERT(PC(Packet)->PA == PA);

    PrintfNdisStatus(__FUNCTION__,Status,FALSE);

    SaveCompletionTime(PA->VirtualAdapter, Packet, Status);

    (*PC(Packet)->TransmitComplete)(PA->VirtualAdapter, Packet, Status);

    InterlockedDecrement((PLONG)&PA->CountSentOutstanding);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -