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.

1308 lines
31 KiB

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