private void ReceiveFrameInner(EthernetFrame frame) { if ((registers.Control & (1u << 1)) == 0) { //if receiving is disabled discard packet return; } var rd = new receiveDescriptor(machine.SystemBus); if (!EthernetFrame.CheckCRC(frame.Bytes)) { rd.CRCError = true; this.Log(LogLevel.Info, "Invalid CRC, packet discarded"); return; } rd.Fetch(receiveDescriptorBase | receiveDescriptorOffset); if (!rd.Enable) { //if receive descritptor disabled discard packet return; } machine.SystemBus.WriteBytes(frame.Bytes, (long)rd.PacketAddress); registers.Status = 1u << 2; if (rd.Wrap) { receiveDescriptorOffset = 0; } else { if (receiveDescriptorOffset != 0x3f8) { receiveDescriptorOffset += 8; } else { receiveDescriptorOffset = 0; } } if (rd.InterruptEnable && ((registers.Control & (1u << 3)) != 0)) { registers.Status |= 1u << 2; this.IRQ.Set(); this.IRQ.Unset(); } rd.Length = (uint)frame.Bytes.Length; rd.Enable = false; rd.Wrap = false; rd.WriteBack(); }
private void ReceiveFrameInner(EthernetFrame frame) { lock (sync) { this.Log(LogLevel.Noisy, "Received packet len {0}", frame.Bytes.Length); if ((registers.Control & (1u << 2)) == 0) { this.Log(LogLevel.Debug, "Receiver not enabled, dropping frame."); return; } if (!registers.IgnoreFCS && !EthernetFrame.CheckCRC(frame.Bytes)) { this.Log(LogLevel.Info, "Invalid CRC, packet discarded"); return; } bool interrupt = false; rxBufferDescriptor rxBD = new rxBufferDescriptor(machine.SystemBus); rxBD.Fetch(registers.RxQueueBaseAddr); if (!rxBD.Ownership)//if we could write data to this BD { interrupt = false; rxBD.Ownership = true; rxBD.StartOfFrame = true; rxBD.EndOfFrame = true; rxBD.Length = (ushort)frame.Bytes.Length; machine.SystemBus.WriteBytes(frame.Bytes, rxBD.BufferAddress); rxBD.WriteBack(); if (rxBD.Wrap) { registers.RxQueueBaseAddr = rxBufferBase; } else { registers.RxQueueBaseAddr += 8; } registers.RxStatus |= 1u << 1; if ((registers.InterruptMask & (1u << 1)) == 0) { registers.InterruptStatus |= 1u << 1; interrupt = true; } if (interrupt) { IRQ.Set(); } } } }
private bool TryReceivePacket(byte[] data) { // first check whether the packet fits into buffer var receiveBufferSize = receiveBufferEnd - receiveBufferStart + 1; var freeSpace = receiveBufferSize - ((receiveBufferSize + currentReceiveWritePointer - receiveReadPointer) % receiveBufferSize); var packetPlusHeadersLength = data.Length + 2 + 4; // next packet pointer and receive status vector packetPlusHeadersLength += packetPlusHeadersLength % 2; // padding byte if (freeSpace < packetPlusHeadersLength) { this.Log(LogLevel.Warning, "No free space for packet. Packet length (+ headers): {0}B, free space: {1}B.", Misc.NormalizeBinary(packetPlusHeadersLength), Misc.NormalizeBinary(freeSpace)); return(false); } if (!EthernetFrame.CheckCRC(data) && crcEnabled.Value) { this.Log(LogLevel.Info, "Invalid CRC, packet discarded"); return(false); } var nextReceiveWritePointer = currentReceiveWritePointer + packetPlusHeadersLength; if (nextReceiveWritePointer > receiveBufferEnd) { nextReceiveWritePointer -= receiveBufferSize; } var packetWithHeader = new byte[packetPlusHeadersLength]; BitConverter.GetBytes((ushort)nextReceiveWritePointer).CopyTo(packetWithHeader, 0); BitConverter.GetBytes((ushort)data.Length).CopyTo(packetWithHeader, 2); BitConverter.GetBytes((ushort)(1 << 7)).CopyTo(packetWithHeader, 4); data.CopyTo(packetWithHeader, 6); var firstPartLength = Math.Min(packetPlusHeadersLength, receiveBufferEnd - currentReceiveWritePointer + 1); Array.Copy(packetWithHeader, 0, ethernetBuffer, currentReceiveWritePointer, firstPartLength); if (firstPartLength < packetPlusHeadersLength) { // packet overlaps buffer Array.Copy(packetWithHeader, firstPartLength, ethernetBuffer, receiveBufferStart, packetWithHeader.Length - firstPartLength); } currentReceiveWritePointer = nextReceiveWritePointer; waitingPacketCount++; RefreshInterruptStatus(); return(true); }
public void ReceiveFrame(EthernetFrame frame) { lock (innerLock) { this.Log(LogLevel.Debug, "Received packet, length {0}", frame.Bytes.Length); if (!receiverEnabled.Value) { this.Log(LogLevel.Info, "Receiver not enabled, dropping frame"); return; } if (!EthernetFrame.CheckCRC(frame.Bytes)) { this.Log(LogLevel.Info, "Invalid CRC, packet discarded"); return; } rxDescriptorsQueue.CurrentDescriptor.Read(); if (rxDescriptorsQueue.CurrentDescriptor.IsEmpty) { if (!rxDescriptorsQueue.CurrentDescriptor.WriteBuffer(frame.Bytes, (uint)frame.Bytes.Length)) { // The current implementation doesn't handle packets that do not fit into a single buffer. // In case we encounter this error, we probably should implement partitioning/scattering procedure. this.Log(LogLevel.Warning, "Could not write the incoming packet to the DMA buffer: maximum packet length exceeded."); return; } rxDescriptorsQueue.CurrentDescriptor.Length = (ushort)frame.Bytes.Length; // Packets going over several buffers not supported rxDescriptorsQueue.CurrentDescriptor.IsLast = true; rxDescriptorsQueue.CurrentDescriptor.IsEmpty = false; // write this back to memory rxDescriptorsQueue.CurrentDescriptor.Update(); rxDescriptorsQueue.GoToNextDescriptor(); interruptManager.SetInterrupt(Interrupts.ReceiveBufferInterrupt); interruptManager.SetInterrupt(Interrupts.ReceiveFrameInterrupt); } else { this.Log(LogLevel.Warning, "Receive DMA buffer overflow"); } } }
public void ReceiveFrame(EthernetFrame frame)//when data is send to us { lock (sync) { if (!frame.DestinationMAC.Value.IsBroadcast && frame.DestinationMAC.Value != MAC) { return; } if (!EthernetFrame.CheckCRC(frame.Bytes)) { this.Log(LogLevel.Info, "Invalid CRC, packet discarded"); return; } rxPacketQueue.Enqueue(frame); } }
public void ReceiveFrame(EthernetFrame frame) { lock (sync) { this.Log(LogLevel.Debug, "Received packet, length {0}", frame.Bytes.Length); if (!receiveEnabled.Value) { this.Log(LogLevel.Info, "Receiver not enabled, dropping frame"); return; } if (!ignoreRxFCS.Value && !EthernetFrame.CheckCRC(frame.Bytes)) { this.Log(LogLevel.Info, "Invalid CRC, packet discarded"); return; } rxDescriptorsQueue.CurrentDescriptor.Invalidate(); if (!rxDescriptorsQueue.CurrentDescriptor.Ownership) { if (!rxDescriptorsQueue.CurrentDescriptor.WriteBuffer(frame.Bytes, receiveBufferOffset.Value)) { this.Log(LogLevel.Warning, "Could not write the incoming packet to the DMA buffer"); return; } rxDescriptorsQueue.CurrentDescriptor.StartOfFrame = true; rxDescriptorsQueue.CurrentDescriptor.EndOfFrame = true; rxDescriptorsQueue.GoToNextDescriptor(); frameReceived.Value = true; interruptManager.SetInterrupt(Interrupts.ReceiveComplete); } else { this.Log(LogLevel.Warning, "Receive DMA buffer overflow"); bufferNotAvailable.Value = true; interruptManager.SetInterrupt(Interrupts.ReceiveUsedBitRead); } } }
public void ReceiveFrame(EthernetFrame frame) { /*if(machine.ElapsedTime < TimeSpan.FromSeconds(30)) * { * return; * }*/ lock (receiveLock) { if ((dmaStatus & ReceiveStatus) != 0) { queue.Enqueue(frame); return; } if (!packetSent) { this.Log(LogLevel.Error, "Dropping - no packets sent."); return; } if (frame.Bytes.Length < 14) { this.Log(LogLevel.Error, "DROPPING - packet too short."); return; } if (this.machine.IsPaused) { this.Log(LogLevel.Debug, "DROPPING - cpu is halted."); return; } var destinationMac = frame.DestinationMAC; if (!destinationMac.IsBroadcast && !destinationMac.Equals(MAC)) { this.Log(LogLevel.Debug, "DROPPING - not for us."); return; } /* * if((dmaInterruptEnable & (ReceiveStatus)) == 0) * { * this.Log(LogLevel.Debug, "DROPPING - rx irq is turned off."); * return; * } */ this.Log(LogLevel.Noisy, Misc.DumpPacket(frame, false, machine)); if (dmaReceiveDescriptorListAddress < 0x20000000) { // TODO: not in ram this.Log(LogLevel.Error, "DROPPING - descriptor is not valid."); return; } var written = 0; var first = true; var bytes = frame.Bytes; if (!EthernetFrame.CheckCRC(bytes)) { if (!(crcStrippingForTypeFrames && bytes.Length > 1536) || !(automaticPadCRCStripping && bytes.Length < 1500)) { this.Log(LogLevel.Info, "Invalid CRC, packet discarded"); return; } } var receiveDescriptor = new RxDescriptor(machine.SystemBus); receiveDescriptor.Fetch(dmaReceiveDescriptorListAddress); if (receiveDescriptor.IsUsed) { this.Log(LogLevel.Error, "DROPPING - descriptor is used."); return; } this.Log(LogLevel.Noisy, "DESCRIPTOR ADDR1={0:X}, ADDR2={1:X}", receiveDescriptor.Address1, receiveDescriptor.Address2); while (!receiveDescriptor.IsUsed) { if (receiveDescriptor.Address1 < 0x20000000) { this.Log(LogLevel.Error, "Descriptor points outside of ram, aborting... This should not happen!"); break; } receiveDescriptor.IsUsed = true; receiveDescriptor.IsFirst = first; first = false; var howManyBytes = Math.Min(receiveDescriptor.Buffer1Length, frame.Bytes.Length - written); var toWriteArray = new byte[howManyBytes]; Array.Copy(bytes, written, toWriteArray, 0, howManyBytes); machine.SystemBus.WriteBytes(toWriteArray, receiveDescriptor.Address1); written += howManyBytes; //write second buffer if (frame.Bytes.Length - written > 0 && !receiveDescriptor.IsNextDescriptorChained) { howManyBytes = Math.Min(receiveDescriptor.Buffer2Length, frame.Bytes.Length - written); toWriteArray = new byte[howManyBytes]; Array.Copy(bytes, written, toWriteArray, 0, howManyBytes); machine.SystemBus.WriteBytes(toWriteArray, receiveDescriptor.Address2); written += howManyBytes; } if (frame.Bytes.Length - written <= 0) { receiveDescriptor.IsLast = true; this.NoisyLog("Setting descriptor length to {0}", (uint)frame.Bytes.Length); receiveDescriptor.FrameLength = (uint)frame.Bytes.Length; } this.NoisyLog("Writing descriptor at 0x{6:X}, first={0}, last={1}, written {2} of {3}. next_chained={4}, endofring={5}", receiveDescriptor.IsFirst, receiveDescriptor.IsLast, written, frame.Bytes.Length, receiveDescriptor.IsNextDescriptorChained, receiveDescriptor.IsEndOfRing, dmaReceiveDescriptorListAddress); receiveDescriptor.WriteBack(); if (!receiveDescriptor.IsNextDescriptorChained) { dmaReceiveDescriptorListAddress += 8; } else if (receiveDescriptor.IsEndOfRing) { dmaReceiveDescriptorListAddress = dmaReceiveDescriptorListAddressBegin; } else { dmaReceiveDescriptorListAddress = receiveDescriptor.Address2; } if (frame.Bytes.Length - written <= 0) { if ((dmaInterruptEnable & (ReceiveStatus)) != 0)// receive interrupt { dmaStatus |= ReceiveStatus; IRQ.Set(); } else { this.DebugLog("Exiting but not scheduling an interrupt!"); } break; } receiveDescriptor.Fetch(dmaReceiveDescriptorListAddress); } this.DebugLog("Packet of length {0} delivered.", frame.Bytes.Length); if (written < frame.Bytes.Length) { this.Log(LogLevel.Error, "Delivered only {0} from {1} bytes!", written, frame.Bytes.Length); } } }
public void ReceiveFrame(EthernetFrame frame) { lock (innerLock) { this.Log(LogLevel.Debug, "Received packet, length {0}", frame.Bytes.Length); if (!receiverEnabled.Value) { this.Log(LogLevel.Info, "Receiver not enabled, dropping frame"); return; } if (discardWithMACLayerError.Value && !EthernetFrame.CheckCRC(frame.Bytes)) { this.Log(LogLevel.Info, "Invalid CRC, packet discarded"); return; } if (discardIPHeaderInvalidChecksum.Value) { var packet = (IPv4Packet)frame.UnderlyingPacket.Extract(typeof(IPv4Packet)); if (packet != null && !packet.ValidChecksum) { this.Log(LogLevel.Info, "Invalid IpV4 checksum, packet discarded"); return; } } if (discardProtocolInvalidChecksum.Value) { var tcpPacket = (TcpPacket)frame.UnderlyingPacket.Extract(typeof(TcpPacket)); if (tcpPacket != null && !tcpPacket.ValidChecksum) { this.Log(LogLevel.Info, "Invalid TCP checksum, packet discarded"); return; } var udpPacket = (UdpPacket)frame.UnderlyingPacket.Extract(typeof(UdpPacket)); if (udpPacket != null && !udpPacket.ValidChecksum) { this.Log(LogLevel.Info, "Invalid UDP checksum, packet discarded"); return; } var icmpv4Packet = (ICMPv4Packet)frame.UnderlyingPacket.Extract(typeof(ICMPv4Packet)); if (icmpv4Packet != null) { var checksum = icmpv4Packet.Checksum; icmpv4Packet.Checksum = 0x0; icmpv4Packet.UpdateCalculatedValues(); if (checksum != icmpv4Packet.Checksum) { this.Log(LogLevel.Info, "Invalid ICMPv4 checksum, packet discarded"); return; } } var icmpv6Packet = (ICMPv6Packet)frame.UnderlyingPacket.Extract(typeof(ICMPv6Packet)); if (icmpv6Packet != null) { var checksum = icmpv6Packet.Checksum; icmpv6Packet.Checksum = 0x0; icmpv6Packet.UpdateCalculatedValues(); if (checksum != icmpv6Packet.Checksum) { this.Log(LogLevel.Info, "Invalid ICMPv6 checksum, packet discarded"); return; } } } rxDescriptorsQueue.CurrentDescriptor.Read(); if (rxDescriptorsQueue.CurrentDescriptor.IsEmpty) { if (!rxDescriptorsQueue.CurrentDescriptor.WriteBuffer(frame.Bytes, (uint)frame.Bytes.Length)) { // The current implementation doesn't handle packets that do not fit into a single buffer. // In case we encounter this error, we probably should implement partitioning/scattering procedure. this.Log(LogLevel.Warning, "Could not write the incoming packet to the DMA buffer: maximum packet length exceeded."); return; } rxDescriptorsQueue.CurrentDescriptor.Length = (ushort)frame.Bytes.Length; // Packets going over several buffers not supported rxDescriptorsQueue.CurrentDescriptor.IsLast = true; rxDescriptorsQueue.CurrentDescriptor.IsEmpty = false; // write this back to memory rxDescriptorsQueue.CurrentDescriptor.Update(); rxDescriptorsQueue.GoToNextDescriptor(); interruptManager.SetInterrupt(Interrupts.ReceiveBufferInterrupt); interruptManager.SetInterrupt(Interrupts.ReceiveFrameInterrupt); } else { this.Log(LogLevel.Warning, "Receive DMA buffer overflow"); } } }
public void ReceiveFrame(EthernetFrame frame) { lock (lockObj) { this.NoisyLog("Received frame on MAC {0}. Frame destination MAC is {1}", this.MAC.ToString(), frame.DestinationMAC); var size = frame.Bytes.Length; var isEven = (size & 1) == 0; if ((receiveControl & ReceiveEnabled) == 0 || (receiveControl & SoftwareReset) != 0) { //Drop if reset is on or receiving is not enabled. return; } var packetSize = Math.Max(64, size & ~1); //64 is the minimal length packetSize += 6; var withCRC = (receiveControl & StripCRC) == 0; if (withCRC) { packetSize += 4; } if (packetSize > MaxPacketSize) { //Maybe we should react to overruns. Now we just drop. return; } byte whichPacket; if (!TryAllocatePacket(out whichPacket)) { return; } rxFifo.Enqueue(whichPacket); var status = 0; if (size > 1518) { status |= 0x0800; } if (!isEven) { status |= 0x1000; } var currentBuffer = memoryBuffer[whichPacket]; currentBuffer.Data[0] = (byte)(status & 0xff); currentBuffer.Data[1] = (byte)(status >> 8); currentBuffer.Data[2] = (byte)(packetSize & 0xff); currentBuffer.Data[3] = (byte)(packetSize >> 8); var frameBytes = frame.Bytes; for (int i = 0; i < (size & ~1); i++) { currentBuffer.Data[4 + i] = frameBytes[i]; } //Pad with 0s if (size < 64) { var pad = 64 - size; if (!isEven) { for (int i = 0; i < pad; i++) { currentBuffer.Data[4 + i + size] = 0; } } else { for (int i = 0; i < pad; i++) { currentBuffer.Data[4 + i + size + 1] = 0; } } size = 64; } if (withCRC) { if (!EthernetFrame.CheckCRC(frame.Bytes)) { this.Log(LogLevel.Info, "Invalid CRC, packet discarded"); return; } } if (!isEven) { //TODO: For a short, odd-length packet, will it work? Should it not be written before? currentBuffer.Data[packetSize - 2] = frameBytes[size - 1]; currentBuffer.Data[packetSize - 1] = 0x60; } else { currentBuffer.Data[packetSize - 1] = 0x40; } interruptStatus |= RxInterrupt; Update(); } }