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

📄 miniport.c

📁 Vitual Ring Routing 管你知不知道
💻 C
📖 第 1 页 / 共 5 页
字号:
// -*- 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"

static void
MiniportRescheduleTimeoutHelper(MiniportAdapter *VA, Time Now, Time Timeout);

uint NextVirtualAdapterIndex;
NDIS_HANDLE MiniportHandle;
NDIS_HANDLE OurDeviceHandle;

struct MiniportAdapters MiniportAdapters;

#define MINIPORT_MAX_MULTICAST_ADDRESS  16
//#define MINIPORT_MAX_FRAME_SIZE         1280 // Original LQSR. See also "MINIPORT_MAX_FRAME_SIZE (1280) bytes"
//
// VRR does not piggyback control messages on data packets.
// This is reasonable because there is less control traffic.
// Aside from the VRR header and advertise the rest as MTU. 
//
#define MINIPORT_HEADER_SIZE            sizeof(EtherHeader)
#define MINIPORT_MAX_FRAME_SIZE         (PROTOCOL_MIN_FRAME_SIZE - MINIPORT_HEADER_SIZE - sizeof(VRRHeader)) 
#define MINIPORT_MAX_LOOKAHEAD          0xffff

#define MAX_RECV_QUEUE_SIZE 16

#define MINIPORT_TIMEOUT        100     // Milliseconds.

#define DEFAULT_METRIC WCETT 

static void
MiniportTimeout(PKDPC Dpc, void *Context, void *Unused1, void *Unused2);

//* FindVirtualAdapterFromIndex
//
//  Given an index, returns the virtual adapter.
//
MiniportAdapter *
FindVirtualAdapterFromIndex(uint Index)
{
    MiniportAdapter *VA;
    KIRQL OldIrql;

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

    return VA;
}

//* FindVirtualAdapterFromGuid
//
//  Given a guid, returns the virtual adapter.
//
MiniportAdapter *
FindVirtualAdapterFromGuid(const GUID *Guid)
{
    MiniportAdapter *VA;
    KIRQL OldIrql;

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

    return VA;
}

//* MiniportReadOrCreateAdapterAddress
//
//  Reads a virtual address from the registry,
//  or if the address is not present, creates a new address
//  and persists it in the registry.
//
NDIS_STATUS
MiniportReadOrCreateAdapterAddress(
    IN HANDLE KeyHandle,
    OUT VirtualAddress Address)
{
    NTSTATUS Status;

    Status = GetRegNetworkAddress(KeyHandle, L"NetworkAddress", Address);
    if (! NT_SUCCESS(Status)) {

        //
        // Create a pseudo-random address.
        //
        GetRandom(Address, VIRTUAL_ADDR_LENGTH);

        //
        // Clear the individual/group bit and
        // the local/universal bit:
        // We want a universal individual address.
        //
        IEEE_802_ADDR_CLEAR_GROUP(Address);
        IEEE_802_ADDR_CLEAR_LOCAL(Address);

        //
        // Write the new address to the registry.
        //
        Status = SetRegNetworkAddress(KeyHandle, L"NetworkAddress", Address);
        if (! NT_SUCCESS(Status)) {
            KdPrint(("VRR!SetRegNetworkAddress -> %x\n", Status));
            return NDIS_STATUS_FAILURE;
        }
    }

    return NDIS_STATUS_SUCCESS;
}

//* MiniportIsInfinite
//
//  Returns TRUE if the link metric indicates that the link
//  is effectively broken.
//
boolint
MiniportIsInfinite(uint Metric)
{
    return Metric == (uint)-1;
}

//* MiniportConvMetric
//
//  Converts a link metric to a path metric.
//
uint
MiniportConvMetric(uint LinkMetric)
{
    return LinkMetric;
}

//* MiniportPathMetric
//
//  Calculates the path metric of an array of links,
//  by summing the metrics of the links.
//
//  Called with the link cache locked.
//
uint
MiniportPathMetric(
    MiniportAdapter *VA,
    Link **Hops,
    uint NumHops)
{
    uint Metric;
    uint New;
    uint i;

    Metric = 0;
    for (i = 0; i < NumHops; i++) {
        //
        // Check for a broken link.
        //
        if ((*VA->IsInfinite)(Hops[i]->Metric)) {
            Metric = (uint)-1;
            break;
        }

        //
        // Check for overflow.
        //
        New = Metric + (*VA->ConvMetric)(Hops[i]->Metric);
        if (New < Metric) {
            Metric = (uint)-1;
            break;
        }
        Metric = New;
    }
    return Metric;
}

