singrdk/base/Services/NetStack/NetDrivers/LoopbackAdapter.cs

199 lines
5.8 KiB
C#
Raw Permalink Normal View History

2008-11-17 18:29:00 -05:00
///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity / Netstack
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: LoopbackAdapter.cs
//
// #define DEBUG_LOOPBACK
using System;
using System.Collections;
using System.Diagnostics;
using System.Threading;
using Microsoft.Singularity;
using Drivers.Net;
using NetStack.Common;
namespace NetStack.NetDrivers
{
public class LoopbackAdapter : IAdapter
{
public const int RingSize = 256; // TODO: Why public?
static int instantiations = 0;
private EthernetAddress address;
private AutoResetEvent writeEvent;
private AutoResetEvent readEvent;
private Queue rxBuffer;
private int txDeliveryComplete;
private int rxAvailable;
public LoopbackAdapter()
{
LoopbackAdapter.instantiations++;
//
// Microsoft OUI 00:50:F2:xx:xx:xx
// It doesn't really matter, but something other
// than zero is preferable for testing purposes.
//
int x = 0xFFFFFF - instantiations;
address = new EthernetAddress(0x00, 0x50, 0xF2,
(byte)((x >> 16) & 0xFF),
(byte)((x >> 8) & 0xFF),
(byte)((x >> 0) & 0xFF));
writeEvent = new AutoResetEvent(false);
readEvent = new AutoResetEvent(false);
rxBuffer = new Queue(LoopbackAdapter.RingSize);
txDeliveryComplete = 0;
rxAvailable = 0;
}
public string DriverName
{
get { return "Loopback Adapter"; }
}
public string DriverVersion
{
get { return "0.1"; }
}
public EthernetAddress HardwareAddress
{
get { return address; }
}
public uint LinkSpeed
{
get { return 1000 * 1000 * 1000; }
}
public int TxSlotsFree
{
get {
int txSlotsFree;
lock (this) {
txSlotsFree = LoopbackAdapter.RingSize
- rxBuffer.Count
- txDeliveryComplete;
DebugStub.Assert(txSlotsFree >= 0);
}
return txSlotsFree;
}
}
public void GetReceivedPackets(Queue! outQueue)
{
lock (this) {
DebugStub.Assert(rxAvailable >= 0 &&
rxAvailable <= LoopbackAdapter.RingSize);
// Move Receive packets to 'outQueue'.
Object packet;
while (rxAvailable > 0 &&
(packet = rxBuffer.Dequeue()) != null) {
outQueue.Enqueue(packet);
txDeliveryComplete++;
rxAvailable--;
}
DebugStub.Assert(rxAvailable >= 0 &&
rxAvailable <= LoopbackAdapter.RingSize);
DebugStub.Assert(
txDeliveryComplete <= LoopbackAdapter.RingSize);
DebugPrint("Loopback: GetReceivedPackets() -> {0}\n",
__arglist(outQueue.Count));
DebugPrintStatus();
readEvent.Reset();
writeEvent.Set();
}
}
[Conditional("DEBUG_LOOPBACK")]
private void DebugPrintStatus()
{
DebugStub.Print("-- queued: {0} txComplete {1}\n",
__arglist(rxBuffer.Count,
txDeliveryComplete));
}
[Conditional("DEBUG_LOOPBACK")]
private static void DebugPrint(string format, __arglist)
{
DebugStub.Print(format, new ArgIterator(__arglist));
}
[Conditional("DEBUG_LOOPBACK")]
private static void DebugPrint(string format)
{
DebugStub.Print(format);
}
public uint GetTransmittedPackets()
{
lock (this) {
DebugPrint("Loopback: GetTransmittedPackets() -> {0}\n",
__arglist(txDeliveryComplete));
DebugPrintStatus();
uint count = (uint)txDeliveryComplete;
txDeliveryComplete = 0;
return count;
}
}
public void PopulateRxRing(NetPacket! packet)
{
DebugPrint("Loopback: PopulateRxRing()\n");
DebugPrintStatus();
// Do nothing
}
public void PopulateTxRing(NetPacket[]! packets, uint count)
{
lock (this) {
DebugPrint("Loopback: PopulateTxRing({0})\n",
__arglist(count));
DebugPrintStatus();
for (uint i = 0; i < count; i++) {
NetPacket! packet = (!)packets[i];
byte[]! txdata = (!)packet.ToContiguous();
rxBuffer.Enqueue(new NetPacket(txdata));
rxAvailable++;
}
DebugStub.Assert(rxBuffer.Count <= RingSize);
writeEvent.Reset();
if (rxBuffer.Count != 0) {
readEvent.Set();
}
}
}
public WaitHandle GetReadHandle()
{
return readEvent;
}
public WaitHandle GetWriteHandle()
{
return writeEvent;
}
}
}