PageRenderTime 43ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/verify/src/Checked/Drivers/Network/Intel/IntelRxRingBuffer.cs

#
C# | 193 lines | 126 code | 34 blank | 33 comment | 18 complexity | 038a6ed6c45eaaef80315467e77d9ff2 MD5 | raw file
  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Microsoft Research Singularity
  4. //
  5. // Copyright (c) Microsoft Corporation. All rights reserved.
  6. //
  7. // Notes: Adaptor class for the Rx ring buffer.
  8. //
  9. using Microsoft.Contracts;
  10. using Microsoft.Singularity.Channels;
  11. using Microsoft.Singularity.Io;
  12. using Microsoft.Singularity.Io.Net;
  13. using Microsoft.Singularity.V1.Services;
  14. using Microsoft.SingSharp;
  15. using System;
  16. using ExRefPacketFifo = Microsoft.Singularity.NetStack2.Channels.Nic.ExRefPacketFifo;
  17. using ByteOrder = Drivers.Net.ByteOrder;
  18. namespace Microsoft.Singularity.Drivers.Network.Intel
  19. {
  20. internal class IntelRxRingBuffer
  21. {
  22. IntelRingBuffer rxRingBuffer;
  23. ExRefPacketFifo rxPacketsInDevice;
  24. internal System.Threading.MonitorLock thisLock = new System.Threading.MonitorLock();
  25. internal IntelRxRingBuffer(uint capacity)
  26. //requires capacity > 0 && IntelRingBuffer.IsPowerOf2(capacity);
  27. {
  28. this.rxRingBuffer = new IntelRingBuffer(capacity);
  29. this.rxPacketsInDevice = new ExRefPacketFifo(
  30. new PacketFifo((int) capacity),
  31. false
  32. );
  33. }
  34. internal void Reset()
  35. {
  36. rxRingBuffer.Reset();
  37. }
  38. ///////////////////////////////////////////////////////////////////////
  39. //
  40. // Buffer Operations, should only be called when a lock is held
  41. // this ring buffer.
  42. //
  43. private void LockedPushRecvBuffer(int length)
  44. {
  45. // (ARM only, not x86) PlatformService.InvalidateDCache(packetVirtAddr, (UIntPtr)length);
  46. ulong controlBits = (ulong) ByteOrder.HostToLittleEndian(length);
  47. rxRingBuffer.Push(controlBits);
  48. }
  49. static int pass = 0;
  50. internal void LockedPushRecvBuffer(Packet packet)
  51. {
  52. DebugStub.Assert(packet.FragmentCount == 1);
  53. DebugStub.Assert(!rxRingBuffer.IsFull);
  54. int length = packet.GetFragmentLength(0);
  55. this.LockedPushRecvBuffer(length);
  56. PacketFifo liveFifo = this.rxPacketsInDevice.Acquire();
  57. liveFifo.Push(packet);
  58. rxPacketsInDevice.Release(liveFifo);
  59. }
  60. internal void Dump()
  61. {
  62. rxRingBuffer.Dump("rx", 8);
  63. }
  64. private FromDeviceFlags GetRecvPktFlags(uint stat_err_flags)
  65. {
  66. FromDeviceFlags fromDevFlags = 0;
  67. if (((RxErrStatFields.CRC_ERROR | RxErrStatFields.SYMBOL_ERROR |
  68. RxErrStatFields.SEQUENCE_ERROR | RxErrStatFields.CARRIER_EXT_ERROR |
  69. RxErrStatFields.RX_DATA_ERROR) & stat_err_flags) != 0) {
  70. Intel.DebugPrint("Packet Rsv Error\n");
  71. fromDevFlags |= FromDeviceFlags.ReceiveError;
  72. } else {
  73. fromDevFlags |= FromDeviceFlags.ReceiveSuccess;
  74. }
  75. if (((stat_err_flags & RxErrStatFields.IGNORE_CHECKSUM) == 0) &&
  76. ((stat_err_flags & RxErrStatFields.IP_CHECKSUM_CALC) != 0)) {
  77. if ((stat_err_flags & RxErrStatFields.IP_CHECKSUM_ERROR) != 0) {
  78. Intel.DebugPrint("Bad Ip Checksum\n");
  79. fromDevFlags |= FromDeviceFlags.BadIp4Checksum;
  80. } else {
  81. // Good IP checksum flag???
  82. }
  83. }
  84. if (((stat_err_flags & RxErrStatFields.IGNORE_CHECKSUM) == 0) &&
  85. ((stat_err_flags & RxErrStatFields.TCP_CHECKSUM_CALC)!= 0)) {
  86. if ((stat_err_flags & RxErrStatFields.TCP_CHECKSUM_ERROR) != 0) {
  87. fromDevFlags |= (FromDeviceFlags.BadTcp4Checksum |
  88. FromDeviceFlags.BadUdp4Checksum);
  89. // don't know if UDP or TCP
  90. Intel.DebugPrint("Bad TCP/UDP Checksum\n");
  91. } else {
  92. fromDevFlags |= (FromDeviceFlags.GoodTcp4Checksum |
  93. FromDeviceFlags.GoodUdp4Checksum);
  94. }
  95. }
  96. //DebugStub.Assert((fromDevFlags == (FromDeviceFlags.ReceiveSuccess)) || (fromDevFlags == (FromDeviceFlags.ReceiveSuccess | FromDeviceFlags.GoodTcp4Checksum | FromDeviceFlags.GoodUdp4Checksum)));
  97. return fromDevFlags;
  98. }
  99. private Packet MakePacketFromDescriptor(DmaMemory mem, ulong controlBits)
  100. {
  101. PacketFifo inDevPkts = rxPacketsInDevice.Acquire();
  102. Packet packet = inDevPkts.Pop();
  103. int length = (int) ((controlBits & RxDescriptor.LENGTH_MASK)
  104. >> RxDescriptor.LENGTH_SHIFT);
  105. uint stat_err = (uint) ((controlBits & RxDescriptor.ERR_STAT_MASK)
  106. >> RxDescriptor.ERR_STAT_SHIFT);
  107. // can't deal with fragments yet
  108. if ((stat_err & RxErrStatFields.END_OF_PACKET) == 0) {
  109. INucleusCalls.DebugPrintHex(40, 0xd0);
  110. DebugStub.Print("FRAGMENT\n");
  111. throw new Exception();
  112. }
  113. //DebugStub.Assert((stat_err & RxErrStatFields.END_OF_PACKET) != 0);
  114. //DebugStub.Assert(packet.GetFragmentVirtualAddress(0) == fragmentVirtAddr);
  115. packet.FromDeviceFlags = GetRecvPktFlags(stat_err);
  116. packet.SetFragment(0, mem.BytesRef(0, length));
  117. rxPacketsInDevice.Release(inDevPkts);
  118. return packet;
  119. }
  120. internal void LockedDrainRecvBuffer(PacketFifo toUser)
  121. {
  122. DmaMemory mem;
  123. ulong controlBits;
  124. while (rxRingBuffer.Peek(out mem, out controlBits)) {
  125. Packet packet = MakePacketFromDescriptor(mem, controlBits);
  126. toUser.Push(packet);
  127. rxRingBuffer.Pop();
  128. }
  129. }
  130. ///////////////////////////////////////////////////////////////////////
  131. //
  132. // Ring buffer properties
  133. //
  134. internal UIntPtr BaseAddress
  135. {
  136. get { return rxRingBuffer.BaseAddress; }
  137. }
  138. internal bool NewReceiveEvent() {
  139. DmaMemory mem;
  140. ulong controlBits;
  141. return rxRingBuffer.Peek(out mem, out controlBits);
  142. // return rxRingBuffer.Peek();
  143. }
  144. //[Pure]
  145. internal uint Capacity { get { return rxRingBuffer.Capacity; } }
  146. //[Pure]
  147. internal uint Free { get { return rxRingBuffer.Free; } }
  148. //[Pure]
  149. internal bool IsFull { get { return rxRingBuffer.IsFull; } }
  150. //[Pure]
  151. internal uint Count { get { return rxRingBuffer.Count; } }
  152. //[Pure]
  153. internal uint Tail { get { return rxRingBuffer.Tail; } }
  154. //[Pure]
  155. internal uint Head { get { return rxRingBuffer.Head; } }
  156. //[Pure]
  157. internal uint DescLength { get { return rxRingBuffer.DescLength; } }
  158. }
  159. }