//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 IrqWorkerMain() { DebugPrint( "Intel {0} Ethernet Driver irq worker thread started.\n", DebugStub.ArgList(this.cardName) ); uint rcnt = 0; uint missed = 0; uint nobuf = 0; while (irqWorkerStop == false) { Thread.Yield(); //TODO: irq.WaitForInterrupt(); uint icr = Read32(Register.ICR); HandleInterrupts(icr); rcnt += Read32(Register.TOTAL_RECV_PACKETS); missed += Read32(0x4010); nobuf += Read32(0x40a0); INucleusCalls.DebugPrintHex(10, rcnt - nobuf); INucleusCalls.DebugPrintHex(20, rcnt); INucleusCalls.DebugPrintHex(30, missed); //TODO: irq.AckInterrupt(); } DisableInterrupts(); DebugPrint( "Intel {0} Ethernet Driver irq worker thread stopped.\n", DebugStub.ArgList(this.cardName) ); }
/////////////////////////////////////////////////////////////////////// // // Setup functions // private void ResetDevice() { // Disable all interrupts DisableInterrupts(); DebugWriteLine("CTRL pre-device-reset : {0:x8}\n", DebugStub.ArgList(Read32(Register.CTRL))); Write32(Register.RECV_CTRL, 0); Write32(Register.TSMT_CTRL, TsmtCtrlBits.PAD_SHORT_PACKETS); Read32(Register.STATUS); // Allow pending PCI transactions to complete Delay(10); // Reset the device RegSetBits((int)Register.CTRL, CtrlBits.RST | CtrlBits.PHY_RST); // Wait for 3us before board is really reset Delay(3); Delay(100); Read32(Register.CTRL); // Set the control register to the proper initial values, // clearing RST and PHY_RST as a side-effect. Write32(Register.CTRL, CtrlBits.FD | CtrlBits.ASDE | CtrlBits.SLU); while ((Read32(Register.CTRL) & CtrlBits.RST) != 0) { DebugWriteLine("."); } DebugWriteLine("Autonegotiation complete"); }
public bool IsChecksumValid() { ushort sum = (ushort)((((int)verLen) << 8) + ((int)tos)); sum = SumShortValues(sum, totalLength); sum = SumShortValues(sum, id); sum = SumShortValues(sum, offset); sum = SumShortValues(sum, (ushort)((((int)ttl) << 8) + ((int)protocol))); sum = SumShortValues(sum, (ushort)(((uint)srcAddress) >> 16)); sum = SumShortValues(sum, (ushort)(((uint)srcAddress) & 0xFFFFU)); sum = SumShortValues(sum, (ushort)(((uint)destAddress) >> 16)); sum = SumShortValues(sum, (ushort)(((uint)destAddress) & 0xFFFFU)); //fix for 0 checksum unchecked { sum = (ushort)~sum; } if (sum == 0) { sum = (ushort)0xFFFF; } if (sum != checksum) { DebugStub.WriteLine("Bad IP Checksum {0:x4} != {1:x4}", DebugStub.ArgList(checksum, sum)); } return(sum == checksum); }
internal override void ReceiveEvent(DhcpFormat dhcp) { //DebugStub.WriteLine("FSM DHCP packet SELECTING.\n"); // Check if message is in response to our request if (dhcp.BootMessageType != DhcpFormat.BootType.Reply || dhcp.TransactionID != client.TransactionID || dhcp.GetHardwareAddress() != client.MacAddress) { DebugStub.WriteLine("FSM DHCP bad id.\n"); return; } IPv4 serverAddress = dhcp.NextServerIPAddress; // Check if offered address is valid (ie not zero // and below class E) IPv4 offeredAddress = dhcp.YourIPAddress; if (offeredAddress == IPv4.Any || offeredAddress.IsMulticast()) { DebugStub.WriteLine("FSM DHCP multicast addr.\n"); return; } // Check if message is an offer SortedList offeredOptions = dhcp.GetOptions(); DhcpByteOption messageType = offeredOptions[DhcpMessageType.OptionCode] as DhcpByteOption; if (messageType == null || messageType.Value != (byte)DhcpFormat.MessageType.Offer) { DebugStub.WriteLine("FSM DHCP not an offer.\n"); return; } // Must have parameters byte [] parameters = new byte [] { DhcpSubnetMask.OptionCode, DhcpRouter.OptionCode, // DhcpDomainNameServer.OptionCode }; foreach (byte p in parameters) { IDhcpOption ido = offeredOptions[p] as IDhcpOption; if (ido == null) { DebugStub.WriteLine("FSM DHCP missing option 0x{0:x2}.\n", DebugStub.ArgList(p)); return; } } client.CancelStateTimeout(); client.ChangeState(new DhcpClientStateRequesting(client, serverAddress, offeredAddress, offeredOptions)); }
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); }
internal static void DebugPrint(string format, params object [] args) { DebugStub.Print("DhcpClient: {0}", DebugStub.ArgList( string.Format(format, args)) ); }
internal static void DebugPrint(string format, params object [] arguments) { DebugStub.Print("UDP: {0}", DebugStub.ArgList( string.Format(format, arguments)) ); }
static void DebugPrint(string format, params object [] args) { DebugStub.Print( "UdpConnectionExpThread [{0}]: {1}", DebugStub.ArgList( string.Format(format, args) ) ); }
//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(); } }
private void DumpPhy() { for (uint i = 0; i < 32; i += 8) { DebugWriteLine("PHY {0:x4} : {1:x4} {2:x4} {3:x4} {4:x4} {5:x4} {6:x4} {7:x4} {8:x4}", DebugStub.ArgList(i, MiiRead(PhyAddress, i + 0), MiiRead(PhyAddress, i + 1), MiiRead(PhyAddress, i + 2), MiiRead(PhyAddress, i + 3), MiiRead(PhyAddress, i + 4), MiiRead(PhyAddress, i + 5), MiiRead(PhyAddress, i + 6), MiiRead(PhyAddress, i + 7)) ); } }
/* internal static UIntPtr GetPhysicalAddress(UIntPtr va) { UIntPtr pa; // Physical address UIntPtr paLeft; // Bytes remaining on physical page if (!DeviceService.GetDmaPhysicalAddress(va, out pa, out paLeft) || pa == UIntPtr.Zero || paLeft < Intel.IEEE8023FrameBytes) { throw new ApplicationException("Bad DMA pointer"); } return pa; } */ internal void Dump(string preamble, uint count) { if (count > this.capacity) { count = this.capacity; } Intel.DebugWriteLine("Head {0} Tail {1}\n", DebugStub.ArgList(this.Head, this.Tail)); for (uint i = 0; i < count; i++) { ulong address = this.region.Read64((int)(i * 16)); ulong fields = this.region.Read64((int)(i * 16 + 8)); Intel.DebugWriteLine("{0}: [{1}] Address {2:x16} Sp={3:x4} Err={4:x1} Sta={5:x2} Checksum {6:x4} Length {7:x4}", DebugStub.ArgList(preamble, i, address, (fields >> 48) & 0xffff, (fields >> 40) & 0xff, (fields >> 32) & 0xff, (fields >> 16) & 0xffff, fields & 0xffff)); } }
internal void ReportChanges(uint[] now) { DebugWriteLine("Changes."); for (int i = 0; i < now.Length; i++) { if (now[i] != 0) { DebugWriteLine("{0} [0x40{1:x1}] -> {2}", DebugStub.ArgList(i, i * 4, now[i])); } } rxRingBuffer.Dump(); DebugWriteLine("Rx head {0:x8} tail {1:x8}", DebugStub.ArgList(Read32(Register.RECV_DESC_HEAD), Read32(Register.RECV_DESC_TAIL))); DebugWriteLine("ICS = {0:x8} ICR = {1:x8}", DebugStub.ArgList(Read32(Register.ICS), Read32(Register.ICR))); }
//create a byte aligned ipheader //index marks the starting location of the ip header within the buffer public IpHeader(Bytes packet, int index) { //assert that the packet is large enough for a ipheader VTable.Assert(packet.Length - index > 20); verLen = packet[index++]; tos = packet[index++]; totalLength = NetworkBitConverter.ToUInt16(packet, index); index += 2; id = NetworkBitConverter.ToUInt16(packet, index); index += 2; offset = NetworkBitConverter.ToUInt16(packet, index); index += 2; ttl = packet[index++]; protocol = packet[index++]; checksum = NetworkBitConverter.ToUInt16(packet, index); index += 2; uint addr; addr = NetworkBitConverter.ToUInt32(packet, index); srcAddress = new IPv4(addr); index += 4; addr = NetworkBitConverter.ToUInt32(packet, index); destAddress = new IPv4(addr); #if false DebugStub.Print("IpHeader verlen 0x{0,8:x}\n tos {1}\n" + " totalLength {2}\n ttl {3}\n protocol 0x{4,4:x}\n" + " checksum 0x{5,4:x}\n src {6}\n, dest {7}\n", DebugStub.ArgList(verLen, tos, totalLength, ttl, protocol, checksum, srcAddress, destAddress)); #endif //sgc complains... pad0 = 0; pad1 = 0; pad2 = 0; pad3 = 0; }
private void DumpBufferDebugRegisters() { // TODO, uses Tracing log DebugPrint("Device Control {0:x8} Device Status {1:x8}\n", DebugStub.ArgList(Read32(Register.CTRL), Read32(Register.STATUS))); //DebugPrint("PCI Status {0:x4}", DebugStub.ArgList(this.pciConfig.Status)); DebugPrint("Recv Control {0:x8} Tsmt Control {1:x8}\n", DebugStub.ArgList(Read32(Register.RECV_CTRL), Read32(Register.TSMT_CTRL))); DebugPrint("RDTR {0:x8} RADV {1:x8}\n", DebugStub.ArgList(Read32(0x2820), Read32(0x282c))); DebugPrint("Total Transmit {0:x8} Total Received {1:x8}\n", DebugStub.ArgList(Read32(Register.TOTAL_TSMT_PACKETS), Read32(Register.TOTAL_RECV_PACKETS))); DebugPrint("Interrupt Mask {0:x8} Rx Error Count {1:x8}\n", DebugStub.ArgList(Read32(Register.IMS), Read32(Register.RX_ERR_COUNT))); DebugPrint("Recv Addr High {0:x8} Recv Addr Low {1:x8}\n", DebugStub.ArgList(Read32(Register.RAH0), Read32(Register.RAL0))); DebugPrint("Recv Desc Head {0:x8} Recv Desc Tail {1:x8}\n", DebugStub.ArgList(Read32(Register.RECV_DESC_HEAD), Read32(Register.RECV_DESC_TAIL))); DebugPrint("Tsmt Desc Head {0:x8} Tsmt Desc Tail {1:x8}\n", DebugStub.ArgList(Read32(Register.TSMT_DESC_HEAD), Read32(Register.TSMT_DESC_TAIL))); }
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(); } } }
public static void ProcessIncomingPacket(Bytes packet, IAdapter adapter) { //check the header //send it off to the instance of the protocol to further parse and handle try { ushort protocol; EthernetHeader.GetProtocol(packet, out protocol); switch (protocol) { case EthernetHeader.PROTOCOL_IP: DebugPrint("IP\n"); // DebugPrint("Received IP Packet...processing\n"); IP.ProcessIncomingPacket(packet, adapter); DebugPrint("IP D\n"); break; case EthernetHeader.PROTOCOL_ARP: // DebugPrint("Received ARP Packet...processing\n"); DebugPrint("ARP\n"); arp.ProcessIncomingPacket(packet, adapter); DebugPrint("ARPD\n"); break; case EthernetHeader.PROTOCOL_NLB: DebugPrint("Received NLB packet...discarding\n"); //delete packet; break; case 0x8100: DebugPrint("Q/P\n"); break; case EthernetHeader.PROTOCOL_IP6: DebugPrint("IPv6\n"); break; default: DebugPrint("Unexpected Ethernet protocol ", protocol.ToString("X") + ". "); // DebugStub.Break(); //delete packet; break; } } catch (Exception e) { DebugStub.Print("Exception in Ethernet.ProcessIncomingPacket txt:{0}\n", DebugStub.ArgList(e)); DebugStub.Break(); } }
internal static void DebugPrint(string format) { DebugStub.Print("UDP: {0}", DebugStub.ArgList(format)); }
public bool ReleaseDataFromTxBuffer(uint bytes) { uint totalBytes = bytes; if (this.Empty) { DebugStub.Print("Attempting to release {0} bytes on an empty list? size {1}\n", DebugStub.ArgList(bytes, this.size)); DebugStub.Break(); return(false); } else if (bytes > this.size) { DebugStub.Print("Ack! attempting to release {0} bytes size {1} bytes\n", DebugStub.ArgList(bytes, this.size)); bytes = this.size; } if (bytes > this.currentTxTotalOffset) { DebugStub.Print("ack! trying to release more than total offset??\n"); DebugStub.Break(); } TcpVectorNode candidate = this.listHead.next; while (bytes != 0) { if (candidate.length <= bytes) { TcpVectorNode toFree = candidate; candidate = candidate.next; bytes = bytes - toFree.length; this.size -= toFree.length; if (this.currentTxBuff == toFree) { this.currentTxBuff = null; this.currentTxBufferOffset = 0; } Bytes data = toFree.Unlink(); this.count--; if (data != null) { //delete data; } } else { candidate.TrimStart(bytes); //this happens when some packets being retransmitted are //acknowledged during retransmission. if ((candidate == this.currentTxBuff) && (candidate.startOffset > this.currentTxBufferOffset)) { DebugStub.WriteLine("startoffset was {0} now {1} current offset {2} totalBytes to Free {3}\n", DebugStub.ArgList((candidate.startOffset - bytes), candidate.startOffset, this.currentTxBufferOffset, totalBytes)); this.currentTxBufferOffset = candidate.startOffset; } this.size -= bytes; bytes = 0; } } if (this.Empty) { return(false); } return(true); }
//dirt simple is the name of the game public static void ProcessIncomingPacket(Bytes packet, IAdapter adapter) { IpHeader ipHeader = new IpHeader(packet, EthernetHeader.Size); //since we apparently don't support fragments yet. if (ipHeader.MoreFragmentsFollowing() == true) { DebugPrint("ACK! ip fragmentation!\n"); return; } // DebugStub.Assert(ipHeader.MoreFragmentsFollowing() == false); //VTable.Assert(ipHeader.MoreFragmentsFollowing() == false); if (ipHeader.IsChecksumValid() == false) { DebugPrint("ProcessIncomingPacket: bad checksum...dropping packets\n"); //delete packet; return; } //make sure the address is 'local' if (hostConfiguration == null) { DebugPrint("ACK hostConfiguration is NULL\n"); return; } if ((hostConfiguration.IsLocalAddress(ipHeader.destAddress) == false) && (ipHeader.destAddress != IPv4.Broadcast)) { // DebugPrint("ProcessIncomingPacket: wrong address ...dropping packets\n"); // DebugPrint("Dest address {0}\n", ipHeader.destAddress); //delete packet; return; } try { //figure out to which protocol the packet belongs switch (ipHeader.protocol) { case IpHeader.TCP: DebugPrint("ProcessIncomingPacket: Got TCP packet\n"); //TCP.ProcessIncomingPacket(packet, ipHeader); break; case IpHeader.UDP: //DebugPrint("ProcessIncomingPacket: Got UDP packet\n"); UDP.ProcessIncomingPacket(packet, ipHeader); break; case IpHeader.ICMP: DebugPrint("ProcessIncomingPacket: Got ICMP packet\n"); //delete packet; break; default: DebugPrint("Got unexpected packet!!\n"); //delete packet; DebugStub.Break(); break; } } catch (Exception e) { DebugStub.Print("Caught exception {0}\n", DebugStub.ArgList(e)); DebugStub.Break(); } }
//This function will format the higher layer packet to //have to correct ethernet and ip header? //Routing to multiple cards was broken in the old netstack... //for now we support a single interface //ipheader is already written...we just need to write the ethernet header public static void SendOutgoingPacket(Bytes header, Bytes buffer, IPv4 destinationAddress) { DebugPrint("IP.SendOutgoingPacket: dst {0}\n", destinationAddress); RouteEntry e = hostConfiguration.RoutingTable.Lookup(destinationAddress); if (e == null) { //delete header; //delete buffer; DebugPrint("Packet dropped -- no route\n"); return; } IPv4 ifaddr = e.InterfaceAddress; IPv4 nextHop; if (e.Gateway == e.InterfaceAddress) { nextHop = destinationAddress; } else { nextHop = e.Gateway; } DebugPrint("Selected destination {0}\n", nextHop); DebugStub.Assert(e.Gateway == e.InterfaceAddress); IAdapter adapter = hostConfiguration.Bindings.GetAdapter(ifaddr); VTable.Assert(adapter != null); EthernetAddress localMac = adapter.HardwareAddress; EthernetAddress remoteMac; IAdapter targetAdapter = hostConfiguration.Bindings.GetAdapter(nextHop); if (targetAdapter != null) { remoteMac = targetAdapter.HardwareAddress; } else { if (arp.Lookup(nextHop, out remoteMac) == false) { DebugStub.WriteLine("Outgoing packet, no ARP Entry for: {0}...about to wait\n", DebugStub.ArgList(nextHop)); arp.ArpRequest(ifaddr, nextHop, localMac, header, buffer, adapter); // DebugPrint("ArpRequest complete...sending packet\n"); // bool rc = arp.Lookup(nextHop, out remoteMac); // DebugStub.Assert(rc == true); return; } } //Format ethernet header EthernetHeader.Write(header, localMac, remoteMac, EthernetHeader.PROTOCOL_IP); //send it! adapter.PopulateTxRing(header, buffer); }
internal static void DebugPrint(string format) { DebugStub.Print("ChainedHash: {0}", DebugStub.ArgList(format)); }
private static void DebugPrint(string format, params object [] arguments) { DebugStub.Print("DNSClient {0}", DebugStub.ArgList( string.Format(format, arguments))); }