public void ReceiveFrame(EthernetFrame frame) { if(deviceFile == null) { return; } var bytes = frame.Bytes; try { // since the file reader operations are buffered, we have to immediately flush writes deviceFile.Write(bytes, 0, bytes.Length); deviceFile.Flush(); } catch(IOException) { if(networkInterface.OperationalStatus != OperationalStatus.Up) { this.DebugLog("Interface is not up during write, frame dropped."); } else { throw; } } this.NoisyLog("Frame of length {0} sent to host.", frame.Length); }
/// <summary> /// Is invoked by the parent interface to transmit a frame to any connected endpoint. /// </summary> /// <param name='frame'> /// Network frame. /// </param> public void TransmitFrameFromInterface(EthernetFrame frame) { var transmit = TransmitFromParentInterface; if(transmit != null) { transmit(this, frame); } }
private void SendFrameToInterface(EthernetFrame frame) { var receive = ReceiveOnParentInterface; if(receive != null) { receive(this, frame); } Parent.ReceiveFrame(frame); }
void ReceiveFrameInner(EthernetFrame frame) { if(!frame.DestinationMAC.Value.IsBroadcast && frame.DestinationMAC.Value != MAC) { return; } lock(packetQueue) { packetQueue.Enqueue(frame); SignalInterrupt(); } }
public void ReceiveFrame(EthernetFrame frame) { // TODO: non blocking if(stream == null) { return; } var handle = GCHandle.Alloc(frame.Bytes, GCHandleType.Pinned); try { var result = LibC.WriteData(stream.Handle, handle.AddrOfPinnedObject(), frame.Length); if(result == 0) { this.Log(LogLevel.Error, "Error while writing to TUN interface: {0}.", result); } } finally { handle.Free(); } }
private async Task ReadPacketAsync() { var buffer = new byte[Mtu]; while(!cts.IsCancellationRequested) { try { if(await deviceFile.ReadAsync(buffer, 0, buffer.Length, cts.Token) > 0) { var frame = new EthernetFrame(buffer, true); Link.TransmitFrameFromInterface(frame); this.NoisyLog("Frame of length {0} received from host.", frame.Length); } } catch(IOException) { if(networkInterface.OperationalStatus != OperationalStatus.Up) { this.NoisyLog("I/O exception while interface is not up, waiting {0}s.", Misc.NormalizeDecimal(GracePeriod.TotalSeconds)); // probably the interface is not opened yet await Task.Delay(GracePeriod); } else { throw; } } } }
private void ReceiveFrameInner(EthernetFrame frame) { lock(sync) { this.Log(LogLevel.Noisy, "Received packet len {0}", frame.Length); if((registers.Control & (1u << 2)) == 0) { this.Log(LogLevel.Debug, "Receiver not enabled, dropping frame."); 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.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 void SendFrames() { lock(sync) { txBufferDescriptor txBD = new txBufferDescriptor(machine.SystemBus); bool interrupt = false; List <byte> packet = new List<byte>(); txBD.Fetch(registers.TxQueueBaseAddr); while(!txBD.Used) { while(!txBD.Last) { packet.AddRange(machine.SystemBus.ReadBytes(txBD.Word0, txBD.Length)); txBD.Used = true; txBD.WriteBack(); if(txBD.Wrap) { registers.TxQueueBaseAddr = txBufferBase; } else { registers.TxQueueBaseAddr += 8; } txBD.Fetch(registers.TxQueueBaseAddr); } interrupt = false; txBD.Used = true; packet.AddRange(machine.SystemBus.ReadBytes(txBD.Word0, txBD.Length)); if((registers.DMAConfig & 1u << 11) != 0)//if checksum offload enable { if((packet[14] & 0xF0) == 0x40) //IP packet { ushort cksum; IPHeaderLength = (ushort)((packet[14] & 0x0F) * 4); if(packet[23] == 0x06) // TCP packet { IPpacket tcpPacket = new IPpacket(IPHeaderLength, IPpacket.PacketType.TCP); tcpPacket.ReadFromBuffer(packet.ToArray()); cksum = tcpPacket.GetChecksum(); cksum -= 1; packet[MACHeaderLegth + IPHeaderLength + 16] = (byte)((cksum >> 8) & 0xFF); packet[MACHeaderLegth + IPHeaderLength + 17] = (byte)((cksum) & 0xFF); } else if(packet[23] == 0x11) // UDP packet { IPpacket udpPacket = new IPpacket(IPHeaderLength, IPpacket.PacketType.UDP); udpPacket.ReadFromBuffer(packet.ToArray()); cksum = udpPacket.GetChecksum(); cksum -= 1; packet[MACHeaderLegth + IPHeaderLength + 6] = (byte)((cksum >> 8) & 0xFF); packet[MACHeaderLegth + IPHeaderLength + 7] = (byte)((cksum) & 0xFF); } } } if(Link.IsConnected) { var frame = new EthernetFrame(packet.ToArray()); this.Log(LogLevel.Noisy, "Sending packet length {0}", packet.ToArray().Length); Link.TransmitFrameFromInterface(frame); } txBD.WriteBack(); if(txBD.Wrap) { registers.TxQueueBaseAddr = txBufferBase; } else { registers.TxQueueBaseAddr += 8; } registers.TxStatus |= 1u << 5; //tx complete txBD.Fetch(registers.TxQueueBaseAddr); if(txBD.Used) { registers.TxStatus |= 0x01; if((registers.InterruptMask & (1u << 3)) == 0) { registers.InterruptStatus |= 1u << 3; interrupt = true; } } if((registers.InterruptMask & (1u << 7)) == 0) { registers.InterruptStatus |= 1u << 7; interrupt = true; } if(interrupt) { IRQ.Set(); } } } }
private void Finished() { if(mode == Mode.WaitingForPacket) { this.DebugLog("Packet received, LEN {7} {0:x} {1:x} {2:x} {3:x} (...) {4:x} {5:x} {6:x}", request[0], request[1], request[2], request[3], request[currentLength - 5], request[currentLength - 4], request[currentLength - 3], currentLength); var frame = new byte[currentLength]; Array.Copy(request, 0, frame, 0, currentLength); var ethernetFrame = new EthernetFrame(frame); Link.TransmitFrameFromInterface(ethernetFrame); mode = Mode.Standard; currentLength = 4; transmissionEnded = true; if(interruptAfterTransmision) { SignalInterrupt(); } } if(mode == Mode.SendingPacket) { mode = Mode.Standard; currentLength = 4; lock(packetQueue) { if(packetQueue.Count > 0) { SignalInterrupt(); } } } if(mode == Mode.Special) { currentLength = 4; mode = Mode.Standard; return; } switch(lastPacketType) { case 0xC0: mode = Mode.WaitingForPacket; var encodedLength = request[3] + (request[4] << 8); this.DebugLog("Encoded length is 0x{0:X}.", encodedLength); currentLength = Align(encodedLength + 1 + 1); transmissionEnded = false; break; case 0xF: lastPacketType = 0; break; } }
// private byte[] macAddress = new byte[] {0,0,0,0,0,0}; #endregion #region USB descriptors private void ReceiveFrameInner(EthernetFrame frame) { lock(sync) { if(!frame.DestinationMAC.Value.IsBroadcast && frame.DestinationMAC.Value != MAC) { return; } rxPacketQueue.Enqueue(frame); } }
public void ReceiveFrame(EthernetFrame frame)//when data is send to us { machine.ReportForeignEvent(frame, ReceiveFrameInner); }
public void ReceiveFrame (EthernetFrame frame) { throw new NotImplementedException (); }
private void ReceiveFrameInner(EthernetFrame frame) { if((registers.Control & (1u << 1)) == 0) { //if receiving is disabled discard packet return; } var rd = new receiveDescriptor(machine.SystemBus); 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.Length; rd.Enable = false; rd.Wrap = false; rd.WriteBack(); }
private void ReceiveFrameInner(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.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.Value; 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 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.Length - written); var toWriteArray = new byte[howManyBytes]; var bytes = frame.Bytes; Array.Copy(bytes, written, toWriteArray, 0, howManyBytes); machine.SystemBus.WriteBytes(toWriteArray, receiveDescriptor.Address1); written += howManyBytes; //write second buffer if(frame.Length - written > 0 && !receiveDescriptor.IsNextDescriptorChained) { howManyBytes = Math.Min(receiveDescriptor.Buffer2Length, frame.Length - written); toWriteArray = new byte[howManyBytes]; Array.Copy(bytes, written, toWriteArray, 0, howManyBytes); machine.SystemBus.WriteBytes(toWriteArray, receiveDescriptor.Address2); written += howManyBytes; } if(frame.Length - written <= 0) { receiveDescriptor.IsLast = true; this.NoisyLog("Setting descriptor length to {0}", (uint)frame.Length + 4); receiveDescriptor.FrameLength = (uint)frame.Length + 4; //with CRC } 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.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.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.Length); if(written < frame.Length) { this.Log(LogLevel.Error, "Delivered only {0} from {1} bytes!", written, frame.Length); } } }
/// <summary> /// Is invoked by a connected endpoint to transmit a frame to the parent interface. /// </summary> /// <param name="frame"> /// Network frame. /// </param> public void ReceiveFrameOnInterface(EthernetFrame frame) { SendFrameToInterface(frame); }
private void TransmitLoop(CancellationToken token) { while(true) { byte[] buffer = null; if(stream == null) { return; } try { buffer = LibC.ReadDataWithTimeout(stream.Handle, MTU, 1000, () => token.IsCancellationRequested); } catch(ArgumentException) { // stream was closed return; } catch(ObjectDisposedException) { return; } if(token.IsCancellationRequested) { return; } if(buffer == null || buffer.Length == 0) { continue; } var ethernetFrame = new EthernetFrame(buffer, true); Link.TransmitFrameFromInterface(ethernetFrame); } }
private void ReceiveFrameInner(EthernetFrame frame) { lock(lockObj) { this.NoisyLog("Received frame on MAC {0}. Frame destination MAC is {1}", this.MAC.ToString(), frame.DestinationMAC); var size = frame.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) { this.Log(LogLevel.Warning, "CRC not implemented."); } 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(); } }
public byte Transmit() { lock(lockObj) { int len; byte whichPacket; if((transmitControl & TransmitEnabled) == 0) { return 0; } if(txFifo.Count == 0) { return 0; } while(txFifo.Count > 0) { whichPacket = txFifo.Dequeue(); var currentBuffer = memoryBuffer[whichPacket]; len = currentBuffer.Data[2]; len |= currentBuffer.Data[3] << 8; len -= 6; byte [] indata = new byte[len]; for(int j=0; j<len; j++) { indata[j] = currentBuffer.Data[j + 4]; } if((control & ControlAutorelease) != 0) { currentBuffer.IsAllocated = false; } else { sentFifo.Enqueue((byte)whichPacket); } var frame = new EthernetFrame(indata); Link.TransmitFrameFromInterface(frame); } Update(); return 0; } }
private void SendFrames() { this.Log(LogLevel.Noisy, "Sending frame"); var transmitDescriptor = new TxDescriptor(machine.SystemBus); var packetData = new List<byte>(); transmitDescriptor.Fetch(dmaTransmitDescriptorListAddress); while(!transmitDescriptor.IsUsed) { transmitDescriptor.IsUsed = true; this.Log(LogLevel.Noisy, "GOING TO READ FROM {0:X}, len={1}", transmitDescriptor.Address1, transmitDescriptor.Buffer1Length); packetData.AddRange(machine.SystemBus.ReadBytes(transmitDescriptor.Address1, transmitDescriptor.Buffer1Length)); if(!transmitDescriptor.IsNextDescriptorChained) { packetData.AddRange(machine.SystemBus.ReadBytes(transmitDescriptor.Address2, transmitDescriptor.Buffer2Length)); } transmitDescriptor.WriteBack(); if(transmitDescriptor.IsEndOfRing) { dmaTransmitDescriptorListAddress = dmaTransmitDescriptorListAddressBegin; } else if(transmitDescriptor.IsNextDescriptorChained) { dmaTransmitDescriptorListAddress = transmitDescriptor.Address2; } else { dmaTransmitDescriptorListAddress += 8; } if(transmitDescriptor.IsLast) { this.Log(LogLevel.Noisy, "Sending frame of {0} bytes.", packetData.Count); if(Link.IsConnected) { var frame = new EthernetFrame(packetData.ToArray()); if(transmitDescriptor.ChecksumInstertionControl > 0) { this.Log(LogLevel.Noisy, "Calculating checksum (mode {0}).", transmitDescriptor.ChecksumInstertionControl); if(transmitDescriptor.ChecksumInstertionControl == 1) { //IP only frame.FillWithChecksums(supportedEtherChecksums, null); } else { //IP and payload frame.FillWithChecksums(supportedEtherChecksums, supportedIPChecksums); } } this.Log(LogLevel.Debug, Misc.DumpPacket(frame, true, machine)); packetSent = true; Link.TransmitFrameFromInterface(frame); } } transmitDescriptor.Fetch(dmaTransmitDescriptorListAddress); } //set TransmitBufferUnavailable dmaStatus |= TransmitBufferUnavailableStatus; if((dmaInterruptEnable & (StartStopTransmission)) == 0) { IRQ.Set(); } this.Log(LogLevel.Noisy, "Frame sent."); }
public void ReceiveFrame(EthernetFrame frame) { machine.ReportForeignEvent(frame, ReceiveFrameInner); }
public void WriteDataBulk(USBPacket packet) { if(packet.data == null) return; byte[] packetToSend; if(packet.data[5] != 64) { packetToSend = new byte[packet.data.Length - 8]; Array.Copy(packet.data, 8, packetToSend, 0, packetToSend.Length); } else { packetToSend = new byte[packet.data.Length - 12]; Array.Copy(packet.data, 12, packetToSend, 0, packetToSend.Length); if((packetToSend[14] & 0xF0) == 0x40) //IP packet { ushort cksum; IPHeaderLength = (ushort)((packetToSend[14] & 0x0F) * 4); if(packetToSend[23] == 0x06) // TCP packet { IPpacket tcpPacket = new IPpacket(IPHeaderLength, IPpacket.PacketType.TCP); tcpPacket.ReadFromBuffer(packetToSend); cksum = tcpPacket.GetChecksum(); cksum -= 1; packetToSend[MACHeaderLegth + IPHeaderLength + 16] = (byte)((cksum >> 8) & 0xFF); packetToSend[MACHeaderLegth + IPHeaderLength + 17] = (byte)((cksum) & 0xFF); } else if(packetToSend[23] == 0x11) // UDP packet { IPpacket udpPacket = new IPpacket(IPHeaderLength, IPpacket.PacketType.UDP); udpPacket.ReadFromBuffer(packetToSend); cksum = udpPacket.GetChecksum(); cksum -= 1; packetToSend[MACHeaderLegth + IPHeaderLength + 6] = (byte)((cksum >> 8) & 0xFF); packetToSend[MACHeaderLegth + IPHeaderLength + 7] = (byte)((cksum) & 0xFF); } } } var frame = new EthernetFrame(packetToSend); Link.TransmitFrameFromInterface(frame); }
private void transmitFrame() { var td = new transmitDescriptor(machine.SystemBus); td.Fetch(transmitDescriptorBase | transmitDescriptorOffset); if(!td.Enable) { return; //if decriptor is disabled there is nothing to send (just return) } var packet = new EthernetFrame(machine.SystemBus.ReadBytes((long)td.PacketAddress, (int)td.Length)); if(Link.IsConnected) { this.Log(LogLevel.Info, "Sending packet length {0}", packet.Length); this.Log(LogLevel.Info, "Packet address = 0x{0:X}", td.PacketAddress); Link.TransmitFrameFromInterface(packet); } registers.Status |= 1u << 3; if(td.Wrap) { transmitDescriptorOffset = 0; } else { if(transmitDescriptorOffset != 0x3f8) { transmitDescriptorOffset += 8; } else { transmitDescriptorOffset = 0; } } if(td.InterruptEnable && ((registers.Control & (1u << 2)) != 0)) { //if interrupts enabled registers.Status |= 1u << 3; //transmitter interrupt bit this.IRQ.Set(); this.IRQ.Unset(); } td.Enable = false; td.Wrap = false; td.InterruptEnable = false; td.Length = 0; td.UnderrunError = false; td.AttemptLimitError = false; td.WriteBack(); }
public void ReceiveFrame(EthernetFrame frame)//when data is send to us { throw new NotImplementedException(); }