//* MiniportInitLinkMetric
//
//  Initialize metric information for a new link.
//
void 
MiniportInitLinkMetric(
    MiniportAdapter *VA,
    int SNode,
    Link *Link, 
    Time Now)
{
    UNREFERENCED_PARAMETER(VA);
    UNREFERENCED_PARAMETER(SNode);
    UNREFERENCED_PARAMETER(Now);

    Link->Metric = 1;
}

//* MiniportPersistControl
//
//  Writes configuration parameters to the registry.
//
NTSTATUS
MiniportPersistControl(
    MiniportAdapter *VA,
    VRR_CONTROL_VIRTUAL_ADAPTER *Control)
{
    NTSTATUS Status;
    HANDLE DeviceKey;
    HANDLE Key;

    //
    // We do not need to validate the configuration parameters.
    // They will be validated after being read from the registry.
    //

    Status = IoOpenDeviceRegistryKey(VA->PhysicalDeviceObject,
                                     PLUGPLAY_REGKEY_DRIVER,
                                     GENERIC_READ,
                                     &DeviceKey);
    if (! NT_SUCCESS(Status))
        return Status;

    Status = OpenRegKey(&Key, DeviceKey, L"Parameters", OpenRegKeyCreate);
    ZwClose(DeviceKey);
    if (! NT_SUCCESS(Status))
        return Status;

    if (Control->Snooping != (uint)-1) {
        Status = SetRegDWORDValue(Key, L"Snooping", Control->Snooping);
        if (! NT_SUCCESS(Status))
            goto CloseReturn;
    }

    if (Control->ArtificialDrop != (uint)-1) {
        Status = SetRegDWORDValue(Key, L"ArtificialDrop",
                                  Control->ArtificialDrop);
        if (! NT_SUCCESS(Status))
            goto CloseReturn;
    }

    if (Control->Crypto != (uint)-1) {
        Status = SetRegDWORDValue(Key, L"Crypto", Control->Crypto);
        if (! NT_SUCCESS(Status))
            goto CloseReturn;
    }

    if (VRR_KEY_PRESENT(Control->CryptoKeyMAC)) {
        Status = SetRegBinaryValue(Key, L"CryptoKeyMAC",
                        Control->CryptoKeyMAC, sizeof Control->CryptoKeyMAC);
        if (! NT_SUCCESS(Status))
            goto CloseReturn;
    }

    if (VRR_KEY_PRESENT(Control->CryptoKeyAES)) {
        Status = SetRegBinaryValue(Key, L"CryptoKeyAES",
                        Control->CryptoKeyAES, sizeof Control->CryptoKeyAES);
        if (! NT_SUCCESS(Status))
            goto CloseReturn;
    }

    if (Control->LinkTimeout != (uint)-1) {
        Status = SetRegDWORDValue(Key, L"LinkTimeout", Control->LinkTimeout);
        if (! NT_SUCCESS(Status))
            goto CloseReturn;
    }

    if (Control->MetricType != (uint)-1) {
        Status = SetRegDWORDValue(Key, L"MetricType", Control->MetricType);
        if (! NT_SUCCESS(Status))
            goto CloseReturn;
    }

    switch (Control->MetricType) {

    case METRIC_TYPE_PKTPAIR:
        if (Control->MetricParams.PktPair.Alpha != (uint)-1) {
            Status = SetRegDWORDValue(Key, L"Alpha",
                                    Control->MetricParams.PktPair.Alpha);
            if (! NT_SUCCESS(Status))
                goto CloseReturn;
        }
        if (Control->MetricParams.PktPair.ProbePeriod != (uint)-1) {
            Status = SetRegDWORDValue(Key, L"ProbePeriod",
                                    Control->MetricParams.PktPair.ProbePeriod);
            if (! NT_SUCCESS(Status))
                goto CloseReturn;
        }
        if (Control->MetricParams.PktPair.PenaltyFactor != (uint)-1) {
            Status = SetRegDWORDValue(Key, L"PenaltyFactor",
                                    Control->MetricParams.PktPair.PenaltyFactor);
            if (! NT_SUCCESS(Status))
                goto CloseReturn;
        }
        break;

    case METRIC_TYPE_WCETT:
        if (Control->MetricParams.Wcett.Alpha != (uint)-1) {
            Status = SetRegDWORDValue(Key, L"Alpha",
                                    Control->MetricParams.Wcett.Alpha);
            if (! NT_SUCCESS(Status))
                goto CloseReturn;
        }
        if (Control->MetricParams.Wcett.PenaltyFactor != (uint)-1) {
            Status = SetRegDWORDValue(Key, L"PenaltyFactor",
                                    Control->MetricParams.Wcett.PenaltyFactor);
            if (! NT_SUCCESS(Status))
                goto CloseReturn;
        }
        if (Control->MetricParams.Wcett.LossInterval != (uint)-1) {
            Status = SetRegDWORDValue(Key, L"LossInterval",
                                    Control->MetricParams.Wcett.LossInterval);
            if (! NT_SUCCESS(Status))
                goto CloseReturn;
        }
        if (Control->MetricParams.Wcett.Beta != (uint)-1) {
            Status = SetRegDWORDValue(Key, L"Beta",
                                    Control->MetricParams.Wcett.Beta);
            if (! NT_SUCCESS(Status))
                goto CloseReturn;
        }
        if (Control->MetricParams.Wcett.PktPairProbePeriod != (uint)-1) {
            Status = SetRegDWORDValue(Key, L"PktPairProbePeriod",
                                    Control->MetricParams.Wcett.PktPairProbePeriod);
            if (! NT_SUCCESS(Status))
                goto CloseReturn;
        }
        if (Control->MetricParams.Wcett.PktPairMinOverProbes != (uint)-1) {
            Status = SetRegDWORDValue(Key, L"PktPairMinOverProbes",
                                    Control->MetricParams.Wcett.PktPairMinOverProbes);
            if (! NT_SUCCESS(Status))
                goto CloseReturn;
        }
        break;
    }

    Status = STATUS_SUCCESS;
CloseReturn:
    ZwClose(Key);
    return Status;
}

