/// <summary> /// Removes a queued frame from the output FIFO and transmits it. /// </summary> void EmptySendFifo() { var frame = sendFifo.Dequeue(); WriteMac("Outputting an Ethernet frame for " + frame.Destination + "."); emptyingFifo = true; // Serialize the Ethernet frame object into a sequence of bytes. var frameBytes = frame.Serialize(); // Call into the physical layer to put the bytes "on the wire". Transmit(frameBytes); }
/// <summary> /// Processes the queue of incoming IP packets. /// </summary> void ProcessPackets() { try { var tuple = inputQueue.Dequeue(); var packet = tuple.Item1; var ifc = tuple.Item2; packet.TimeToLive--; // Drop packet and send "TTL Expired"-ICMP back to packet originator. if (packet.TimeToLive == 0) { if (packet.Protocol != IpProtocol.Icmp) { SendIcmp(ifc, packet.Source, IcmpPacket.TimeExceeded(packet)); } return; } // Incrementally update the checksum. var sum = (uint)(packet.Checksum + 0x01); packet.Checksum = (ushort)(sum + (sum >> 16)); if (IsPacketForUs(packet)) { // See if we have all parts and can reassemble the original packet. if (IsFragment(packet)) { ReassemblePacket(packet); } else { // If it's not a fragment, hand the data up to the transport layer. HandUp(packet.Data, packet.Protocol); } } else { // If it's not for us, see if we can forward it to its destination. RoutePacket(packet, ifc); } } finally { // Nodal processing delay is the time it takes on average to process // a single IP packet. if (inputQueue.Count > 0) { Simulation.Callback(nodalProcessingDelay, ProcessPackets); } } }