//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(); } }
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); }
// 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); } }
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); }
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(); } } }