//* MiniportReadControl
//
//  Reads configuration parameters from the registry.
//
void
MiniportReadControl(
    MiniportAdapter *VA,
    VRR_CONTROL_VIRTUAL_ADAPTER *Control)
{
    NTSTATUS Status;
    HANDLE DeviceKey;
    HANDLE Key;

    //
    // We must always return an initialized Control structure.
    //
    VRR_INIT_CONTROL_VIRTUAL_ADAPTER(Control);

    Status = IoOpenDeviceRegistryKey(VA->PhysicalDeviceObject,
                                     PLUGPLAY_REGKEY_DRIVER,
                                     GENERIC_READ,
                                     &DeviceKey);
    if (! NT_SUCCESS(Status))
        return;

    Status = OpenRegKey(&Key, DeviceKey, L"Parameters", OpenRegKeyCreate);
    ZwClose(DeviceKey);
    if (! NT_SUCCESS(Status))
        return;

    //
    // Read configuration parameters.
    //

    (void) GetRegDWORDValue(Key, L"Snooping",
                            (PULONG)&Control->Snooping);
    (void) GetRegDWORDValue(Key, L"ArtificialDrop",
                            (PULONG)&Control->ArtificialDrop);

    (void) GetRegDWORDValue(Key, L"Crypto",
                            (PULONG)&Control->Crypto);
    (void) GetRegBinaryValue(Key, L"CryptoKeyMAC",
                Control->CryptoKeyMAC, sizeof Control->CryptoKeyMAC);
    (void) GetRegBinaryValue(Key, L"CryptoKeyAES",
                Control->CryptoKeyAES, sizeof Control->CryptoKeyAES);

    (void) GetRegDWORDValue(Key, L"LinkTimeout",
                            (PULONG)&Control->LinkTimeout);

    (void) GetRegDWORDValue(Key, L"MetricType",
                            (PULONG)&Control->MetricType);
    switch (Control->MetricType) {

⌨️ 快捷键说明

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