private void TxExchange() { int toCount = 0; int fromCount = 0; NicDeviceContract /*.Imp*/ imp = (NicDeviceContract)nicChannel.Acquire(); try { PacketFifo src = this.txFifo.Acquire(); PacketFifo free = this.txFreeFifo.Acquire(); toCount = src.Count; try { src = imp.GiveTxPacketsToDevice(src); fromCount = src.Count; free.Push(src); } finally { this.txFreeFifo.Release(free); this.txFifo.Release(src); } } catch (Exception e) { DebugStub.Print("TxExchange FAILED arg {0}\n", DebugStub.ArgList(e.ToString())); DebugStub.Break(); } finally { nicChannel.Release(imp); } DebugPrint("TxExchange out: {0} in: {1}\n", toCount, fromCount); }
//push a single packet onto the ring void IAdapter.PopulateTxRing(Bytes header, Bytes data) { try { PacketFifo txFree = this.txFreeFifo.Acquire(); PacketFifo txToDevice = this.txFifo.Acquire(); DebugPrint("populate tx ring\n"); try { Packet packet = txFree.Pop(); packet.SetFragment(0, header); packet.SetFragment(1, data); txToDevice.Push(packet); } finally { this.txFreeFifo.Release(txFree); this.txFifo.Release(txToDevice); } } catch (Exception e) { DebugStub.Print("Populate tx ring failed?? {0}\n", DebugStub.ArgList(e)); DebugStub.Break(); } //When to exchange? //how do we best manage the tradeoff of throughput and latency? //to begin let's just send one at a time. //I think i'd rather have another thread.... using (thisLock.Lock()) { TxExchange(); } }
/////////////////////////////////////////////////////////////////////// // // Tx buffer operations // internal void PopulateTsmtBuffer(PacketFifo fromUser) { DebugStub.Assert(this.ioRunning); // since no transmit interrupts are sent, we must check for // transmission events here if (txRingBuffer.NewTransmitEvent()) { NicEventType ev = NicEventType.TransmitEvent; if (eventRelay != null) { eventRelay.ForwardEvent(ev); } } using (txRingBuffer.thisLock.Lock()) { while (fromUser.Count > 0) { Packet packet = fromUser.Pop(); txRingBuffer.LockedPushTsmtBuffer(packet); } // update hardware tail pointer // so that hardware knows it has new packets to transmit Write32(Register.TSMT_DESC_TAIL, txRingBuffer.Head); // sw head is hw tail } }
private Packet MakePacketFromDescriptor(ulong controlBits) { PacketFifo inDevPkts = txPacketsInDevice.Acquire(); Packet packet = inDevPkts.Pop(); // int length = (int) ((controlBits & TxDescriptor.LENGTH_MASK) // >> TxDescriptor.LENGTH_SHIFT); int stat_err = (int)((controlBits & TxDescriptor.ERR_STAT_MASK) >> TxDescriptor.ERR_STAT_SHIFT); //DebugStub.Assert(packet.GetFragmentVirtualAddress(0) == fragmentVirtAddr); if (((TxStatErrFields.LATE_COLLISION | TxStatErrFields.EXCESS_COLLISIONS | TxStatErrFields.TRANSMIT_UNDERRUN) & stat_err) == 0) { packet.FromDeviceFlags = FromDeviceFlags.TransmitSuccess; } else { packet.FromDeviceFlags = FromDeviceFlags.TransmitError; } txPacketsInDevice.Release(inDevPkts); return(packet); }
private Packet MakePacketFromDescriptor(DmaMemory mem, ulong controlBits) { PacketFifo inDevPkts = rxPacketsInDevice.Acquire(); Packet packet = inDevPkts.Pop(); int length = (int)((controlBits & RxDescriptor.LENGTH_MASK) >> RxDescriptor.LENGTH_SHIFT); uint stat_err = (uint)((controlBits & RxDescriptor.ERR_STAT_MASK) >> RxDescriptor.ERR_STAT_SHIFT); // can't deal with fragments yet if ((stat_err & RxErrStatFields.END_OF_PACKET) == 0) { INucleusCalls.DebugPrintHex(40, 0xd0); DebugStub.Print("FRAGMENT\n"); throw new Exception(); } //DebugStub.Assert((stat_err & RxErrStatFields.END_OF_PACKET) != 0); //DebugStub.Assert(packet.GetFragmentVirtualAddress(0) == fragmentVirtAddr); packet.FromDeviceFlags = GetRecvPktFlags(stat_err); packet.SetFragment(0, mem.BytesRef(0, length)); rxPacketsInDevice.Release(inDevPkts); return(packet); }
private void RxProvision() { PacketFifo toDevice = this.rxFifo.Acquire(); RxProvisionInternal(toDevice); this.rxFifo.Release(toDevice); }
private void RxProvisionInternal(PacketFifo toDevice) { for (int i = 0; i < toDevice.Capacity; i++) { toDevice.Push( new Packet( new Bytes(new byte[this.mtu]) ) ); } }
internal void LockedDrainRecvBuffer(PacketFifo toUser) { DmaMemory mem; ulong controlBits; while (rxRingBuffer.Peek(out mem, out controlBits)) { Packet packet = MakePacketFromDescriptor(mem, controlBits); toUser.Push(packet); rxRingBuffer.Pop(); } }
//since data comes from the user, the packets are empty shells //with a default of two fragments; one for the header and one for //the packet body private void TxProvision() { PacketFifo txFree = this.txFreeFifo.Acquire(); for (int i = 0; i < txFree.Capacity; i++) { txFree.Push( new Packet(2) ); } this.txFreeFifo.Release(txFree); }
internal void LockedPushTsmtBuffer(Packet packet) { DebugStub.Assert(packet.FragmentCount == 1); DebugStub.Assert(!txRingBuffer.IsFull); this._LockedPushTsmtBuffer(packet); PacketFifo liveFifo = this.txPacketsInDevice.Acquire(); liveFifo.Push(packet); txPacketsInDevice.Release(liveFifo); }
//push a single packet onto the ring void IAdapter.PopulateTxRing(Bytes header, Bytes data) { try { PacketFifo txFree = this.txFreeFifo.Acquire(); PacketFifo txCoalesce = this.txCoalesceFifo.Acquire(); try { DebugStub.Assert(txFree.Count > 0); int cnt = 0; while (txFree.Count <= 0) { //try again... //this happens when we're hammering the outgoing connection this.txCoalesceFifo.Release(txCoalesce); this.txFreeFifo.Release(txFree); this.muxEvent.Set(); Thread.Yield(); txFree = this.txFreeFifo.Acquire(); txCoalesce = this.txCoalesceFifo.Acquire(); if (cnt > 100) { DebugStub.Print("txFree empty???\n"); //DebugStub.Break(); } cnt++; } Packet packet = txFree.Pop(); packet.SetFragment(0, header); packet.SetFragment(1, data); if ((txCoalesce.Count + 1) > txCoalesce.Capacity) { DebugStub.Break(); } DebugStub.Assert((txCoalesce.Count + 1) <= txCoalesce.Capacity); txCoalesce.Push(packet); } catch { DebugStub.Print("failure in populate tx ring\n"); DebugStub.Break(); DebugStub.Assert(false); } finally { this.txCoalesceFifo.Release(txCoalesce); this.txFreeFifo.Release(txFree); //notify the mux that there are waiting packets this.muxEvent.Set(); } } catch (Exception e) { DebugStub.Print("Populate tx ring failed?? {0}\n", DebugStub.ArgList(e)); DebugStub.Break(); } }
internal void LockedPushRecvBuffer(Packet packet) { DebugStub.Assert(packet.FragmentCount == 1); DebugStub.Assert(!rxRingBuffer.IsFull); int length = packet.GetFragmentLength(0); this.LockedPushRecvBuffer(length); PacketFifo liveFifo = this.rxPacketsInDevice.Acquire(); liveFifo.Push(packet); rxPacketsInDevice.Release(liveFifo); }
/////////////////////////////////////////////////////////////////////// // // Rx buffer operations // internal void PopulateRecvBuffer(PacketFifo fromUser) { if (fromUser.Count < 1) { return; } using (rxRingBuffer.thisLock.Lock()) { while (fromUser.Count > 0) { rxRingBuffer.LockedPushRecvBuffer(fromUser.Pop()); } Write32(Register.RECV_DESC_TAIL, rxRingBuffer.Head); } }
//XXX On the first exchange we receive an empty fifo from the Nic //We fill it here...this should be special cased in the startio //routine... private void RxExchangeInternal(NicDeviceContract /*.Imp*/ imp) { int toCount, fromCount; PacketFifo exFifo = this.rxFifo.Acquire(); toCount = exFifo.Count; try { exFifo = imp.GiveRxPacketsToDevice(exFifo); fromCount = exFifo.Count; } finally { this.rxFifo.Release(exFifo); } DebugPrint("RxExchange out: {0} in: {1}\n", toCount, fromCount); }
// Get the received packets from the adapter void DeMuxReceivedPackets() { //Grab the latest set of packets RxExchange(); PacketFifo newPackets = this.rxFifo.Acquire(); try { int count = newPackets.Count; for (int i = 0; i < count; i++) { Packet packet = newPackets.Pop(); // If packet from device has an error // recycle it right away. FromDeviceFlags fromFlags = packet.FromDeviceFlags; if ((fromFlags & FromDeviceFlags.ReceiveError) != 0) { DebugStub.Print("Packet had error???\n"); newPackets.Push(packet); continue; } Bytes data = packet.ReleaseFragment(0); Ethernet.ProcessIncomingPacket(data, this); #if false if (filterAdapter == null || filterAdapter.ProcessIncomingPacket(data)) { Ethernet.ProcessIncomingPacket(data, this); } else { //delete data; } #endif //XXX Totally inefficient first try immediately replaces //the lost data. Bytes nxtPacket = new Bytes(new byte[this.mtu]); packet.SetFragment(0, nxtPacket); newPackets.Push(packet); } } finally { this.rxFifo.Release(newPackets); } }
public EOSS3_PacketFIFO(Machine machine) : base(machine) { queueNames = new Dictionary <long, string>() { { 0, "PacketFifo0" }, { 1, "PacketFifo1" }, { 2, "PacketFifo2" }, { 3, "PacketFifo8k" } }; packetFifos = new PacketFifoBase[NumberOfQueues]; for (var i = 0; i < NumberOfRegularQueues; i++) { packetFifos[i] = new PacketFifo(this, queueNames[i], fifoSizes[i]); } packetFifos[NumberOfQueues - 1] = new PacketFifoSwitchable(this, queueNames[NumberOfQueues - 1], fifoSizes[NumberOfQueues - 1]); DefineRegisters(); }
public void Run() { System.DebugStub.Print("Nic@" + Kernel.CurrentThread + ". "); while (true) { this.muxEvent.WaitOne(); PacketFifo txCoalesce = this.txCoalesceFifo.Acquire(); PacketFifo txToDevice = this.txFifo.Acquire(); try { DebugPrint("coalescing {0} packets\n", txCoalesce.Count); txToDevice.Push(txCoalesce); } catch (Exception e) { DebugStub.Print("Mux FAILED! arg {0}\n", DebugStub.ArgList(e.ToString())); DebugStub.Break(); } finally { this.txCoalesceFifo.Release(txCoalesce); this.txFifo.Release(txToDevice); TxExchange(); } } }
internal void DrainTsmtBuffer(PacketFifo toUser) { using (txRingBuffer.thisLock.Lock()) { txRingBuffer.LockedDrainTsmtBuffer(toUser); } }
internal void DrainRecvBuffer(PacketFifo toUser) { using (rxRingBuffer.thisLock.Lock()) { rxRingBuffer.LockedDrainRecvBuffer(toUser); } }
internal ExRefPacketFifo(PacketFifo o, bool dummy) { VTable.Assert(o != null); this.o = o; }
public void Release(PacketFifo v) { o = v; thisLock.Release(); }
public PacketFifo GiveTxPacketsToDevice(PacketFifo txFifo) { device.PopulateTsmtBuffer(txFifo); device.DrainTsmtBuffer(txFifo); return(txFifo); }
public PacketFifo GiveRxPacketsToDevice(PacketFifo rxFifo) { device.PopulateRecvBuffer(rxFifo); device.DrainRecvBuffer(rxFifo); return(rxFifo); }