Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

344 lines
6.0 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. io.c
  5. Abstract:
  6. Contains the send/rcv packet routines
  7. Author:
  8. Stefan Solomon 07/06/1995
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. // nr of receive work items (receive packets) posted
  14. ULONG RcvPostedCount;
  15. // nr of send worl items posted
  16. ULONG SendPostedCount;
  17. // high and low water marks for the current count of posted rcv packets
  18. #define RCV_POSTED_LOW_WATER_MARK 8
  19. #define RCV_POSTED_HIGH_WATER_MARK 16
  20. ULONG RcvPostedLowWaterMark = RCV_POSTED_LOW_WATER_MARK;
  21. ULONG RcvPostedHighWaterMark = RCV_POSTED_HIGH_WATER_MARK;
  22. DWORD
  23. ReceiveSubmit(PWORK_ITEM wip);
  24. /*++
  25. Function: OpenIpxWanSocket
  26. Descr:
  27. --*/
  28. HANDLE IpxWanSocketHandle;
  29. DWORD
  30. OpenIpxWanSocket(VOID)
  31. {
  32. USHORT ipxwansocket;
  33. PUTUSHORT2SHORT(&ipxwansocket, IPXWAN_SOCKET);
  34. if((IpxWanSocketHandle = CreateSocketPort(ipxwansocket)) == INVALID_HANDLE_VALUE) {
  35. Trace(INIT_TRACE, "CreateSocketPort FAILED!\n");
  36. return ERROR_CAN_NOT_COMPLETE;
  37. }
  38. return NO_ERROR;
  39. }
  40. /*++
  41. Function: CloseIpxWanSocket
  42. Descr:
  43. --*/
  44. DWORD
  45. CloseIpxWanSocket(VOID)
  46. {
  47. DWORD rc;
  48. rc = DeleteSocketPort(IpxWanSocketHandle);
  49. Trace(INIT_TRACE, "IpxWan: DeleteSocketPort rc = %d\n", rc);
  50. while ((RcvPostedCount>0) || (SendPostedCount>0))
  51. SleepEx (1000, TRUE);
  52. return rc;
  53. }
  54. /*++
  55. Function: StartReceiver
  56. Descr: Starts allocating and posting receive
  57. work items until it reaches the low water mark.
  58. --*/
  59. VOID
  60. StartReceiver(VOID)
  61. {
  62. PWORK_ITEM wip;
  63. DWORD rc;
  64. ACQUIRE_QUEUES_LOCK;
  65. while(RcvPostedCount < RcvPostedLowWaterMark) {
  66. if((wip = AllocateWorkItem(RECEIVE_PACKET_TYPE)) == NULL) {
  67. // !!! log something
  68. break;
  69. }
  70. if((rc = ReceiveSubmit(wip)) != NO_ERROR) {
  71. FreeWorkItem(wip);
  72. break;
  73. }
  74. }
  75. RELEASE_QUEUES_LOCK;
  76. }
  77. /*++
  78. Function: RepostRcvPacket
  79. Descr:
  80. --*/
  81. VOID
  82. RepostRcvPacket(PWORK_ITEM wip)
  83. {
  84. ACQUIRE_QUEUES_LOCK;
  85. if(RcvPostedCount >= RcvPostedHighWaterMark) {
  86. // discard the received wi and don't repost
  87. FreeWorkItem(wip);
  88. }
  89. else
  90. {
  91. if(ReceiveSubmit(wip) != NO_ERROR) {
  92. FreeWorkItem(wip);
  93. }
  94. }
  95. RELEASE_QUEUES_LOCK;
  96. }
  97. /*++
  98. Function: ReceiveComplete
  99. Descr: invoked in the io completion thread when a receive packet has completed.
  100. if the number of receive packets waiting to be processed is below
  101. the limit then
  102. Enqueues the received packet work item in the WorkersQueue.
  103. Finally, it reposts a new receive packet if below the low water mark.
  104. --*/
  105. VOID
  106. ReceiveComplete(PWORK_ITEM wip)
  107. {
  108. PWORK_ITEM newwip;
  109. DWORD rc;
  110. PUCHAR reservedp;
  111. reservedp = wip->AddressReserved.Reserved;
  112. wip->AdapterIndex = GetNicId(reservedp);
  113. InterlockedDecrement(&RcvPostedCount);
  114. // repost if below water mark
  115. if (wip->IoCompletionStatus!=NO_ERROR) {
  116. if((wip->IoCompletionStatus!=ERROR_OPERATION_ABORTED)
  117. && (wip->IoCompletionStatus!=ERROR_INVALID_HANDLE)) {
  118. Trace(RECEIVE_TRACE, "Receive failed with error 0x%x\n",
  119. wip->IoCompletionStatus);
  120. ACQUIRE_QUEUES_LOCK;
  121. if (RcvPostedCount < RcvPostedLowWaterMark) {
  122. if(ReceiveSubmit(wip) == NO_ERROR) {
  123. RELEASE_QUEUES_LOCK;
  124. return;
  125. }
  126. }
  127. RELEASE_QUEUES_LOCK;
  128. }
  129. // Closing, or enough posted already, or failed to repost
  130. FreeWorkItem(wip);
  131. return;
  132. }
  133. //
  134. //** Process the received packet **
  135. //
  136. ACQUIRE_QUEUES_LOCK;
  137. // first repost a new receive packet if below water mark
  138. if(RcvPostedCount < RcvPostedLowWaterMark) {
  139. if((newwip = AllocateWorkItem(RECEIVE_PACKET_TYPE)) == NULL) {
  140. Trace(RECEIVE_TRACE, "ReceiveComplete: Cannot allocate work item\n");
  141. }
  142. else
  143. {
  144. // repost the new receive packet and increment the ref count
  145. if((rc = ReceiveSubmit(newwip)) != NO_ERROR) {
  146. FreeWorkItem(newwip);
  147. }
  148. }
  149. }
  150. EnqueueWorkItemToWorker(wip);
  151. RELEASE_QUEUES_LOCK;
  152. }
  153. /*++
  154. Function: SendComplete
  155. Descr: invoked in the worker thread APC when a send packet has completed
  156. --*/
  157. VOID
  158. SendComplete(PWORK_ITEM wip)
  159. {
  160. InterlockedDecrement(&SendPostedCount);
  161. // if one time send packet type, free it
  162. if(!wip->ReXmitPacket) {
  163. FreeWorkItem(wip);
  164. return;
  165. }
  166. ACQUIRE_QUEUES_LOCK;
  167. wip->WiState = WI_SEND_COMPLETED;
  168. EnqueueWorkItemToWorker(wip);
  169. RELEASE_QUEUES_LOCK;
  170. }
  171. /*++
  172. Function: ReceiveSubmit
  173. Descr: posts a receive packet work item for receive
  174. increments the receive posted count
  175. --*/
  176. DWORD
  177. ReceiveSubmit(PWORK_ITEM wip)
  178. {
  179. DWORD rc;
  180. wip->Overlapped.hEvent = NULL;
  181. rc = IpxRecvPacket(IpxWanSocketHandle,
  182. wip->Packet,
  183. MAX_IPXWAN_PACKET_LEN,
  184. &wip->AddressReserved,
  185. &wip->Overlapped,
  186. NULL);
  187. if(rc != NO_ERROR) {
  188. Trace(RECEIVE_TRACE, "Failed to submit receive error 0x%x\n", rc);
  189. }
  190. else
  191. {
  192. InterlockedIncrement(&RcvPostedCount);
  193. }
  194. return rc;
  195. }
  196. /*++
  197. Function: SendSubmit
  198. Descr: posts a send packet work item for send to the adapter index
  199. specified by the work item
  200. increments the send statistics for the interface specified
  201. by the work item
  202. Remark: >> called with the interface lock held <<
  203. --*/
  204. DWORD
  205. SendSubmit(PWORK_ITEM wip)
  206. {
  207. DWORD rc;
  208. USHORT SendPacketLength;
  209. // get the length from the packet to send
  210. SendPacketLength = GETSHORT2USHORT(&SendPacketLength, wip->Packet + IPXH_LENGTH);
  211. wip->Overlapped.hEvent = NULL;
  212. rc = IpxSendPacket(IpxWanSocketHandle,
  213. wip->AdapterIndex,
  214. wip->Packet,
  215. (ULONG)SendPacketLength,
  216. &wip->AddressReserved,
  217. &wip->Overlapped,
  218. NULL);
  219. if(rc != NO_ERROR) {
  220. Trace(SEND_TRACE, "Failed to send the packet on adapter %d error 0x%x\n",
  221. wip->acbp->AdapterIndex,
  222. rc);
  223. }
  224. else
  225. {
  226. InterlockedIncrement(&SendPostedCount);
  227. }
  228. return rc;
  229. }