Leaked source code of windows server 2003
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.

1320 lines
33 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. wanarp2\send.c
  5. Abstract:
  6. The file contains the part of interface of the IP in IP tunnel driver
  7. to the TCP/IP stack that deals with sending data
  8. The code is a cleaned up version of wanarp\ipif.c which in turn
  9. was derived from HenrySa's ip\arp.c
  10. Revision History:
  11. AmritanR
  12. --*/
  13. #define __FILE_SIG__ SEND_SIG
  14. #include "inc.h"
  15. NDIS_STATUS
  16. WanIpTransmit(
  17. PVOID pvContext,
  18. NDIS_PACKET **ppPacketArray,
  19. UINT uiNumPackets,
  20. DWORD dwDestAddr,
  21. RouteCacheEntry *pRce,
  22. PVOID pvLinkContext
  23. )
  24. /*++
  25. Routine Description:
  26. Function called by IP to send an array of packets. We allocate
  27. one ETH_HEADER for each packet. The adapter (which is the pvContext)
  28. is locked. If the adapter is not mapped, we fail the send, otherwise
  29. we lock the interface. If
  30. Locks:
  31. Arguments:
  32. pvContext Our context to IP for the interface - the PTUNNEL
  33. ppPacketArray The array of NDIS_PACKETs to send
  34. uiNumPackets The number of packets in the array
  35. dwDestAddr The destination (next hop) address
  36. pRce Pointer to RCE.
  37. Return Value:
  38. NDIS_STATUS_SUCCESS
  39. --*/
  40. {
  41. PADAPTER pAdapter;
  42. PUMODE_INTERFACE pInterface;
  43. PADDRESS_CONTEXT pAddrContext;
  44. PCONN_ENTRY pConnEntry;
  45. KIRQL kiIrql;
  46. NDIS_STATUS nsResult;
  47. UINT i;
  48. LIST_ENTRY leBufferList;
  49. TraceEnter(SEND, "IpTransmit");
  50. Trace(SEND,TRACE,
  51. ("IpTransmit: %d packet(s) over %p/%p to %d.%d.%d.%d\n",
  52. uiNumPackets,
  53. pvContext,
  54. pvLinkContext,
  55. PRINT_IPADDR(dwDestAddr)));
  56. if(g_nhNdiswanBinding is NULL)
  57. {
  58. //
  59. // In the process of shutting down, return
  60. //
  61. return NDIS_STATUS_ADAPTER_NOT_READY;
  62. }
  63. //
  64. // Get the ethernet headers for each packet
  65. //
  66. if(!GetBufferListFromPool(&g_bpHeaderBufferPool,
  67. uiNumPackets,
  68. &leBufferList))
  69. {
  70. //
  71. // Couldnt get headers for all the buffers
  72. //
  73. Trace(SEND, ERROR,
  74. ("IpTransmit: couldnt allocate %d header buffers\n",
  75. uiNumPackets));
  76. return NDIS_STATUS_RESOURCES;
  77. }
  78. //
  79. // This function is not guaranteed to be at dispatch
  80. // The context given to us is a pointer to our adapter
  81. //
  82. pConnEntry = NULL;
  83. pAdapter = (PADAPTER)pvContext;
  84. RtAcquireSpinLock(&(pAdapter->rlLock),
  85. &kiIrql);
  86. if(pAdapter->byState isnot AS_MAPPED)
  87. {
  88. //
  89. // If the adapter is unmapped, the connection is disconnected
  90. //
  91. RtReleaseSpinLock(&(pAdapter->rlLock),
  92. kiIrql);
  93. FreeBufferListToPool(&g_bpHeaderBufferPool,
  94. &leBufferList);
  95. Trace(SEND, INFO,
  96. ("IpTransmit: Send on %x which is unmapped\n",
  97. pAdapter));
  98. //
  99. // Cant increment stats because we dont have an interface
  100. //
  101. return NDIS_STATUS_ADAPTER_NOT_READY;
  102. }
  103. //
  104. // Since the adapter is mapped, it must have an interface
  105. //
  106. pInterface = pAdapter->pInterface;
  107. RtAssert(pInterface);
  108. RtAcquireSpinLockAtDpcLevel(&(pInterface->rlLock));
  109. //
  110. // If interface is not yet connected (for demand dial case) the copy the
  111. // packet and succeed the send.
  112. //
  113. if(pInterface->dwOperState isnot IF_OPER_STATUS_CONNECTED)
  114. {
  115. if(pInterface->duUsage isnot DU_ROUTER)
  116. {
  117. //
  118. // Just a race condition
  119. //
  120. RtReleaseSpinLockFromDpcLevel(&(pInterface->rlLock));
  121. RtReleaseSpinLock(&(pAdapter->rlLock),
  122. kiIrql);
  123. FreeBufferListToPool(&g_bpHeaderBufferPool,
  124. &leBufferList);
  125. return NDIS_STATUS_ADAPTER_NOT_READY;
  126. }
  127. //
  128. // If IP is transmitting on us, he must have called out to
  129. // connect
  130. //
  131. RtAssert(pInterface->dwOperState is IF_OPER_STATUS_CONNECTING);
  132. Trace(SEND, INFO,
  133. ("IpTransmit: I/F not connected, queueing packet\n"));
  134. //
  135. // New function which queues the whole packet array
  136. //
  137. nsResult = WanpCopyAndQueuePackets(pAdapter,
  138. ppPacketArray,
  139. &leBufferList,
  140. uiNumPackets);
  141. RtReleaseSpinLockFromDpcLevel(&(pInterface->rlLock));
  142. RtReleaseSpinLock(&(pAdapter->rlLock),
  143. kiIrql);
  144. if(nsResult isnot STATUS_SUCCESS)
  145. {
  146. FreeBufferListToPool(&g_bpHeaderBufferPool,
  147. &leBufferList);
  148. }
  149. return nsResult;
  150. }
  151. //
  152. // Find the connection entry for this send
  153. //
  154. if(pAdapter is g_pServerAdapter)
  155. {
  156. pConnEntry = (PCONN_ENTRY)pvLinkContext;
  157. //RtAssert(pConnEntry);
  158. //
  159. // Hack for multicast
  160. //
  161. if(pConnEntry is NULL)
  162. {
  163. pConnEntry = WanpGetConnEntryGivenAddress(dwDestAddr);
  164. }
  165. //
  166. // We are dont with the adapter lock. All we need is to lock down
  167. // the connection entry
  168. // It is important that we release the locks since for dial-in
  169. // clients the locking hierarchy is CONN_ENTRY->ADAPTER->INTERFACE
  170. //
  171. if(pConnEntry)
  172. {
  173. if(pvLinkContext != NULL)
  174. {
  175. ReferenceConnEntry(pConnEntry);
  176. }
  177. }
  178. RtReleaseSpinLockFromDpcLevel(&(pAdapter->rlLock));
  179. RtReleaseSpinLockFromDpcLevel(&(pInterface->rlLock));
  180. //
  181. // NOTE: The state of the connection can change in this window
  182. //
  183. if(pConnEntry)
  184. {
  185. RtAcquireSpinLockAtDpcLevel(&(pConnEntry->rlLock));
  186. //
  187. // Not a useful assert because (i) we add static routes to clients
  188. // and (ii) we have that hack for netbt broadcasts
  189. //
  190. // RtAssert((pConnEntry->dwRemoteAddr is dwDestAddr) or
  191. // (dwAddress is 0xFFFFFFFF));
  192. }
  193. }
  194. else
  195. {
  196. //
  197. // This send is on some adapter other than the server adapter
  198. // Such an adapter has only one connection. For these sends we
  199. // lock the adapter instead of the connection
  200. //
  201. pConnEntry = pAdapter->pConnEntry;
  202. if(pConnEntry)
  203. {
  204. ReferenceConnEntry(pConnEntry);
  205. RtAssert(pConnEntry->pAdapter is pAdapter);
  206. }
  207. }
  208. //
  209. // So now we have a locked connection entry (if client)
  210. // or a locked adapter (for dial out and router)
  211. //
  212. if((pConnEntry is NULL) or
  213. (pConnEntry->byState isnot CS_CONNECTED))
  214. {
  215. if((ULONG)(dwDestAddr & 0x000000FF) < (ULONG) 0x000000E0)
  216. {
  217. Trace(SEND, ERROR,
  218. ("IpTransmit: Could not find conn entry for %d.%d.%d.%d\n",
  219. PRINT_IPADDR(dwDestAddr)));
  220. }
  221. for(i = 0; i < uiNumPackets; i++)
  222. {
  223. PLIST_ENTRY pleNode;
  224. PNDIS_BUFFER pnbBuffer;
  225. PVOID pvFirstBuffer;
  226. UINT uiFirstBufLen, uiTotalLen;
  227. PIP_HEADER pIpHeader;
  228. NdisGetFirstBufferFromPacket(ppPacketArray[i],
  229. &pnbBuffer,
  230. &pvFirstBuffer,
  231. &uiFirstBufLen,
  232. &uiTotalLen);
  233. if (pvFirstBuffer)
  234. {
  235. pIpHeader = (PIP_HEADER)pvFirstBuffer;
  236. RtAssert(pIpHeader);
  237. RtAssert(uiFirstBufLen >= sizeof(IP_HEADER));
  238. if(IsUnicastAddr(pIpHeader->dwDest))
  239. {
  240. pInterface->ulOutUniPkts++;
  241. }
  242. else
  243. {
  244. pInterface->ulOutNonUniPkts++;
  245. }
  246. }
  247. }
  248. //
  249. // The entry has been disconnected.
  250. // This is just a window in the timing
  251. //
  252. pInterface->ulOutDiscards += uiNumPackets;
  253. if(pAdapter is g_pServerAdapter)
  254. {
  255. if(pConnEntry isnot NULL)
  256. {
  257. RtReleaseSpinLock(&(pConnEntry->rlLock),
  258. kiIrql);
  259. }
  260. else
  261. {
  262. KeLowerIrql(kiIrql);
  263. }
  264. }
  265. else
  266. {
  267. RtReleaseSpinLockFromDpcLevel(&(pAdapter->rlLock));
  268. RtReleaseSpinLock(&(pInterface->rlLock),
  269. kiIrql);
  270. }
  271. FreeBufferListToPool(&g_bpHeaderBufferPool,
  272. &leBufferList);
  273. if(pConnEntry)
  274. {
  275. DereferenceConnEntry(pConnEntry);
  276. }
  277. return NDIS_STATUS_ADAPTER_NOT_READY;
  278. }
  279. #if DBG
  280. Trace(SEND, TRACE,
  281. ("IpTransmit: Send on %s\n",
  282. pAdapter->asDeviceNameA.Buffer));
  283. for(i = 0; i < uiNumPackets; i++)
  284. {
  285. PacketContext *pPC;
  286. pPC = (PacketContext *)((ppPacketArray[i])->ProtocolReserved);
  287. RtAssert(pPC->pc_common.pc_owner isnot PACKET_OWNER_LINK);
  288. }
  289. #endif
  290. //
  291. // This function will free the locks
  292. //
  293. nsResult = WanpSendPackets(pAdapter,
  294. pInterface,
  295. pConnEntry,
  296. ppPacketArray,
  297. &leBufferList,
  298. uiNumPackets,
  299. kiIrql);
  300. if(nsResult isnot STATUS_SUCCESS)
  301. {
  302. Trace(SEND,TRACE,
  303. ("IpTransmit: SendPackets returned status %x\n",nsResult));
  304. }
  305. DereferenceConnEntry(pConnEntry);
  306. return nsResult;
  307. }
  308. NDIS_STATUS
  309. WanpSendPackets(
  310. PADAPTER pAdapter,
  311. PUMODE_INTERFACE pInterface,
  312. PCONN_ENTRY pConnEntry,
  313. NDIS_PACKET **ppPacketArray,
  314. PLIST_ENTRY pleBufferList,
  315. UINT uiNumPackets,
  316. KIRQL kiIrql
  317. )
  318. /*++
  319. Routine Description:
  320. Main routine to send an array of packets
  321. Locks:
  322. Called with the connection entry (for dial in) or the adapter+interface
  323. (all others) locked
  324. Arguments:
  325. pAdapter The adapter for the connection
  326. pInterface The interface the adapter is mapped to
  327. pConnEntry The connection entry for the send
  328. ppPacketArray The array of packets to send
  329. pBuffHead A list of buffers for the link layer header
  330. uiNumPackets Number of packets (and ll header buffers)
  331. kiIrql Irql at which the adapter or conn entry was locked
  332. Return Value:
  333. NDIS_STATUS_PENDING
  334. --*/
  335. {
  336. NDIS_STATUS nsStatus;
  337. PBYTE pbyHeader;
  338. ULONG i;
  339. #if DBG
  340. Trace(SEND, TRACE,
  341. ("SendPackets: %s\n",
  342. pAdapter->asDeviceNameA.Buffer));
  343. #endif
  344. for(i = 0; i < uiNumPackets; i++)
  345. {
  346. PNDIS_BUFFER pnbBuffer, pnbTempBuffer;
  347. PLIST_ENTRY pleNode;
  348. PVOID pvFirstBuffer;
  349. UINT uiFirstBufLen, uiTotalBufLen, uiIpHdrLen;
  350. PIP_HEADER pIpHeader;
  351. PBUFFER_HEAD pBufferHead;
  352. NdisGetFirstBufferFromPacket(ppPacketArray[i],
  353. &pnbTempBuffer,
  354. &pvFirstBuffer,
  355. &uiFirstBufLen,
  356. &uiTotalBufLen);
  357. pIpHeader = (PIP_HEADER)pvFirstBuffer;
  358. RtAssert(pIpHeader);
  359. #if DBG
  360. RtAssert((pIpHeader->byVerLen & 0xF0) == 0x40);
  361. RtAssert(LengthOfIpHeader(pIpHeader) >= 20);
  362. #endif
  363. //
  364. // ToDo: remove till NK fixes the bug in IP transmit
  365. // with header inc
  366. //
  367. // RtAssert(uiFirstBufLen >= sizeof(IP_HEADER));
  368. #if L2TP_DBG
  369. #define L2TP_PORT_NBO 0xA506 // 1701 == 06A5
  370. //
  371. // If this is a l2tp packet, break
  372. //
  373. if(pIpHeader->byProtocol is 17)
  374. {
  375. WORD UNALIGNED *pwPort;
  376. //
  377. // See if we have enough data to get to the UDP header in
  378. // the first buffer
  379. //
  380. uiIpHdrLen = LengthOfIpHeader(pIpHeader);
  381. if(uiFirstBufLen >= uiIpHdrLen + sizeof(ULONG))
  382. {
  383. pwPort = (WORD UNALIGNED *)((ULONG_PTR)pIpHeader + uiIpHdrLen);
  384. }
  385. else
  386. {
  387. PNDIS_BUFFER pNextBuf;
  388. //
  389. // Get the next buffer and look into its
  390. //
  391. pNextBuf = pnbTempBuffer->Next;
  392. pwPort = (WORD UNALIGNED *)(pnbTempBuffer->MappedSystemVa);
  393. }
  394. if((pwPort[0] is L2TP_PORT_NBO) or
  395. (pwPort[1] is L2TP_PORT_NBO))
  396. {
  397. Trace(SEND, ERROR,
  398. ("SendPackets: %x buffer %x header %x port %d.%d\n",
  399. pnbTempBuffer, pIpHeader, pwPort,
  400. pwPort[0], pwPort[1]));
  401. RtAssert(FALSE);
  402. }
  403. }
  404. #endif
  405. //
  406. // NOTE: If this is a client send, the server interface is not
  407. // locked. Hence the stats can be inconsistent for the server
  408. // interface
  409. //
  410. if(IsUnicastAddr(pIpHeader->dwDest))
  411. {
  412. pInterface->ulOutUniPkts++;
  413. }
  414. else
  415. {
  416. pInterface->ulOutNonUniPkts++;
  417. }
  418. pleNode = RemoveHeadList(pleBufferList);
  419. #if LIST_DBG
  420. pBufferHead = CONTAINING_RECORD(pleNode,
  421. BUFFER_HEAD,
  422. leListLink);
  423. RtAssert(IsListEmpty(&(pBufferHead->leFreeBufferLink)));
  424. RtAssert(pBufferHead->bBusy);
  425. pBufferHead->leListLink.Flink = NULL;
  426. pBufferHead->leListLink.Blink = NULL;
  427. #else
  428. pBufferHead = CONTAINING_RECORD(pleNode,
  429. BUFFER_HEAD,
  430. leFreeBufferLink);
  431. #endif
  432. //
  433. // Get a pointer to the data and to the buffer
  434. //
  435. pbyHeader = BUFFER_FROM_HEAD(pBufferHead);
  436. pnbBuffer = pBufferHead->pNdisBuffer;
  437. //
  438. // Copy our prebuilt header into each buffer
  439. //
  440. RtlCopyMemory(pbyHeader,
  441. &(pConnEntry->ehHeader),
  442. sizeof(ETH_HEADER));
  443. //
  444. // Put the ethernet header in the front of the packet
  445. //
  446. NdisChainBufferAtFront(ppPacketArray[i],
  447. pnbBuffer);
  448. //
  449. // Reference the entry once for each packet
  450. //
  451. ReferenceConnEntry(pConnEntry);
  452. #if PKT_DBG
  453. Trace(SEND, ERROR,
  454. ("SendPackets: Pkt %x Eth buff %x (%x) Header %x (%x)\n",
  455. ppPacketArray[1],
  456. pnbBuffer,
  457. pbyHeader,
  458. pnbTempBuffer,
  459. pvFirstBuffer));
  460. #endif // PKT_DBG
  461. }
  462. //
  463. // Increment the output queue length. This will be decremented
  464. // in the send complete handler
  465. //
  466. pAdapter->ulQueueLen++;
  467. //
  468. // Let go of the locks
  469. //
  470. if(pConnEntry->duUsage isnot DU_CALLIN)
  471. {
  472. RtReleaseSpinLockFromDpcLevel(&(pInterface->rlLock));
  473. }
  474. RtReleaseSpinLock(pConnEntry->prlLock,
  475. kiIrql);
  476. NdisSendPackets(g_nhNdiswanBinding,
  477. ppPacketArray,
  478. uiNumPackets);
  479. //
  480. // Dont dereference the connection entry. We will deref it in
  481. // the send complete handler
  482. //
  483. return NDIS_STATUS_PENDING;
  484. }
  485. VOID
  486. WanNdisSendComplete(
  487. NDIS_HANDLE nhHandle,
  488. PNDIS_PACKET pnpPacket,
  489. NDIS_STATUS nsStatus
  490. )
  491. /*++
  492. Routine Description:
  493. Our send complete handler called by NDIS once for each packet that was
  494. pending after a send.
  495. Locks:
  496. Arguments:
  497. Return Value:
  498. --*/
  499. {
  500. PacketContext *pPC;
  501. PNDIS_BUFFER pnbBuffer, pnbEthBuffer;
  502. KIRQL kiIrql;
  503. PADAPTER pAdapter;
  504. PUMODE_INTERFACE pInterface;
  505. PCONN_ENTRY pConnEntry;
  506. PETH_HEADER pEthHeader;
  507. ULONG ulIndex;
  508. PVOID pvFirstBuffer;
  509. UINT uiFirstBufLen, uiTotalLen;
  510. TraceEnter(SEND, "NdisSendComplete");
  511. //
  512. // Get first buffer on packet. This is our ethernet header buffer
  513. //
  514. NdisUnchainBufferAtFront(pnpPacket,
  515. &pnbEthBuffer);
  516. //
  517. // Get the fake ethernet header
  518. //
  519. pEthHeader = NdisBufferVirtualAddress(pnbEthBuffer);
  520. #if DBG
  521. //
  522. // The buffer head should say the same thing
  523. //
  524. RtAssert(pnbEthBuffer is ((HEAD_FROM_BUFFER(pEthHeader))->pNdisBuffer));
  525. #endif
  526. ulIndex = GetConnIndexFromAddr(pEthHeader->rgbySourceAddr);
  527. //
  528. // Done with our buffer
  529. //
  530. FreeBufferToPool(&g_bpHeaderBufferPool,
  531. (PBYTE)pEthHeader);
  532. //
  533. // Get the connection entry
  534. //
  535. RtAcquireSpinLock(&g_rlConnTableLock,
  536. &kiIrql);
  537. pConnEntry = GetConnEntryGivenIndex(ulIndex);
  538. if(pConnEntry is NULL)
  539. {
  540. RtAssert(FALSE);
  541. RtReleaseSpinLock(&g_rlConnTableLock,
  542. kiIrql);
  543. Trace(SEND, ERROR,
  544. ("NdisSendComplete: Couldnt find entry for connection %d\n",
  545. ulIndex));
  546. TraceLeave(RCV, "NdisSendComplete");
  547. return;
  548. }
  549. RtAcquireSpinLockAtDpcLevel(pConnEntry->prlLock);
  550. RtReleaseSpinLockFromDpcLevel(&g_rlConnTableLock);
  551. pAdapter = pConnEntry->pAdapter;
  552. #if DBG
  553. Trace(SEND, INFO,
  554. ("NdisSendComplete: Extracted adapter %x with name %s\n",
  555. pAdapter,
  556. pAdapter->asDeviceNameA.Buffer));
  557. #endif
  558. pAdapter->ulQueueLen--;
  559. if(pConnEntry->duUsage is DU_CALLIN)
  560. {
  561. pInterface = g_pServerInterface;
  562. RtAssert(pAdapter is g_pServerAdapter);
  563. }
  564. else
  565. {
  566. //
  567. // See if we are still mapped to an interface, if so lock it
  568. //
  569. pInterface = pAdapter->pInterface;
  570. if(pInterface isnot NULL)
  571. {
  572. RtAcquireSpinLockAtDpcLevel(&(pInterface->rlLock));
  573. }
  574. }
  575. //
  576. // Right now we have the adapter + interface or the connection entry
  577. // locked.
  578. //
  579. if(nsStatus is NDIS_STATUS_SUCCESS)
  580. {
  581. NdisGetFirstBufferFromPacket(pnpPacket,
  582. &pnbBuffer,
  583. &pvFirstBuffer,
  584. &uiFirstBufLen,
  585. &uiTotalLen);
  586. if(pInterface)
  587. {
  588. pInterface->ulOutOctets += uiTotalLen;
  589. }
  590. #if PKT_DBG
  591. Trace(SEND, ERROR,
  592. ("NdisSendComplete: Pkt %x Eth buff %x (%x) Header %x (%x)\n",
  593. pnpPacket,
  594. pnbEthBuffer,
  595. pEthHeader,
  596. pnbBuffer,
  597. pvFirstBuffer));
  598. #endif PKT_DBG
  599. }
  600. else
  601. {
  602. Trace(SEND, INFO,
  603. ("NdisSendComplete: Failed %x\n",
  604. nsStatus));
  605. if(pInterface)
  606. {
  607. pInterface->ulOutDiscards++;
  608. }
  609. }
  610. //
  611. // If this is not our packet return it to the protocol
  612. //
  613. pPC = (PacketContext *)pnpPacket->ProtocolReserved;
  614. //
  615. // Unlock
  616. //
  617. if(pConnEntry->duUsage isnot DU_CALLIN)
  618. {
  619. if(pInterface isnot NULL)
  620. {
  621. RtReleaseSpinLockFromDpcLevel(&(pInterface->rlLock));
  622. }
  623. }
  624. RtReleaseSpinLock(pConnEntry->prlLock,
  625. kiIrql);
  626. if(pPC->pc_common.pc_owner isnot PACKET_OWNER_LINK)
  627. {
  628. Trace(SEND, TRACE,
  629. ("NdisSendComplete: Calling IPSendComplete for %p over %p(%p)\n",
  630. pnpPacket,
  631. pAdapter,
  632. pAdapter->pvIpContext));
  633. g_pfnIpSendComplete(pAdapter->pvIpContext,
  634. pnpPacket,
  635. nsStatus);
  636. }
  637. else
  638. {
  639. //
  640. // Free all buffers from our packet and then the packet itself
  641. //
  642. Trace(SEND, TRACE,
  643. ("NdisSendComplete: Not calling IPSendComplete for %p\n",
  644. pnpPacket));
  645. WanpFreePacketAndBuffers(pnpPacket);
  646. }
  647. //
  648. // Deref the conn entry for the send and for the fact that
  649. // GetConnEntry.. put a ref on it
  650. //
  651. DereferenceConnEntry(pConnEntry);
  652. DereferenceConnEntry(pConnEntry);
  653. return;
  654. }
  655. VOID
  656. WanpTransmitQueuedPackets(
  657. IN PADAPTER pAdapter,
  658. IN PUMODE_INTERFACE pInterface,
  659. IN PCONN_ENTRY pConnEntry,
  660. IN KIRQL kiIrql
  661. )
  662. {
  663. ULONG i;
  664. PNDIS_PACKET rgPacketArray[64];
  665. NDIS_PACKET **ppPacketArray;
  666. LIST_ENTRY leBufferList, *pleNode;
  667. //
  668. // This is only called for ROUTER interfaces
  669. //
  670. RtAssert(pConnEntry->duUsage is DU_ROUTER);
  671. RtAssert(pInterface->duUsage is DU_ROUTER);
  672. //
  673. // If there are no packets to transmit, just release the
  674. // locks
  675. //
  676. if(pInterface->ulPacketsPending is 0)
  677. {
  678. RtAssert(IsListEmpty(&(pAdapter->lePendingPktList)));
  679. RtAssert(IsListEmpty(&(pAdapter->lePendingHdrList)));
  680. RtReleaseSpinLockFromDpcLevel(&(pInterface->rlLock));
  681. RtReleaseSpinLock(&(pAdapter->rlLock),
  682. kiIrql);
  683. return;
  684. }
  685. if(pInterface->ulPacketsPending <= 64)
  686. {
  687. //
  688. // Just use the stack array
  689. //
  690. ppPacketArray = rgPacketArray;
  691. }
  692. else
  693. {
  694. //
  695. // Allocate a packet array
  696. //
  697. ppPacketArray =
  698. RtAllocate(NonPagedPool,
  699. sizeof(PNDIS_PACKET) * pInterface->ulPacketsPending,
  700. WAN_CONN_TAG);
  701. if(ppPacketArray is NULL)
  702. {
  703. Trace(SEND, ERROR,
  704. ("TransmitQueuedPackets: Unable to allocate %d pointers\n",
  705. pInterface->ulPacketsPending));
  706. while(!IsListEmpty(&(pAdapter->lePendingPktList)))
  707. {
  708. PNDIS_PACKET pnpPacket;
  709. pleNode = RemoveHeadList(&(pAdapter->lePendingPktList));
  710. //
  711. // get to the packet structure in which LIST_ENTRY is embedded
  712. //
  713. pnpPacket = CONTAINING_RECORD(pleNode,
  714. NDIS_PACKET,
  715. MacReserved);
  716. WanpFreePacketAndBuffers(pnpPacket);
  717. }
  718. while(!IsListEmpty(&(pAdapter->lePendingHdrList)))
  719. {
  720. PBYTE pbyHeader;
  721. PBUFFER_HEAD pBuffHead;
  722. pleNode = RemoveHeadList(&(pAdapter->lePendingHdrList));
  723. #if LIST_DBG
  724. pBuffHead = CONTAINING_RECORD(pleNode,
  725. BUFFER_HEAD,
  726. leListLink);
  727. RtAssert(IsListEmpty(&(pBuffHead->leFreeBufferLink)));
  728. RtAssert(pBuffHead->bBusy);
  729. pBuffHead->leListLink.Flink = NULL;
  730. pBuffHead->leListLink.Blink = NULL;
  731. #else
  732. pBuffHead = CONTAINING_RECORD(pleNode,
  733. BUFFER_HEAD,
  734. leFreeBufferLink);
  735. #endif
  736. pbyHeader = BUFFER_FROM_HEAD(pBuffHead);
  737. FreeBufferToPool(&g_bpHeaderBufferPool,
  738. pbyHeader);
  739. }
  740. }
  741. }
  742. for(i = 0, pleNode = pAdapter->lePendingPktList.Flink;
  743. pleNode isnot &(pAdapter->lePendingPktList);
  744. pleNode = pleNode->Flink, i++)
  745. {
  746. PNDIS_PACKET pnpPacket;
  747. pnpPacket = CONTAINING_RECORD(pleNode,
  748. NDIS_PACKET,
  749. MacReserved);
  750. ppPacketArray[i] = pnpPacket;
  751. }
  752. RtAssert(i is pInterface->ulPacketsPending);
  753. #if DBG
  754. for(i = 0, pleNode = pAdapter->lePendingHdrList.Flink;
  755. pleNode isnot &(pAdapter->lePendingHdrList);
  756. pleNode = pleNode->Flink, i++);
  757. RtAssert(i is pInterface->ulPacketsPending);
  758. #endif
  759. //
  760. // copy out the pending hdr list to leBufferList.
  761. //
  762. leBufferList = pAdapter->lePendingHdrList;
  763. pAdapter->lePendingHdrList.Flink->Blink = &leBufferList;
  764. pAdapter->lePendingHdrList.Blink->Flink = &leBufferList;
  765. pInterface->ulPacketsPending = 0;
  766. InitializeListHead(&(pAdapter->lePendingPktList));
  767. InitializeListHead(&(pAdapter->lePendingHdrList));
  768. WanpSendPackets(pAdapter,
  769. pInterface,
  770. pConnEntry,
  771. ppPacketArray,
  772. &leBufferList,
  773. pInterface->ulPacketsPending,
  774. kiIrql);
  775. if(rgPacketArray isnot ppPacketArray)
  776. {
  777. RtFree(ppPacketArray);
  778. }
  779. }
  780. NDIS_STATUS
  781. WanpCopyAndQueuePackets(
  782. PADAPTER pAdapter,
  783. NDIS_PACKET **ppPacketArray,
  784. PLIST_ENTRY pleBufferList,
  785. UINT uiNumPackets
  786. )
  787. /*++
  788. Routine Description:
  789. This routine queues the packet to the adapter
  790. Once this routine is called, the caller can not touch the pleListHead
  791. Locks:
  792. The ADAPTER must be locked and mapped
  793. The interface the adapter is mapped to must also be locked
  794. Arguments:
  795. pAdapter
  796. ppPacketArray
  797. pBuffHead
  798. uiNumPackets
  799. Return Value:
  800. NDIS_STATUS_SUCCESS
  801. STATUS_QUOTA_EXCEEDED
  802. NDIS_STATUS_RESOURCES
  803. --*/
  804. {
  805. PacketContext *pPC;
  806. NDIS_STATUS nsStatus;
  807. PLIST_ENTRY pleNode;
  808. ULONG i;
  809. #if DBG
  810. ULONG ulPended = 0, ulHdrs = 0;
  811. #endif
  812. TraceEnter(SEND, "CopyAndQueuePackets");
  813. if(pAdapter->pInterface->ulPacketsPending >= WANARP_MAX_PENDING_PACKETS)
  814. {
  815. Trace(SEND, WARN,
  816. ("CopyAndQueuePackets: Dropping packets since cap exceeded\n"));
  817. return STATUS_QUOTA_EXCEEDED;
  818. }
  819. for(i = 0; i < uiNumPackets; i++)
  820. {
  821. PNDIS_PACKET pnpPacket;
  822. UINT uiTotalLen, uiBytesCopied;
  823. //
  824. // Get size of buffers required
  825. //
  826. NdisQueryPacket(ppPacketArray[i],
  827. NULL,
  828. NULL,
  829. NULL,
  830. &uiTotalLen);
  831. //
  832. // Allocate a packet.
  833. //
  834. pnpPacket = NULL;
  835. NdisAllocatePacket(&nsStatus,
  836. &pnpPacket,
  837. g_nhPacketPool);
  838. if(nsStatus isnot NDIS_STATUS_SUCCESS)
  839. {
  840. Trace(SEND, ERROR,
  841. ("CopyAndQueuePackets: Cant allocate packet. %x\n",
  842. nsStatus));
  843. }
  844. else
  845. {
  846. //
  847. // Allocate buffers for the packet
  848. //
  849. nsStatus = GetBufferChainFromPool(&g_bpDataBufferPool,
  850. pnpPacket,
  851. uiTotalLen,
  852. NULL,
  853. NULL);
  854. }
  855. if(nsStatus is STATUS_SUCCESS)
  856. {
  857. //
  858. // If we got a packet and the buffers, then copy from TCP/IP's
  859. // packet into ours
  860. //
  861. NdisCopyFromPacketToPacket(pnpPacket,
  862. 0,
  863. uiTotalLen,
  864. ppPacketArray[i],
  865. 0,
  866. &uiBytesCopied);
  867. RtAssert(uiBytesCopied is uiTotalLen);
  868. //
  869. // This is now our packet, so set its context
  870. //
  871. pPC = (PacketContext *)pnpPacket->ProtocolReserved;
  872. pPC->pc_common.pc_owner = PACKET_OWNER_LINK;
  873. //
  874. // Attach Packet to pending packet list
  875. // We use the MacReserved portion as the list entry
  876. //
  877. InsertTailList(&pAdapter->lePendingPktList,
  878. (PLIST_ENTRY)&(pnpPacket->MacReserved));
  879. pAdapter->pInterface->ulPacketsPending++;
  880. #if DBG
  881. ulPended++;
  882. #endif
  883. }
  884. else
  885. {
  886. PBUFFER_HEAD pBufferHead;
  887. PBYTE pbyHeader;
  888. //
  889. // We either have no packet, or couldnt get a buffer.
  890. // Nasty Nasty: Side effect of such a failure is that we free
  891. // one of the header buffers
  892. //
  893. RtAssert(!IsListEmpty(pleBufferList));
  894. pleNode = RemoveHeadList(pleBufferList);
  895. #if LIST_DBG
  896. pBufferHead = CONTAINING_RECORD(pleNode,
  897. BUFFER_HEAD,
  898. leListLink);
  899. RtAssert(IsListEmpty(&(pBufferHead->leFreeBufferLink)));
  900. RtAssert(pBufferHead->bBusy);
  901. pBufferHead->leListLink.Flink = NULL;
  902. pBufferHead->leListLink.Blink = NULL;
  903. #else
  904. pBufferHead = CONTAINING_RECORD(pleNode,
  905. BUFFER_HEAD,
  906. leFreeBufferLink);
  907. #endif
  908. //
  909. // Get a pointer to the data and to the buffer
  910. //
  911. pbyHeader = BUFFER_FROM_HEAD(pBufferHead);
  912. FreeBufferToPool(&g_bpHeaderBufferPool,
  913. pbyHeader);
  914. if(pnpPacket)
  915. {
  916. NdisFreePacket(pnpPacket);
  917. }
  918. }
  919. }
  920. //
  921. // we have queued all the packets we could, and for the ones we
  922. // failed, we freed the corresponding ethernet header.
  923. // So the number of headers left on pleBufferList should be the number of
  924. // packets queued
  925. //
  926. if(!IsListEmpty(pleBufferList))
  927. {
  928. #if DBG
  929. for(pleNode = pleBufferList->Flink;
  930. pleNode isnot pleBufferList;
  931. pleNode = pleNode->Flink)
  932. {
  933. ulHdrs++;
  934. }
  935. #endif
  936. //
  937. // Add the headers to the front of the adapter chain
  938. //
  939. pleBufferList->Blink->Flink = pAdapter->lePendingHdrList.Flink;
  940. pleBufferList->Flink->Blink = &(pAdapter->lePendingHdrList);
  941. pAdapter->lePendingHdrList.Flink->Blink = pleBufferList->Blink;
  942. pAdapter->lePendingHdrList.Flink = pleBufferList->Flink;
  943. }
  944. #if DBG
  945. RtAssert(ulPended is ulHdrs);
  946. #endif
  947. return NDIS_STATUS_SUCCESS;
  948. }
  949. VOID
  950. WanpFreePacketAndBuffers(
  951. PNDIS_PACKET pnpPacket
  952. )
  953. {
  954. PNDIS_BUFFER pnbFirstBuffer;
  955. FreeBufferChainToPool(&g_bpDataBufferPool,
  956. pnpPacket);
  957. NdisFreePacket(pnpPacket);
  958. }
  959. VOID
  960. WanIpInvalidateRce(
  961. PVOID pvContext,
  962. RouteCacheEntry *pRce
  963. )
  964. {
  965. return;
  966. }