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.

5130 lines
142 KiB

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. ip.c
  5. Abstract:
  6. ARP1394 IP-related handlers.
  7. Revision History:
  8. Who When What
  9. -------- -------- ----------------------------------------------
  10. josephj 01-06-98 Created (adapted from atmarpc.sys, arpif.c)
  11. Notes:
  12. --*/
  13. #include <precomp.h>
  14. //
  15. // File-specific debugging defaults.
  16. //
  17. #define TM_CURRENT TM_IP
  18. #define CLASSA_MASK 0x000000ff
  19. #define CLASSB_MASK 0x0000ffff
  20. #define CLASSC_MASK 0x00ffffff
  21. #define CLASSD_MASK 0x000000e0
  22. #define CLASSE_MASK 0xffffffff
  23. //=========================================================================
  24. // L O C A L P R O T O T Y P E S
  25. //=========================================================================
  26. ULONG ArpSendCompletes = 0;
  27. ULONG ArpSends = 0;
  28. ULONG ArpSendFailure = 0;
  29. #define LOGSTATS_SendFifoCounts(_pIF, _pNdisPacket, _Status) \
  30. arpLogSendFifoCounts(_pIF, _pNdisPacket, _Status)
  31. #define LOGSTATS_SendChannelCounts(_pIF, _pNdisPacket, _Status) \
  32. arpLogSendChannelCounts(_pIF, _pNdisPacket, _Status)
  33. #define LOGSTATS_TotalArpCacheLookups(_pIF, _Status) \
  34. NdisInterlockedIncrement(&((_pIF)->stats.arpcache.TotalLookups))
  35. const
  36. NIC1394_ENCAPSULATION_HEADER
  37. Arp1394_IpEncapHeader =
  38. {
  39. 0x0000, // Reserved
  40. H2N_USHORT(NIC1394_ETHERTYPE_IP)
  41. };
  42. //
  43. // ZZZ This is a little-endian specific check.
  44. //
  45. #define ETH_IS_MULTICAST(Address) \
  46. (BOOLEAN)(((PUCHAR)(Address))[0] & ((UCHAR)0x01))
  47. //
  48. // Check whether an address is broadcast.
  49. //
  50. #define ETH_IS_BROADCAST(Address) \
  51. ((((PUCHAR)(Address))[0] == ((UCHAR)0xff)) && (((PUCHAR)(Address))[1] == ((UCHAR)0xff)))
  52. VOID
  53. arpReStartInterface(
  54. IN PNDIS_WORK_ITEM pWorkItem,
  55. IN PVOID IfContext
  56. );
  57. VOID
  58. arpInitializeLocalIp(
  59. IN ARPCB_LOCAL_IP * pLocalIp, // LOCKIN NOLOCKOUT
  60. IN UINT AddressType,
  61. IN IP_ADDRESS IpAddress,
  62. IN IP_MASK Mask,
  63. IN PRM_STACK_RECORD pSR
  64. );
  65. VOID
  66. arpUnloadLocalIp(
  67. IN ARPCB_LOCAL_IP * pLocalIp, // LOCKIN NOLOCKOUT
  68. IN PRM_STACK_RECORD pSR
  69. );
  70. INT
  71. arpQueryIpEntityId(
  72. ARP1394_INTERFACE * pIF,
  73. IN UINT EntityType,
  74. IN PNDIS_BUFFER pNdisBuffer,
  75. IN OUT PUINT pBufferSize,
  76. PRM_STACK_RECORD pSR
  77. );
  78. VOID
  79. nicGetMacAddressFromEuid (
  80. UINT64 *pEuid,
  81. ENetAddr *pMacAddr
  82. );
  83. INT
  84. arpQueryIpAddrXlatInfo(
  85. ARP1394_INTERFACE * pIF,
  86. IN PNDIS_BUFFER pNdisBuffer,
  87. IN OUT PUINT pBufferSize,
  88. PRM_STACK_RECORD pSR
  89. );
  90. INT
  91. arpQueryIpAddrXlatEntries(
  92. ARP1394_INTERFACE * pIF,
  93. IN PNDIS_BUFFER pNdisBuffer,
  94. IN OUT PUINT pBufferSize,
  95. IN PVOID QueryContext,
  96. PRM_STACK_RECORD pSR
  97. );
  98. INT
  99. arpQueryIpMibStats(
  100. ARP1394_INTERFACE * pIF,
  101. IN PNDIS_BUFFER pNdisBuffer,
  102. IN OUT PUINT pBufferSize,
  103. PRM_STACK_RECORD pSR
  104. );
  105. PNDIS_BUFFER
  106. arpCopyToNdisBuffer(
  107. IN PNDIS_BUFFER pDestBuffer,
  108. IN PUCHAR pDataSrc,
  109. IN UINT LenToCopy,
  110. IN OUT PUINT pOffsetInBuffer
  111. );
  112. VOID
  113. arpSendIpPkt(
  114. IN ARP1394_INTERFACE * pIF, // LOCKIN NOLOCKOUT (IF send lk)
  115. IN PARPCB_DEST pDest,
  116. IN PNDIS_PACKET pNdisPacket
  117. );
  118. VOID
  119. arpAddRce(
  120. IN ARPCB_REMOTE_IP *pRemoteIp,
  121. IN RouteCacheEntry *pRCE,
  122. IN PRM_STACK_RECORD pSR
  123. );
  124. VOID
  125. arpDelRce(
  126. IN RouteCacheEntry *pRce, // IF send lock WRITELOCKIN WRITELOCKOUTD
  127. IN PRM_STACK_RECORD pSR
  128. );
  129. NDIS_STATUS
  130. arpTaskSendPktsOnRemoteIp(
  131. IN struct _RM_TASK * pTask,
  132. IN RM_TASK_OPERATION Code,
  133. IN UINT_PTR UserParam, // Unused
  134. IN PRM_STACK_RECORD pSR
  135. );
  136. VOID
  137. arpTryResumeSuspendedCleanupTask(
  138. IN ARP1394_INTERFACE * pIF,
  139. IN ARPCB_DEST * pDest
  140. );
  141. VOID
  142. arpQueuePktOnRemoteIp(
  143. IN ARPCB_REMOTE_IP * pRemoteIp, // LOCKIN LOCKOUT
  144. IN PNDIS_PACKET pNdisPacket,
  145. IN PRM_STACK_RECORD pSR
  146. );
  147. VOID
  148. arpSendPktsQueuedOnRemoteIp(
  149. IN ARP1394_INTERFACE * pIF, // NOLOCKIN NOLOCKOUT
  150. IN ARPCB_REMOTE_IP * pRemoteIp, // NOLOCKIN NOLOCKOUT
  151. IN PRM_STACK_RECORD pSR
  152. );
  153. MYBOOL
  154. arpIsNonUnicastIpAddress(
  155. IN PARP1394_INTERFACE pIF, // LOCKIN LOCKOUT
  156. IN IP_ADDRESS Addr,
  157. IN PRM_STACK_RECORD pSR
  158. );
  159. MYBOOL
  160. arpIsNonUnicastEthAddress (
  161. IN PARP1394_INTERFACE pIF, // LOCKIN LOCKOUT
  162. IN ENetAddr* pAddr,
  163. IN PRM_STACK_RECORD pSR
  164. );
  165. VOID
  166. arpLoopbackNdisPacket(
  167. IN PARP1394_INTERFACE pIF,
  168. IN PARPCB_DEST pBroadcastDest,
  169. IN PNDIS_PACKET pOldPacket
  170. );
  171. //=========================================================================
  172. // I P H A N D L E R S
  173. //=========================================================================
  174. INT
  175. ArpIpDynRegister(
  176. IN PNDIS_STRING pAdapterString,
  177. IN PVOID IpContext,
  178. IN struct _IP_HANDLERS * pIpHandlers,
  179. IN struct LLIPBindInfo * pBindInfo,
  180. IN UINT InterfaceNumber
  181. )
  182. /*++
  183. Routine Description:
  184. This routine is called from the IP layer when it wants to tell us,
  185. the ARP module, about its handlers for an Interface.
  186. Arguments:
  187. pAdapterString - Name of the logical adapter for this interface
  188. IpContext - IP's context for this interface
  189. pIpHandlers - Points to struct containing the IP handlers
  190. pBindInfo - Pointer to bind info with our information
  191. InterfaceNumber - ID for this interface
  192. Return Value:
  193. TRUE always.
  194. --*/
  195. {
  196. ENTER("IfDynRegister", 0xc1b569b9)
  197. ARP1394_INTERFACE* pIF;
  198. RM_DECLARE_STACK_RECORD(sr)
  199. pIF = (ARP1394_INTERFACE*)(pBindInfo->lip_context);
  200. TR_INFO(("pIF 0x%p\n", pIF));
  201. ASSERT(pIF->Hdr.Sig == MTAG_INTERFACE);
  202. LOCKOBJ(pIF, &sr);
  203. //
  204. // TODO: fail if we're not in a position to do this -- such as when shutting
  205. // down.
  206. //
  207. pIF->ip.Context = IpContext;
  208. pIF->ip.RcvHandler = pIpHandlers->IpRcvHandler;
  209. pIF->ip.TxCmpltHandler = pIpHandlers->IpTxCompleteHandler;
  210. pIF->ip.StatusHandler = pIpHandlers->IpStatusHandler;
  211. pIF->ip.TDCmpltHandler = pIpHandlers->IpTransferCompleteHandler;
  212. pIF->ip.RcvCmpltHandler = pIpHandlers->IpRcvCompleteHandler;
  213. pIF->ip.PnPEventHandler = pIpHandlers->IpPnPHandler;
  214. pIF->ip.RcvPktHandler = pIpHandlers->IpRcvPktHandler;
  215. pIF->ip.IFIndex = InterfaceNumber;
  216. UNLOCKOBJ(pIF, &sr);
  217. //
  218. RM_ASSERT_CLEAR(&sr);
  219. EXIT()
  220. return TRUE;
  221. }
  222. VOID
  223. ArpIpOpen(
  224. IN PVOID Context
  225. )
  226. /*++
  227. Routine Description:
  228. This routine is called when IP is ready to use this interface.
  229. Arguments:
  230. Context - Actually a pointer to our ARP394_INTERFACE structure
  231. --*/
  232. {
  233. ARP1394_INTERFACE* pIF;
  234. ENTER("ArpIpOpen", 0x7cae1e55)
  235. RM_DECLARE_STACK_RECORD(sr)
  236. TR_INFO(("Enter. pContext = 0x%p\n", Context));
  237. pIF = (ARP1394_INTERFACE*) Context;
  238. // Validate context.
  239. //
  240. ASSERT(pIF->Hdr.Sig == MTAG_INTERFACE);
  241. LOCKOBJ(pIF, &sr);
  242. // Get the local HW address if we don't have it yet
  243. //
  244. {
  245. // TODO (this is from ip/atm -- I think in our case we can assume we have
  246. // it?)
  247. }
  248. // Mark interface as open.
  249. //
  250. {
  251. ASSERT(CHECK_IF_IP_STATE(pIF, ARPIF_IPS_CLOSED));
  252. SET_IF_IP_STATE(pIF, ARPIF_IPS_OPEN);
  253. pIF->stats.LastChangeTime = GetTimeTicks();
  254. }
  255. #if ARP_WMI
  256. //
  257. // Register interface with WMI
  258. //
  259. // TODO
  260. #endif // ARP_WMI
  261. // Record the fact that we're open, to verify that the IF is closed before
  262. // the IF block is deallocated.
  263. //
  264. DBG_ADDASSOC(&pIF->Hdr, NULL, NULL, ARPASSOC_IP_OPEN, " IP IF Open\n", &sr);
  265. UNLOCKOBJ(pIF, &sr);
  266. RM_ASSERT_CLEAR(&sr);
  267. EXIT()
  268. }
  269. VOID
  270. ArpIpClose(
  271. IN PVOID Context
  272. )
  273. /*++
  274. Routine Description:
  275. IP wants to stop using this Interface.
  276. Arguments:
  277. Context - Actually a pointer to our ARP1394_INTERFACE structure
  278. --*/
  279. {
  280. ARP1394_INTERFACE * pIF = (ARP1394_INTERFACE*) Context;
  281. PRM_TASK pTask;
  282. BOOLEAN fResumeTask = FALSE;
  283. ENTER("ArpIpClose", 0xdb8c8216)
  284. RM_DECLARE_STACK_RECORD(sr)
  285. TR_INFO(("Enter. pContext = 0x%p\n", Context));
  286. ASSERT(pIF->Hdr.Sig == MTAG_INTERFACE);
  287. LOCKOBJ(pIF, &sr);
  288. //
  289. //Set state to closed.
  290. //
  291. SET_IF_IP_STATE(pIF, ARPIF_IPS_CLOSED);
  292. pIF->stats.LastChangeTime= GetTimeTicks();
  293. // (delete "ARPASSOC_IP_OPEN" association added in arpIpOpen)
  294. //
  295. DBG_DELASSOC(&pIF->Hdr, NULL, NULL, ARPASSOC_IP_OPEN, &sr);
  296. // If there is a shutdown task pending, we notify it
  297. // Note: a task is protected by it's parent object's lock, which is
  298. // pIF in the case of the init and shutdown-interface tasks.
  299. //
  300. pTask = pIF->pActDeactTask;
  301. if (pTask && pTask->pfnHandler == arpTaskDeactivateInterface)
  302. {
  303. TASK_DEACTIVATE_IF *pShutdownTask =
  304. (TASK_DEACTIVATE_IF *) pTask;
  305. if (pShutdownTask->fPendingOnIpClose)
  306. {
  307. ASSERT(pIF->ip.Context == NULL);
  308. RmTmpReferenceObject(&pTask->Hdr, &sr);
  309. fResumeTask = TRUE;
  310. }
  311. else
  312. {
  313. // Hmm... unsolicited IpClose. We don't expect this currently.
  314. //
  315. ASSERT(FALSE);
  316. pIF->ip.Context = NULL;
  317. }
  318. }
  319. UNLOCKOBJ(pIF, &sr);
  320. if (fResumeTask)
  321. {
  322. RmResumeTask(pTask, (UINT_PTR) 0, &sr);
  323. RmTmpDereferenceObject(&pTask->Hdr, &sr);
  324. }
  325. RM_ASSERT_CLEAR(&sr);
  326. EXIT()
  327. }
  328. UINT
  329. ArpIpAddAddress(
  330. IN PVOID Context,
  331. IN UINT AddressType,
  332. IN IP_ADDRESS IpAddress,
  333. IN IP_MASK Mask,
  334. IN PVOID Context2
  335. )
  336. /*++
  337. Routine Description:
  338. The IP layer calls this when a new IP address (or block of IP addresses,
  339. as determined by AddressType) needs to be added to an Interface.
  340. We could see any of four address types: Local, Multicast, Broadcast
  341. and Proxy ARP. In the case of Proxy ARP, the address along with the mask
  342. can specify a block of contiguous IP addresses for which this host acts
  343. as a proxy. Currently, we only support the "Local", "Broadcast", and
  344. "Multicast" types.
  345. Arguments:
  346. Context - Actually a pointer to our structure
  347. AddressType - Type of address(es) being added.
  348. IpAddress - Address to be added.
  349. Mask - For the above.
  350. Context2 - Additional context (We ignore this)
  351. Return Value:
  352. TRUE if successful, FALSE otherwise.
  353. --*/
  354. {
  355. ARP1394_INTERFACE * pIF = (ARP1394_INTERFACE*) Context;
  356. ENTER("ArpIpAddAddress", 0xd6630961)
  357. INT fCreated = FALSE;
  358. ARPCB_LOCAL_IP *pLocalIp = NULL;
  359. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  360. RM_DECLARE_STACK_RECORD(sr)
  361. TR_INFO(("Enter. pIF = 0x%p\n", pIF));
  362. ASSERT(pIF->Hdr.Sig == MTAG_INTERFACE);
  363. #if OBSOLETE // Instead, we grab IF lock and don't specify the RM_LOCK flag.
  364. // See notes.txt entry "03/05/1999 More corny locking problems"
  365. //
  366. // WARNING: We SHOULD NOT grab the IF lock, because we request that
  367. // the pLocalIp's lock be grabbed in RmLookupObjectInGroup below,
  368. // AND the pLocalIp's lock is actually the same as the IF lock.
  369. // (This is asserted later on below).
  370. // So obviously we can't get the IF lock here! (And we don't need to either).
  371. //
  372. #endif
  373. LOCKOBJ(pIF, &sr);
  374. // We're not yet in the open state -- we're "opening", so we don't assert...
  375. // ASSERT(!CHECK_IF_OPEN_STATE(pIF, ARPIF_CLOSED));
  376. do
  377. {
  378. //
  379. // Note: we could just as well have done the initialiation as part of
  380. // the creation of the LocalIpObject itself, by passing in all the
  381. // required initialization params in the pvCreateParams arg to
  382. // RmLookupObjectInGroup. Instead we choose to do the initialization
  383. // ourselves. Things are more explicit this way.
  384. //
  385. // Unfortunately, to do this we must first validate the args...
  386. //
  387. if (AddressType != LLIP_ADDR_BCAST &&
  388. AddressType != LLIP_ADDR_MCAST &&
  389. AddressType != LLIP_ADDR_LOCAL)
  390. {
  391. break;
  392. }
  393. Status = RmLookupObjectInGroup(
  394. &pIF->LocalIpGroup,
  395. RM_CREATE,
  396. (PVOID) ULongToPtr (IpAddress), // pKey
  397. (PVOID) ULongToPtr (IpAddress), // pvCreateParams
  398. &(PRM_OBJECT_HEADER)pLocalIp,
  399. &fCreated,
  400. &sr
  401. );
  402. if (FAIL(Status)) break;
  403. //
  404. // NOTE: we already have claimed the pIF lock, which
  405. // which is the same as the pIF lock.
  406. //
  407. RM_ASSERT_SAME_LOCK_AS_PARENT(pLocalIp);
  408. // (Dbg only) Change lock scope from pIF to pLocalIp.
  409. //
  410. RmDbgChangeLockScope(
  411. &pIF->Hdr,
  412. &pLocalIp->Hdr,
  413. 0x9cbc0b52, // LocID
  414. &sr
  415. );
  416. if (fCreated)
  417. {
  418. if (AddressType == LLIP_ADDR_BCAST)
  419. {
  420. // Update the interface's broadcast address...
  421. //
  422. pIF->ip.BroadcastAddress = IpAddress;
  423. }
  424. else if (AddressType == LLIP_ADDR_LOCAL)
  425. {
  426. // Update the interface's default local IP address.
  427. // TODO: need to find another one if this address is removed.
  428. //
  429. pIF->ip.DefaultLocalAddress = IpAddress;
  430. }
  431. arpInitializeLocalIp(
  432. pLocalIp,
  433. AddressType,
  434. IpAddress,
  435. Mask,
  436. &sr
  437. );
  438. //
  439. // pLocalIp's lock is released above (which is actually the IF lock).
  440. //
  441. RM_ASSERT_NOLOCKS(&sr);
  442. }
  443. else
  444. {
  445. //
  446. // Hmm... this IP address already existed. Apparently it's possible for
  447. // MCAST addreses (IP/ATM arp module dealt with this for the MCAST case).
  448. // We don't special-case LOCAL/BCAST/MCAST addresses at this stage,
  449. // so we support multiple adds for all types of local IP addresses.
  450. //
  451. ASSERTEX(pLocalIp->AddAddressCount>0, pLocalIp);
  452. pLocalIp->AddAddressCount++;
  453. }
  454. RmTmpDereferenceObject(&pLocalIp->Hdr, &sr);
  455. } while (FALSE);
  456. TR_INFO((
  457. "IF 0x%p, Type %d, Addr %d.%d.%d.%d, Mask 0x%p, pLocIp 0x%p, Ret %d\n",
  458. pIF,
  459. AddressType,
  460. ((PUCHAR)(&IpAddress))[0],
  461. ((PUCHAR)(&IpAddress))[1],
  462. ((PUCHAR)(&IpAddress))[2],
  463. ((PUCHAR)(&IpAddress))[3],
  464. Mask, pLocalIp, !FAIL(Status)));
  465. RmUnlockAll(&sr);
  466. RM_ASSERT_CLEAR(&sr);
  467. EXIT()
  468. return !FAIL(Status);
  469. }
  470. UINT
  471. ArpIpDelAddress(
  472. IN PVOID Context,
  473. IN UINT AddressType,
  474. IN IP_ADDRESS IpAddress,
  475. IN IP_MASK Mask
  476. )
  477. /*++
  478. Routine Description:
  479. This is called from the IP layer when an address added via ArpIpAddAddress
  480. is to be deleted.
  481. Assumption: the given address was successfully added earlier.
  482. Arguments:
  483. Context - Actually a pointer to our Interface structure
  484. AddressType - Type of address(es) being deleted.
  485. IpAddress - Address to be deleted.
  486. Mask - For the above.
  487. Return Value:
  488. TRUE if successful, FALSE otherwise.
  489. --*/
  490. {
  491. ARP1394_INTERFACE * pIF = (ARP1394_INTERFACE*) Context;
  492. ENTER("ArpIpDelAddress", 0xd6630961)
  493. ARPCB_LOCAL_IP *pLocalIp = NULL;
  494. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  495. RM_DECLARE_STACK_RECORD(sr)
  496. TR_INFO(("Enter. pIF = 0x%p\n", Context));
  497. ASSERT(pIF->Hdr.Sig == MTAG_INTERFACE);
  498. #if OBSOLETE // See ArpIpAddAddress
  499. //
  500. // WARNING: We SHOULD NOT grab the IF lock, because we request that
  501. // the pLocalIp's lock be grabbed in RmLookupObjectInGroup below,
  502. // AND the pLocalIp's lock is actually the same as the IF lock.
  503. // (This is asserted later on below).
  504. // So obviously we can't get the IF lock here! (And we don't need to either).
  505. //
  506. #endif // OBSOLETE
  507. LOCKOBJ(pIF, &sr);
  508. ASSERT(!CHECK_IF_IP_STATE(pIF, ARPIF_IPS_CLOSED));
  509. do
  510. {
  511. Status = RmLookupObjectInGroup(
  512. &pIF->LocalIpGroup,
  513. 0, // Flags
  514. (PVOID) ULongToPtr (IpAddress), // pKey
  515. NULL, // pvCreateParams
  516. &(PRM_OBJECT_HEADER)pLocalIp,
  517. NULL, // pfCreated
  518. &sr
  519. );
  520. if (FAIL(Status))
  521. {
  522. UNLOCKOBJ(pIF, &sr);
  523. break;
  524. }
  525. //
  526. // NOTE: we have the pLocalIp lock, which is the same as the pIF lock.
  527. //
  528. RM_ASSERT_SAME_LOCK_AS_PARENT(pLocalIp);
  529. // (Dbg only) Change lock scope from pIF to pLocalIp.
  530. //
  531. RmDbgChangeLockScope(
  532. &pIF->Hdr,
  533. &pLocalIp->Hdr,
  534. 0x188ed5b3, // LocID
  535. &sr
  536. );
  537. if (pLocalIp->AddAddressCount <= 1)
  538. {
  539. ASSERTEX(pLocalIp->AddAddressCount == 1, pLocalIp);
  540. arpUnloadLocalIp(
  541. pLocalIp,
  542. &sr
  543. );
  544. //
  545. // pLocalIp's lock is released above.
  546. //
  547. RM_ASSERT_NOLOCKS(&sr);
  548. }
  549. else
  550. {
  551. pLocalIp->AddAddressCount--;
  552. UNLOCKOBJ(pLocalIp, &sr);
  553. }
  554. RmTmpDereferenceObject(&pLocalIp->Hdr, &sr);
  555. } while (FALSE);
  556. TR_INFO((
  557. "IF 0x%p, Type %d, Addr %d.%d.%d.%d, Mask 0x%p, pLocIp 0x%p, Ret %d\n",
  558. pIF,
  559. AddressType,
  560. ((PUCHAR)(&IpAddress))[0],
  561. ((PUCHAR)(&IpAddress))[1],
  562. ((PUCHAR)(&IpAddress))[2],
  563. ((PUCHAR)(&IpAddress))[3],
  564. Mask, pLocalIp, !FAIL(Status)));
  565. RM_ASSERT_CLEAR(&sr);
  566. EXIT()
  567. return !FAIL(Status);
  568. }
  569. NDIS_STATUS
  570. ArpIpMultiTransmit(
  571. IN PVOID Context,
  572. IN PNDIS_PACKET * pNdisPacketArray,
  573. IN UINT NumberOfPackets,
  574. IN IP_ADDRESS Destination,
  575. IN RouteCacheEntry * pRCE OPTIONAL,
  576. IN void * ArpCtxt
  577. )
  578. /*++
  579. TODO: implement send array-of-packets. Currenty we just call
  580. ArpIpTransmit multiple times. We'll gain a few cycles by processing
  581. all at once, although it's not going to be a big gain, because we're pretty
  582. fast with the single-packet case, provided the RCE is valid.
  583. Routine Description:
  584. This is called from the IP layer when it has a sequence of datagrams,
  585. each in the form of an NDIS buffer chain, to send over an Interface.
  586. Arguments:
  587. Context - Actually a pointer to our Interface structure
  588. pNdisPacketArray - Array of Packets to be sent on this Interface
  589. NumberOfPackets - Length of array
  590. Destination - IP address of next hop for this packet
  591. pRCE - Optional pointer to Route Cache Entry structure.
  592. Return Value:
  593. NDIS_STATUS_PENDING if all packets were queued for transmission.
  594. If one or more packets "failed", we set the packet status to reflect
  595. what happened to each, and return NDIS_STATUS_FAILURE.
  596. --*/
  597. {
  598. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  599. PNDIS_PACKET * ppNdisPacket;
  600. for (ppNdisPacket = pNdisPacketArray;
  601. NumberOfPackets > 0;
  602. NumberOfPackets--, ppNdisPacket++)
  603. {
  604. PNDIS_PACKET pNdisPacket;
  605. pNdisPacket = *ppNdisPacket;
  606. NDIS_SET_PACKET_STATUS(pNdisPacket, NDIS_STATUS_PENDING);
  607. ASSERTEX(pNdisPacket->Private.Head != NULL, pNdisPacket);
  608. Status = ArpIpTransmit(
  609. Context,
  610. *ppNdisPacket,
  611. Destination,
  612. pRCE
  613. ,NULL
  614. );
  615. if (Status != NDIS_STATUS_PENDING)
  616. {
  617. NDIS_SET_PACKET_STATUS(*ppNdisPacket, Status);
  618. break;
  619. }
  620. }
  621. return Status;
  622. }
  623. NDIS_STATUS
  624. ArpIpTransmit(
  625. IN PVOID Context,
  626. IN PNDIS_PACKET pNdisPacket,
  627. IN IP_ADDRESS Destination,
  628. IN RouteCacheEntry * pRCE OPTIONAL,
  629. IN void * ArpCtxt
  630. )
  631. /*++
  632. HOT PATH
  633. Routine Description:
  634. This is called from the IP layer when it has a datagram (in the form of
  635. an NDIS buffer chain) to send over an Interface.
  636. The destination IP address is passed to us in this routine, which may
  637. or may not be the final destination for the packet.
  638. The Route Cache Entry is created by the IP layer, and is used to speed
  639. up our lookups. An RCE, if specified, uniquely identifies atleast the
  640. IP destination for this packet. The RCE contains space for the ARP layer
  641. to keep context information about this destination. When the first packet
  642. goes out to a Destination, our context info in the RCE will be NULL, and
  643. we search the ARP Table for the matching IP Entry. However, we then fill
  644. our context info (pointer to IP Entry) in the RCE, so that subsequent
  645. transmits aren't slowed down by an IP address lookup.
  646. Arguments:
  647. Context - Actually a pointer to our Interface structure
  648. pNdisPacket - Packet to be sent on this Interface
  649. Destination - IP address of next hop for this packet
  650. pRCE - Optional pointer to Route Cache Entry structure.
  651. Return Value:
  652. Status of the transmit: NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, or
  653. a failure.
  654. --*/
  655. {
  656. ARP1394_INTERFACE * pIF = (ARP1394_INTERFACE*) Context;
  657. ARP1394_ADAPTER * pAdapter = (ARP1394_ADAPTER*) RM_PARENT_OBJECT(pIF );
  658. NDIS_STATUS Status;
  659. REMOTE_DEST_KEY DestinationKey;
  660. ARP_INIT_REENTRANCY_COUNT()
  661. ENTER("IfTransmit", 0x46f1973e)
  662. ARP_INC_REENTRANCY();
  663. ASSERT_VALID_INTERFACE(pIF);
  664. // IP does sometimes call this function before we set our state to OPEN,
  665. // so this is an incorrect assert...
  666. // ASSERT(!CHECK_IF_IP_STATE(pIF, ARPIF_IPS_CLOSED));
  667. TR_INFO((
  668. "pIf 0x%p, Pkt 0x%p, Dst 0x%p, pRCE 0x%p\n",
  669. pIF, pNdisPacket, Destination, pRCE));
  670. DBGMARK(0xf87d7fff);
  671. NdisInterlockedIncrement (&ArpSends);
  672. // Since we don't hold any locks, this check is approximate, but it should
  673. // prevent lots of useless activity while we're trying to shutdown.
  674. //
  675. // Check for not Inited Or Low Power
  676. if (!CHECK_IF_PRIMARY_STATE(pIF, ARPIF_PS_INITED) ||
  677. (! CHECK_POWER_STATE(pAdapter, ARPAD_POWER_NORMAL) ))
  678. {
  679. TR_INFO(("Failing ArpIpTransmit because pIF 0x%p is closing.\n", pIF));
  680. ARP_DEC_REENTRANCY();
  681. NdisInterlockedIncrement (&ArpSendCompletes);
  682. NdisInterlockedIncrement (&ArpSendFailure);
  683. return NDIS_STATUS_FAILURE; // EARLY_RETURN
  684. }
  685. #define LOGSTATS_TotSends(_pIF, _pNdisPacket) \
  686. NdisInterlockedIncrement(&((_pIF)->stats.sendpkts.TotSends))
  687. #define LOGSTATS_SetPktTimestamp(_pIF, _pNdisPacket) \
  688. { \
  689. LARGE_INTEGER liTemp = KeQueryPerformanceCounter(NULL); \
  690. *(PULONG) ((_pNdisPacket)->WrapperReservedEx) = liTemp.LowPart; \
  691. }
  692. LOGSTATS_TotSends(pIF, pNdisPacket);
  693. LOGSTATS_SetPktTimestamp(pIF, pNdisPacket);
  694. //
  695. // If there is a RCE, we'll try to quickly get all the information we need
  696. // and send off the packet. If we can't do this, we resort to the
  697. // "slow send path" (call arpIpSlowtransmit)...
  698. //
  699. if (pRCE != NULL)
  700. {
  701. ARP_RCE_CONTEXT * pArpRceContext;
  702. ARPCB_REMOTE_IP * pRemoteIp;
  703. pArpRceContext = ARP_OUR_CTXT_FROM_RCE(pRCE);
  704. ARP_FASTREADLOCK_IF_SEND_LOCK(pIF);
  705. pRemoteIp = pArpRceContext->pRemoteIp;
  706. //
  707. // Validate the Remote Ip. If it not meant for this packet
  708. // fall back to the slow path
  709. //
  710. if (pRemoteIp != NULL && pRemoteIp->IpAddress == Destination)
  711. {
  712. ARPCB_DEST * pDest;
  713. pDest = pRemoteIp->pDest;
  714. if (pDest != NULL )
  715. {
  716. //
  717. // Note: pDest->sendinfo is protected by the IF send lock.
  718. //
  719. if (ARP_CAN_SEND_ON_DEST(pDest))
  720. {
  721. #define LOGSTATS_FastSends(_pIF, _pNdisPacket) \
  722. NdisInterlockedIncrement(&((_pIF)->stats.sendpkts.FastSends))
  723. LOGSTATS_FastSends(pIF, pNdisPacket);
  724. arpSendIpPkt(pIF, pDest, pNdisPacket);
  725. //
  726. // IF Send lock released above.
  727. ARP_DEC_REENTRANCY();
  728. return NDIS_STATUS_PENDING; // EARLY RETURN
  729. }
  730. }
  731. }
  732. else
  733. {
  734. // if we have a mismatched RCE , then the RCE should be ignored
  735. // i,e. not be propagated to the SlowIpTransmit.
  736. //
  737. if (pRemoteIp != NULL && pRemoteIp->IpAddress != Destination)
  738. {
  739. pRCE = NULL;
  740. }
  741. }
  742. //
  743. // If we get here, it's on to slow path...
  744. //
  745. ARP_FASTUNLOCK_IF_SEND_LOCK(pIF);
  746. }
  747. // The slow path...
  748. //
  749. REMOTE_DEST_KEY_INIT(&DestinationKey);
  750. DestinationKey.IpAddress = Destination;
  751. Status = arpSlowIpTransmit(
  752. pIF,
  753. pNdisPacket,
  754. DestinationKey,
  755. pRCE
  756. );
  757. if (Status != NDIS_STATUS_PENDING)
  758. {
  759. LOGSTATS_SendFifoCounts(pIF, pNdisPacket, Status);
  760. }
  761. ARP_DEC_REENTRANCY();
  762. EXIT()
  763. return Status;
  764. }
  765. NDIS_STATUS
  766. ArpIpTransfer(
  767. IN PVOID Context,
  768. IN NDIS_HANDLE Context1,
  769. IN UINT ArpHdrOffset,
  770. IN UINT ProtoOffset,
  771. IN UINT BytesWanted,
  772. IN PNDIS_PACKET pNdisPacket,
  773. OUT PUINT pTransferCount
  774. )
  775. /*++
  776. Routine Description:
  777. This routine is called from the IP layer in order to copy in the
  778. contents of a received packet that we indicated up earlier. The
  779. context we had passed up in the receive indication is given back to
  780. us, so that we can identify what it was that we passed up.
  781. We simply call NDIS to do the transfer.
  782. Arguments:
  783. Context - Actually a pointer to our Interface structure
  784. Context1 - Packet context we had passed up (pointer to NDIS packet)
  785. ArpHdrOffset - Offset we had passed up in the receive indicate
  786. ProtoOffset - The offset into higher layer protocol data to start copy from
  787. BytesWanted - The amount of data to be copied
  788. pNdisPacket - The packet to be copied into
  789. pTransferCount - Where we return the actual #bytes copied
  790. Return Value:
  791. NDIS_STATUS_SUCCESS always.
  792. --*/
  793. {
  794. ENTER("IfTransfer", 0xa084562c)
  795. TR_INFO((
  796. "Ctx 0x%p, Ctx1 0x%p, HdrOff %d, ProtOff %d, Wanted %d, Pkt 0x%p\n",
  797. Context,
  798. Context1,
  799. ArpHdrOffset,
  800. ProtoOffset,
  801. BytesWanted,
  802. pNdisPacket));
  803. NdisCopyFromPacketToPacket(
  804. pNdisPacket,
  805. 0,
  806. BytesWanted,
  807. (PNDIS_PACKET)Context1,
  808. ArpHdrOffset+ProtoOffset,
  809. pTransferCount
  810. );
  811. EXIT()
  812. return NDIS_STATUS_SUCCESS;
  813. }
  814. VOID
  815. ArpIpInvalidate(
  816. IN PVOID Context,
  817. IN RouteCacheEntry * pRCE
  818. )
  819. /*++
  820. Routine Description:
  821. This routine is called from the IP layer to invalidate a Route Cache
  822. Entry. If this RCE is associated with one of our IP Entries, unlink
  823. it from the list of RCE's pointing to that IP entry.
  824. Arguments:
  825. Context - Actually a pointer to our Interface structure
  826. pRCE - Pointer to Route Cache Entry being invalidated.
  827. --*/
  828. {
  829. ARP1394_INTERFACE * pIF = (ARP1394_INTERFACE*) Context;
  830. ENTER("ArpIpInvalidate", 0xee77fb09)
  831. RM_DECLARE_STACK_RECORD(sr)
  832. TR_INFO(("Enter. pIF = 0x%p pRCE=0x%p\n", pIF, pRCE));
  833. ASSERT_VALID_INTERFACE(pIF);
  834. ASSERT(pRCE != NULL);
  835. DBGMARK(0xe35c780d);
  836. ARP_WRITELOCK_IF_SEND_LOCK(pIF, &sr);
  837. arpDelRce(pRCE, &sr);
  838. ARP_UNLOCK_IF_SEND_LOCK(pIF, &sr);
  839. RM_ASSERT_CLEAR(&sr);
  840. EXIT()
  841. }
  842. INT
  843. ArpIpQueryInfo(
  844. IN PVOID Context,
  845. IN TDIObjectID * pID,
  846. IN PNDIS_BUFFER pNdisBuffer,
  847. IN OUT PUINT pBufferSize,
  848. IN PVOID QueryContext
  849. )
  850. /*++
  851. Routine Description:
  852. This is called from the IP layer to query for statistics or other
  853. information about an interface.
  854. Arguments:
  855. Context - Actually a pointer to our Interface
  856. pID - Describes the object being queried
  857. pNdisBuffer - Space for returning information
  858. pBufferSize - Pointer to size of above. On return, we fill
  859. it with the actual bytes copied.
  860. QueryContext - Context value pertaining to the query.
  861. Return Value:
  862. TDI Status code.
  863. --*/
  864. {
  865. UINT EntityType;
  866. UINT Instance;
  867. INT ReturnStatus;
  868. ARP1394_INTERFACE * pIF = (ARP1394_INTERFACE*) Context;
  869. ENTER("ArpIpQueryInfo", 0x15059be1)
  870. RM_DECLARE_STACK_RECORD(sr)
  871. EntityType = pID->toi_entity.tei_entity;
  872. Instance = pID->toi_entity.tei_instance;
  873. TR_VERB((
  874. "IfQueryInfo: pIf 0x%p, pID 0x%p, pBuf 0x%p, Size %d, Ent %d, Inst %d\n",
  875. pIF, pID, pNdisBuffer, *pBufferSize, EntityType, Instance));
  876. ASSERT(pIF->Hdr.Sig == MTAG_INTERFACE);
  877. //
  878. // Initialize
  879. //
  880. ReturnStatus = TDI_INVALID_PARAMETER;
  881. LOCKOBJ(pIF, &sr);
  882. do
  883. {
  884. if (!CHECK_IF_PRIMARY_STATE(pIF, ARPIF_PS_INITED))
  885. {
  886. if (!CHECK_IF_ACTIVE_STATE(pIF, ARPIF_AS_ACTIVATING))
  887. {
  888. ReturnStatus = TDI_INVALID_REQUEST;
  889. break;
  890. }
  891. }
  892. //
  893. // Check the Entity and Instance values.
  894. //
  895. if ((EntityType != AT_ENTITY || Instance != pIF->ip.ATInstance) &&
  896. (EntityType != IF_ENTITY || Instance != pIF->ip.IFInstance))
  897. {
  898. TR_INFO(
  899. ("Mismatch: Entity %d, AT_ENTITY %d, Inst %d, IF AT Inst %d, IF_ENTITY %d, IF IF Inst %d\n",
  900. EntityType,
  901. AT_ENTITY,
  902. Instance,
  903. pIF->ip.ATInstance,
  904. IF_ENTITY,
  905. pIF->ip.IFInstance
  906. ));
  907. ReturnStatus = TDI_INVALID_REQUEST;
  908. break;
  909. }
  910. TR_VERB(("QueryInfo: pID 0x%p, toi_type %d, toi_class %d, toi_id %d\n",
  911. pID, pID->toi_type, pID->toi_class, pID->toi_id));
  912. if (pID->toi_type != INFO_TYPE_PROVIDER)
  913. {
  914. TR_INFO(("toi_type %d != PROVIDER (%d)\n",
  915. pID->toi_type,
  916. INFO_TYPE_PROVIDER));
  917. break;
  918. }
  919. if (pID->toi_class == INFO_CLASS_GENERIC)
  920. {
  921. if (pID->toi_id == ENTITY_TYPE_ID)
  922. {
  923. ReturnStatus = arpQueryIpEntityId(
  924. pIF,
  925. EntityType,
  926. pNdisBuffer,
  927. pBufferSize,
  928. &sr
  929. );
  930. }
  931. break;
  932. }
  933. if (EntityType == AT_ENTITY)
  934. {
  935. //
  936. // This query is for an Address Translation Object.
  937. //
  938. if (pID->toi_id == AT_MIB_ADDRXLAT_INFO_ID)
  939. {
  940. ReturnStatus = arpQueryIpAddrXlatInfo(
  941. pIF,
  942. pNdisBuffer,
  943. pBufferSize,
  944. &sr
  945. );
  946. }
  947. else if (pID->toi_id == AT_MIB_ADDRXLAT_ENTRY_ID)
  948. {
  949. ReturnStatus = arpQueryIpAddrXlatEntries(
  950. pIF,
  951. pNdisBuffer,
  952. pBufferSize,
  953. QueryContext,
  954. &sr
  955. );
  956. }
  957. else
  958. {
  959. ReturnStatus = TDI_INVALID_PARAMETER;
  960. }
  961. break;
  962. }
  963. if ( pID->toi_class == INFO_CLASS_PROTOCOL
  964. && pID->toi_id == IF_MIB_STATS_ID)
  965. {
  966. ReturnStatus = arpQueryIpMibStats(
  967. pIF,
  968. pNdisBuffer,
  969. pBufferSize,
  970. &sr
  971. );
  972. }
  973. }
  974. while (FALSE);
  975. if ( ReturnStatus != TDI_SUCCESS
  976. && ReturnStatus != TDI_BUFFER_OVERFLOW
  977. && ReturnStatus != TDI_INVALID_REQUEST)
  978. {
  979. //
  980. // This again preserves the semantics of QueryInfo from atmarpc.sys...
  981. //
  982. *pBufferSize = 0;
  983. }
  984. TR_VERB(("Returning 0x%p (%s), BufferSize %d\n",
  985. ReturnStatus,
  986. ((ReturnStatus == TDI_SUCCESS)? "SUCCESS": "FAILURE"),
  987. *pBufferSize
  988. ));
  989. UNLOCKOBJ(pIF, &sr);
  990. RM_ASSERT_CLEAR(&sr);
  991. EXIT()
  992. return (ReturnStatus);
  993. }
  994. INT
  995. ArpIpSetInfo(
  996. IN PVOID Context,
  997. IN TDIObjectID * pID,
  998. IN PVOID pBuffer,
  999. IN UINT BufferSize
  1000. )
  1001. /*++
  1002. Routine Description:
  1003. This is called from the IP layer to set the value of an object
  1004. for an interface.
  1005. Arguments:
  1006. Context - Actually a pointer to our Interface
  1007. pID - Describes the object being set
  1008. pBuffer - Value for the object
  1009. BufferSize - Size of above
  1010. Return Value:
  1011. TDI Status code.
  1012. --*/
  1013. {
  1014. ARP1394_INTERFACE *pIF = (ARP1394_INTERFACE*) Context;
  1015. UINT Entity, Instance;
  1016. IFEntry *pIFE = (IFEntry *) pBuffer;
  1017. NTSTATUS ReturnStatus = TDI_INVALID_REQUEST;
  1018. IPNetToMediaEntry *IPNME = NULL;
  1019. ENTER("IpSetInfo", 0x05dabea3)
  1020. RM_DECLARE_STACK_RECORD(sr)
  1021. //
  1022. // This code is taken from the tcpip Arp module with some changes to adjust
  1023. // it to arp1394's internal structures
  1024. //
  1025. // This code only supports deleting Arp Entries
  1026. //
  1027. Entity = pID->toi_entity.tei_entity;
  1028. Instance = pID->toi_entity.tei_instance;
  1029. do
  1030. {
  1031. // First, make sure it's possibly an ID we can handle.
  1032. if (Entity != AT_ENTITY || Instance != pIF->ip.ATInstance)
  1033. {
  1034. TR_INFO(
  1035. ("Mismatch: Entity %d, AT_ENTITY %d, Inst %d, IF AT Inst %d, IF_ENTITY %d, IF IF Inst %d\n",
  1036. Entity,
  1037. AT_ENTITY,
  1038. Instance,
  1039. pIF->ip.ATInstance,
  1040. IF_ENTITY,
  1041. pIF->ip.IFInstance
  1042. ));
  1043. ReturnStatus = TDI_INVALID_REQUEST;
  1044. break;
  1045. }
  1046. if (pID->toi_type != INFO_TYPE_PROVIDER) {
  1047. ReturnStatus = TDI_INVALID_REQUEST;
  1048. break;
  1049. }
  1050. if (pID->toi_id != AT_MIB_ADDRXLAT_ENTRY_ID ||
  1051. BufferSize < sizeof(IPNetToMediaEntry))
  1052. {
  1053. ReturnStatus = TDI_INVALID_REQUEST;
  1054. break;
  1055. }
  1056. // He does want to set an ARP table entry. See if he's trying to
  1057. // create or delete one.
  1058. IPNME = (IPNetToMediaEntry *) pBuffer;
  1059. if (IPNME->inme_type != INME_TYPE_INVALID)
  1060. {
  1061. ReturnStatus = TDI_INVALID_REQUEST;
  1062. break;
  1063. }
  1064. // We need to delete the IP address passed in the ipnme struct
  1065. ReturnStatus = arpDelArpEntry (pIF, IPNME->inme_addr, &sr);
  1066. }while (FALSE);
  1067. return ReturnStatus; // TBD: support Sets.
  1068. EXIT();
  1069. }
  1070. INT
  1071. ArpIpGetEList(
  1072. IN PVOID Context,
  1073. IN TDIEntityID * pEntityList,
  1074. IN OUT PUINT pEntityListSize
  1075. )
  1076. /*++
  1077. Routine Description:
  1078. This routine is called when the interface starts up, in order to
  1079. assign all relevant Entity Instance numbers for an interface.
  1080. The ARP1394 module belongs to the "AT" and "IF" types. The entity
  1081. list is a list of <Entity type, Instance number> tuples that have
  1082. been filled in by other modules.
  1083. For each of the entity types we support, we find the largest
  1084. instance number in use (by walking thru the Entity list), and
  1085. assign to ourselves the next larger number in each case. Using
  1086. these numbers, we append our tuples to the end of the Entity list,
  1087. if there is enough space.
  1088. W2K: we may find that our entries are already present, in which
  1089. case we don't create new entries.
  1090. Arguments:
  1091. Context - Actually a pointer to our ARP1394_INTERFACE
  1092. pEntityList - Pointer to TDI Entity list
  1093. pEntityListSize - Pointer to length of above list. We update
  1094. this if we add our entries to the list.
  1095. Return Value:
  1096. TRUE if successful, FALSE otherwise.
  1097. --*/
  1098. {
  1099. ARP1394_INTERFACE * pIF = (ARP1394_INTERFACE*) Context;
  1100. UINT EntityCount; // Total elements in Entity list
  1101. UINT i; // Iteration counter
  1102. UINT MyATInstance; // "AT" Instance number we assign to ourselves
  1103. UINT MyIFInstance; // "IF" Instance number we assign to ourselves
  1104. INT ReturnValue;
  1105. TDIEntityID * pATEntity; // Points to our AT entry
  1106. TDIEntityID * pIFEntity; // Points to our IF entry
  1107. ENTER("ArpIpGetEList", 0x8b5190e5)
  1108. RM_DECLARE_STACK_RECORD(sr)
  1109. ASSERT(pIF->Hdr.Sig == MTAG_INTERFACE);
  1110. EntityCount = *pEntityListSize;
  1111. pATEntity = NULL;
  1112. pIFEntity = NULL;
  1113. MyATInstance = MyIFInstance = 0;
  1114. TR_INFO(("IfGetEList: pIf 0x%p, &pIF.ip 0x%p pList 0x%p, Cnt %d\n",
  1115. pIF, &pIF->ip, pEntityList, EntityCount));
  1116. LOCKOBJ(pIF, &sr);
  1117. do
  1118. {
  1119. //
  1120. // Walk down the list, looking for AT/IF entries matching our
  1121. // instance values. Also remember the largest AT and IF instance
  1122. // values we see, so that we can allocate the next larger values
  1123. // for ourselves, in case we don't have instance values assigned.
  1124. //
  1125. for (i = 0; i < EntityCount; i++, pEntityList++)
  1126. {
  1127. //
  1128. // Skip invalid entries.
  1129. //
  1130. if (pEntityList->tei_instance == INVALID_ENTITY_INSTANCE)
  1131. {
  1132. continue;
  1133. }
  1134. if (pEntityList->tei_entity == AT_ENTITY)
  1135. {
  1136. if (pEntityList->tei_instance == pIF->ip.ATInstance)
  1137. {
  1138. //
  1139. // This is our AT entry.
  1140. //
  1141. pATEntity = pEntityList;
  1142. }
  1143. else
  1144. {
  1145. if (MyATInstance < (pEntityList->tei_instance + 1))
  1146. {
  1147. MyATInstance = pEntityList->tei_instance + 1;
  1148. }
  1149. }
  1150. }
  1151. else if (pEntityList->tei_entity == IF_ENTITY)
  1152. {
  1153. if (pEntityList->tei_instance == pIF->ip.IFInstance)
  1154. {
  1155. //
  1156. // This is our IF entry.
  1157. //
  1158. pIFEntity = pEntityList;
  1159. }
  1160. else
  1161. {
  1162. if (MyIFInstance < (pEntityList->tei_instance + 1))
  1163. {
  1164. MyIFInstance = pEntityList->tei_instance + 1;
  1165. }
  1166. }
  1167. }
  1168. }
  1169. ReturnValue = TRUE;
  1170. // WARNING: The following check is subtle -- we MUST set the instance
  1171. // values to INVALID_ENTITY_INSTANCE when the interface is being
  1172. // deactivated, but we MUST NOT do this if the interface is just opened
  1173. // (ArpIpOpen called) -- otherwise we could mess up the caller's state
  1174. // to such an extent that a reboot is required. Basically our behaviour
  1175. // here is what results in the proper acquiring AND release of instance IDs.
  1176. //
  1177. // So don't replace the following check by checking for
  1178. // ARPIF_PS_INITED or ARPIF_IPS_OPEN or even ARPIF_PS_DEINITING.
  1179. // The latter check (ARPIF_PS_DEINITING) would have been ok except for the
  1180. // fact that the IF is deactivated/reactivated during ARPIF_PS_REINITING
  1181. // as well, so the correct check is basically the one below...
  1182. //
  1183. //
  1184. if(CHECK_IF_ACTIVE_STATE(pIF, ARPIF_AS_DEACTIVATING))
  1185. {
  1186. //
  1187. // We're deactivating the interface, set values to invalid and
  1188. // get out of here...
  1189. //
  1190. if (pATEntity)
  1191. {
  1192. pATEntity->tei_instance = INVALID_ENTITY_INSTANCE;
  1193. }
  1194. if (pIFEntity)
  1195. {
  1196. pIFEntity->tei_instance = INVALID_ENTITY_INSTANCE;
  1197. }
  1198. break;
  1199. }
  1200. //
  1201. // Update or create our Address Translation entry.
  1202. //
  1203. if (pATEntity)
  1204. {
  1205. //
  1206. // We found our entry, nothing to do...
  1207. //
  1208. TR_INFO(("YOWZA: Found existing AT entry.\n"));
  1209. }
  1210. else
  1211. {
  1212. //
  1213. // Grab an entry for ourselves...
  1214. //
  1215. TR_INFO(("YOWZA: Grabbing new AT entry 0x%lu.\n", MyATInstance));
  1216. if (EntityCount >= MAX_TDI_ENTITIES)
  1217. {
  1218. ReturnValue = FALSE;
  1219. break;
  1220. }
  1221. pEntityList->tei_entity = AT_ENTITY;
  1222. pEntityList->tei_instance = MyATInstance;
  1223. pIF->ip.ATInstance = MyATInstance;
  1224. pEntityList++;
  1225. (*pEntityListSize)++;
  1226. EntityCount++;
  1227. }
  1228. //
  1229. // Update or create or IF entry.
  1230. //
  1231. if (pIFEntity)
  1232. {
  1233. //
  1234. // We found our entry, nothing to do...
  1235. //
  1236. TR_INFO(("YOWZA: Found existing IF entry.\n"));
  1237. }
  1238. else
  1239. {
  1240. //
  1241. // Grab an entry for ourselves.
  1242. //
  1243. TR_INFO(("YOWZA: Grabbing new IF entry 0x%lu.\n", MyIFInstance));
  1244. if (EntityCount >= MAX_TDI_ENTITIES)
  1245. {
  1246. ReturnValue = FALSE;
  1247. break;
  1248. }
  1249. pEntityList->tei_entity = IF_ENTITY;
  1250. pEntityList->tei_instance = MyIFInstance;
  1251. pIF->ip.IFInstance = MyIFInstance;
  1252. pEntityList++;
  1253. (*pEntityListSize)++;
  1254. EntityCount++;
  1255. }
  1256. }
  1257. while (FALSE);
  1258. TR_INFO(
  1259. ("IfGetEList: returning %d, MyAT %d, MyIF %d, pList 0x%p, Size %d\n",
  1260. ReturnValue, MyATInstance, MyIFInstance, pEntityList, *pEntityListSize));
  1261. UNLOCKOBJ(pIF, &sr);
  1262. RM_ASSERT_CLEAR(&sr);
  1263. EXIT()
  1264. return (ReturnValue);
  1265. }
  1266. VOID
  1267. ArpIpPnPComplete(
  1268. IN PVOID Context,
  1269. IN NDIS_STATUS Status,
  1270. IN PNET_PNP_EVENT pNetPnPEvent
  1271. )
  1272. /*++
  1273. Routine Description:
  1274. This routine is called by IP when it completes a previous call
  1275. we made to its PnP event handler. We complete the
  1276. NDIS PNP notification that lead to this.
  1277. Arguments:
  1278. Context - Actually a pointer to our ATMARP Interface
  1279. Status - Completion status from IP
  1280. pNetPnPEvent - The PNP event
  1281. Return Value:
  1282. None
  1283. --*/
  1284. {
  1285. ENTER("ArpIpPnPComplete", 0x23b1941e)
  1286. PARP1394_INTERFACE pIF;
  1287. pIF = (PARP1394_INTERFACE) Context;
  1288. TR_INFO(("IfPnPComplete: IF 0x%p, Status 0x%p, Event 0x%p\n",
  1289. pIF, Status, pNetPnPEvent));
  1290. if (pIF == NULL)
  1291. {
  1292. NdisCompletePnPEvent(
  1293. Status,
  1294. NULL,
  1295. pNetPnPEvent
  1296. );
  1297. }
  1298. else
  1299. {
  1300. PARP1394_ADAPTER pAdapter;
  1301. ASSERT_VALID_INTERFACE(pIF);
  1302. pAdapter = (PARP1394_ADAPTER) RM_PARENT_OBJECT(pIF);
  1303. NdisCompletePnPEvent(
  1304. Status,
  1305. pAdapter->bind.AdapterHandle,
  1306. pNetPnPEvent
  1307. );
  1308. }
  1309. EXIT()
  1310. return;
  1311. }
  1312. #ifdef PROMIS
  1313. EXTERN
  1314. NDIS_STATUS
  1315. ArpIpSetNdisRequest(
  1316. IN PVOID Context,
  1317. IN NDIS_OID Oid,
  1318. IN UINT On
  1319. )
  1320. /*++
  1321. Routine Description:
  1322. ARP Ndisrequest handler.
  1323. Called by the upper driver to set the packet filter for the interface.
  1324. Arguments:
  1325. Context - Actually a pointer to our ATMARP Interface
  1326. OID - Object ID to set/unset
  1327. On - Set_if, clear_if or clear_card
  1328. Return Value:
  1329. Status
  1330. --*/
  1331. {
  1332. return NDIS_STATUS_FAILURE;
  1333. #if 0
  1334. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1335. PATMARP_INTERFACE pInterface = (PATMARP_INTERFACE)Context;
  1336. AADEBUGP(AAD_INFO,("IfSetNdisRequest: pIF =0x%p; Oid=0x%p; On=%u\n",
  1337. pInterface,
  1338. Oid,
  1339. On
  1340. ));
  1341. do
  1342. {
  1343. //
  1344. // We set IPAddress and mask to span the entire mcast address range...
  1345. //
  1346. IP_ADDRESS IPAddress = IP_CLASSD_MIN;
  1347. IP_MASK Mask = IP_CLASSD_MASK;
  1348. UINT ReturnStatus = TRUE;
  1349. NDIS_OID PrevOidValue;
  1350. if (Oid != NDIS_PACKET_TYPE_ALL_MULTICAST)
  1351. {
  1352. Status = NDIS_STATUS_NOT_SUPPORTED;
  1353. break;
  1354. }
  1355. AA_STRUCT_ASSERT(pInterface, aai);
  1356. AA_ACQUIRE_IF_LOCK(pInterface);
  1357. PrevOidValue = pInterface->EnabledIPFilters & NDIS_PACKET_TYPE_ALL_MULTICAST;
  1358. if (On)
  1359. {
  1360. if (PrevOidValue == 0)
  1361. {
  1362. pInterface->EnabledIPFilters |= NDIS_PACKET_TYPE_ALL_MULTICAST;
  1363. ReturnStatus = AtmArpMcAddAddress(pInterface, IPAddress, Mask);
  1364. //
  1365. // IF lock released above
  1366. //
  1367. }
  1368. else
  1369. {
  1370. AA_RELEASE_IF_LOCK(pInterface);
  1371. }
  1372. }
  1373. else
  1374. {
  1375. if (PrevOidValue != 0)
  1376. {
  1377. pInterface->EnabledIPFilters &= ~NDIS_PACKET_TYPE_ALL_MULTICAST;
  1378. ReturnStatus = AtmArpMcDelAddress(pInterface, IPAddress, Mask);
  1379. //
  1380. // IF lock released above
  1381. //
  1382. }
  1383. else
  1384. {
  1385. AA_RELEASE_IF_LOCK(pInterface);
  1386. }
  1387. }
  1388. if (ReturnStatus != TRUE)
  1389. {
  1390. //
  1391. // We've got to restore EnabledIPFilters to it's original value.
  1392. //
  1393. AA_ACQUIRE_IF_LOCK(pInterface);
  1394. pInterface->EnabledIPFilters &= ~NDIS_PACKET_TYPE_ALL_MULTICAST;
  1395. pInterface->EnabledIPFilters |= PrevOidValue;
  1396. AA_RELEASE_IF_LOCK(pInterface);
  1397. Status = NDIS_STATUS_FAILURE;
  1398. }
  1399. }
  1400. while (FALSE);
  1401. AADEBUGP(AAD_INFO, ("IfSetNdisRequest(pIF =0x%p) returns 0x%p\n",
  1402. pInterface,
  1403. Status
  1404. ));
  1405. return Status;
  1406. #endif // 0
  1407. }
  1408. #endif // PROMIS
  1409. VOID
  1410. arpInitializeLocalIp(
  1411. IN ARPCB_LOCAL_IP * pLocalIp, // LOCKIN NOLOCKOUT
  1412. IN UINT AddressType,
  1413. IN IP_ADDRESS IpAddress,
  1414. IN IP_MASK Mask,
  1415. IN PRM_STACK_RECORD pSR
  1416. )
  1417. /*++
  1418. Routine Description:
  1419. Initialize the specified local ip object. This includines starting
  1420. address registration for the object.
  1421. Arguments:
  1422. pLocalIp - The object to be initialized.
  1423. AddressType - One of the LLIP_ADDR_* constants.
  1424. IpAddress - The IP address of the object.
  1425. Mask - The mask associated with the IP address.
  1426. --*/
  1427. {
  1428. ENTER("InitailizeLocalIp", 0x8a0ff47c)
  1429. RM_DBG_ASSERT_LOCKED(&pLocalIp->Hdr, pSR);
  1430. pLocalIp->IpAddress = IpAddress;
  1431. pLocalIp->IpMask = Mask;
  1432. pLocalIp->IpAddressType = AddressType;
  1433. pLocalIp->AddAddressCount = 1;
  1434. if (arpCanTryMcap(IpAddress))
  1435. {
  1436. SET_LOCALIP_MCAP(pLocalIp, ARPLOCALIP_MCAP_CAPABLE);
  1437. }
  1438. UNLOCKOBJ(pLocalIp, pSR);
  1439. EXIT()
  1440. }
  1441. VOID
  1442. arpUnloadLocalIp(
  1443. IN ARPCB_LOCAL_IP * pLocalIp, // LOCKIN NOLOCKOUT
  1444. IN PRM_STACK_RECORD pSR
  1445. )
  1446. /*++
  1447. Routine Description:
  1448. Starts a task to unload pLocalIp.
  1449. The actual unload could happen asynchronously.
  1450. Arguments:
  1451. pLocalIp - The object to be unloaded.
  1452. --*/
  1453. {
  1454. ARP1394_INTERFACE * pIF = (ARP1394_INTERFACE*) pLocalIp->Hdr.pParentObject;
  1455. ENTER("arpDeinitializeLocalIp", 0x1db1015e)
  1456. PRM_TASK pTask;
  1457. NDIS_STATUS Status;
  1458. TR_INFO(("Enter. pLocalIp = 0x%p\n", pLocalIp));
  1459. RM_DBG_ASSERT_LOCKED(&pLocalIp->Hdr, pSR);
  1460. #if TODO // if it can be synchronously unloaded, no need to start a task
  1461. // (on the other hand, I'm not sure we should bother)
  1462. if (arpLocalIpReadyForSyncDeinit(pLocalIp, pSR))
  1463. {
  1464. arpSyncDeinitLocalIp(pLocalIp, pSR); // Lock released on exit.
  1465. }
  1466. #endif // TODO
  1467. UNLOCKOBJ(pLocalIp, pSR);
  1468. //
  1469. // Allocate and start a task to unload pLocalIp;
  1470. //
  1471. Status = arpAllocateTask(
  1472. &pLocalIp->Hdr, // pParentObject
  1473. arpTaskUnloadLocalIp, // pfnHandler
  1474. 0, // Timeout
  1475. "Task: unload LocalIp", // szDescription
  1476. &pTask,
  1477. pSR
  1478. );
  1479. if (FAIL(Status))
  1480. {
  1481. // TODO Need special allocation mechanism for unload-related tasks
  1482. // that will block until a free task becomes available.
  1483. // See notes.txt 03/09/1999 entry "Special allocator for unload-related
  1484. // tasks
  1485. //
  1486. TR_FATAL(("FATAL: couldn't alloc unload-local-ip task!\n"));
  1487. }
  1488. else
  1489. {
  1490. (void)RmStartTask(
  1491. pTask,
  1492. 0, // UserParam (unused)
  1493. pSR
  1494. );
  1495. }
  1496. EXIT()
  1497. }
  1498. INT
  1499. arpQueryIpEntityId(
  1500. ARP1394_INTERFACE * pIF, // LOCKIN LOCKOUT
  1501. IN UINT EntityType,
  1502. IN PNDIS_BUFFER pNdisBuffer,
  1503. IN OUT PUINT pBufferSize,
  1504. PRM_STACK_RECORD pSR
  1505. )
  1506. /*++
  1507. Routine Description:
  1508. Return the entity ID for the specified EntityType.
  1509. Arguments:
  1510. pIF - Interface
  1511. EntityType - QueryInfo entity type (AT_*)
  1512. pNdisBuffer - Space for returning information
  1513. pBufferSize - Pointer to size of above. On return, we fill
  1514. it with the actual bytes copied.
  1515. Return Value:
  1516. TDI Status code.
  1517. --*/
  1518. {
  1519. ENTER("arpQueryIpEntityId", 0x1ada17cb)
  1520. UINT ReturnStatus;
  1521. RM_DBG_ASSERT_LOCKED(&pIF->Hdr, pSR);
  1522. if (*pBufferSize >= sizeof(UINT))
  1523. {
  1524. UINT EntityId;
  1525. UINT ByteOffset = 0;
  1526. TR_VERB(
  1527. ("INFO GENERIC, ENTITY TYPE, BufferSize %d\n", *pBufferSize));
  1528. EntityId = ((EntityType == AT_ENTITY) ? AT_ARP: IF_MIB);
  1529. arpCopyToNdisBuffer(
  1530. pNdisBuffer,
  1531. (PUCHAR)&EntityId,
  1532. sizeof(EntityId),
  1533. &ByteOffset);
  1534. // *pBufferSize = sizeof(UINT); << This was commented-out in atmarpc.sys
  1535. *pBufferSize = 0; // To keep the same behavior as atmarpc.sys
  1536. ReturnStatus = TDI_SUCCESS;
  1537. }
  1538. else
  1539. {
  1540. ReturnStatus = TDI_BUFFER_TOO_SMALL;
  1541. }
  1542. return ReturnStatus;
  1543. }
  1544. INT
  1545. arpQueryIpAddrXlatInfo(
  1546. ARP1394_INTERFACE * pIF, // LOCKIN LOCKOUT
  1547. IN PNDIS_BUFFER pNdisBuffer,
  1548. IN OUT PUINT pBufferSize,
  1549. PRM_STACK_RECORD pSR
  1550. )
  1551. /*++
  1552. Routine Description:
  1553. Request for the number of entries in the address translation
  1554. table, and the IF index.
  1555. Arguments:
  1556. pIF - Interface
  1557. pNdisBuffer - Space for returning information
  1558. pBufferSize - Pointer to size of above. On return, we fill
  1559. it with the actual bytes copied.
  1560. QueryContext - Context value pertaining to the query.
  1561. Return Value:
  1562. TDI Status code.
  1563. --*/
  1564. {
  1565. UINT ReturnStatus;
  1566. AddrXlatInfo Info;
  1567. ENTER("arpQueryIpXlatInfo", 0xd320b55a)
  1568. RM_DBG_ASSERT_LOCKED(&pIF->Hdr, pSR);
  1569. TR_INFO(("QueryInfo: AT Entity, for IF index, ATE size\n"));
  1570. if (*pBufferSize >= sizeof(Info))
  1571. {
  1572. UINT ByteOffset = 0;
  1573. ARP_ZEROSTRUCT(&Info);
  1574. *pBufferSize = sizeof(Info);
  1575. Info.axi_count = RM_NUM_ITEMS_IN_GROUP(&pIF->RemoteIpGroup);
  1576. Info.axi_index = pIF->ip.IFIndex;
  1577. arpCopyToNdisBuffer(
  1578. pNdisBuffer,
  1579. (PUCHAR)&Info,
  1580. sizeof(Info),
  1581. &ByteOffset);
  1582. ReturnStatus = TDI_SUCCESS;
  1583. }
  1584. else
  1585. {
  1586. ReturnStatus = TDI_BUFFER_TOO_SMALL;
  1587. }
  1588. EXIT()
  1589. return ReturnStatus;
  1590. }
  1591. VOID
  1592. arpCopyDestInfoIntoInmeInfo (
  1593. PUCHAR pinme_physaddr,
  1594. PARPCB_DEST pDest
  1595. )
  1596. /*++
  1597. Routine Description:
  1598. Copy the correct destination address to the location provided
  1599. In the Fifo Send case, we need to report the Fake Mac Address
  1600. In all other cases, we'll report the first six bytes of the destination
  1601. Arguments:
  1602. pinme_physaddr - Location we need to fill up.
  1603. pdest
  1604. Return Value:
  1605. TDI Status code.
  1606. --*/
  1607. {
  1608. PNIC1394_DESTINATION pNicDest = &pDest->Params.HwAddr;
  1609. ENetAddr FakeEnetAddress = {0,0,0,0,0,0};
  1610. PUCHAR pDestAddr = NULL;
  1611. //
  1612. // This assertion is important for this function to work.
  1613. // If it is changed, then we can no longer use FakeMac Addresses
  1614. // to identify remote nodes. We will have to revert back to using Unique IDs
  1615. //
  1616. ASSERT (sizeof(ENetAddr) == ARP1394_IP_PHYSADDR_LEN);
  1617. if (NIC1394AddressType_FIFO == pNicDest->AddressType &&
  1618. pDest->Params.ReceiveOnly== FALSE)
  1619. {
  1620. //
  1621. // We are translating an entry that describes a SendFifo Destination
  1622. //
  1623. //
  1624. // Use the same algorithm as nic1394 uses to get a
  1625. // MAC address to report back to IP
  1626. //
  1627. if (pNicDest->FifoAddress.UniqueID != 0)
  1628. {
  1629. nicGetMacAddressFromEuid(&pNicDest->FifoAddress.UniqueID, &FakeEnetAddress);
  1630. }
  1631. pDestAddr = (PUCHAR) &FakeEnetAddress;
  1632. }
  1633. else
  1634. {
  1635. // We'll use the first six bytes of the NIC1394_DESTINATION
  1636. //
  1637. // We copy the 1st ARP1394_IP_PHYSADDR_LEN bytes of the address...
  1638. // (In the case of a channel, only the 1st 4 bytes (UINT Channel)
  1639. // are significant; The rest will be all zeros.)
  1640. //
  1641. pDestAddr = (PUCHAR)pNicDest;
  1642. }
  1643. NdisMoveMemory (pinme_physaddr, pDestAddr, ARP1394_IP_PHYSADDR_LEN);
  1644. }
  1645. arpQueryIpAddrXlatEntries(
  1646. ARP1394_INTERFACE * pIF, // LOCKIN LOCKOUT
  1647. IN PNDIS_BUFFER pNdisBuffer,
  1648. IN OUT PUINT pBufferSize,
  1649. IN PVOID QueryContext,
  1650. PRM_STACK_RECORD pSR
  1651. )
  1652. /*++
  1653. Routine Description:
  1654. Return as many AddrXlat entries (aka arp entries) as will fit
  1655. into the specified buffer.
  1656. Arguments:
  1657. pIF - Interface
  1658. pNdisBuffer - Space for returning information
  1659. pBufferSize - Pointer to size of above. On return, we fill
  1660. it with the actual bytes copied.
  1661. QueryContext - Context value pertaining to the query.
  1662. Return Value:
  1663. TDI Status code.
  1664. --*/
  1665. {
  1666. //
  1667. // Our context structure is laid out as follows
  1668. //
  1669. typedef struct
  1670. {
  1671. IP_ADDRESS IpAddr;
  1672. // UINT TableSize; << TODO To deal with dynamic changes in table-size.
  1673. } OUR_QUERY_CONTEXT;
  1674. OUR_QUERY_CONTEXT * pOurCtxt;
  1675. UINT ReturnStatus;
  1676. UINT ByteOffset;
  1677. UINT BytesCopied;
  1678. UINT BufferSize;
  1679. ARPCB_REMOTE_IP * pRemoteIp;
  1680. NDIS_STATUS Status;
  1681. ENTER("arpQueryIpXlatEntries", 0x61c86684)
  1682. TR_INFO(("QueryInfo: AT Entity, for reading ATE\n"));
  1683. RM_DBG_ASSERT_LOCKED(&pIF->Hdr, pSR);
  1684. // See notes.txt entry ..
  1685. // 03/04/1999 JosephJ Size of the context passed in ArpIpQueryInfo.
  1686. //
  1687. ASSERT(sizeof(OUR_QUERY_CONTEXT) <= 16);
  1688. BufferSize = *pBufferSize;
  1689. *pBufferSize = 0;
  1690. BytesCopied = 0;
  1691. ByteOffset = 0;
  1692. pOurCtxt = (OUR_QUERY_CONTEXT*) QueryContext;
  1693. pRemoteIp = NULL;
  1694. ReturnStatus = TDI_SUCCESS;
  1695. //
  1696. // Our context structure is supposed to be initialized with Zeros the 1st time
  1697. // it's called.
  1698. //
  1699. if (pOurCtxt->IpAddr == 0)
  1700. {
  1701. //
  1702. // This is a brand new context. So we get the 1st entry.
  1703. //
  1704. Status = RmGetNextObjectInGroup(
  1705. &pIF->RemoteIpGroup,
  1706. NULL,
  1707. &(PRM_OBJECT_HEADER)pRemoteIp,
  1708. pSR
  1709. );
  1710. if (FAIL(Status))
  1711. {
  1712. // Presumably there are no entries.
  1713. pRemoteIp = NULL;
  1714. }
  1715. }
  1716. else
  1717. {
  1718. //
  1719. // This is an ongoing context. Let's look up this IP address, which is
  1720. // supposed to be the IP address of the next item in the arp table.
  1721. //
  1722. Status = RmLookupObjectInGroup(
  1723. &pIF->RemoteIpGroup,
  1724. 0, // Flags
  1725. (PVOID) ULongToPtr (pOurCtxt->IpAddr), // pKey
  1726. NULL, // pvCreateParams
  1727. &(PRM_OBJECT_HEADER)pRemoteIp,
  1728. NULL, // pfCreated
  1729. pSR
  1730. );
  1731. if (FAIL(Status))
  1732. {
  1733. //
  1734. // Ah well, things have changed since the last time we were called,
  1735. // and now this entry is no longer around.
  1736. //
  1737. pRemoteIp = NULL;
  1738. }
  1739. }
  1740. while (pRemoteIp != NULL)
  1741. {
  1742. ARPCB_REMOTE_IP * pNextRemoteIp = NULL;
  1743. IPNetToMediaEntry ArpEntry;
  1744. if (((INT)BufferSize - (INT)BytesCopied) < sizeof(ArpEntry))
  1745. {
  1746. //
  1747. // out of space; Update the context, and set special return value.
  1748. //
  1749. ARP_ZEROSTRUCT(pOurCtxt);
  1750. pOurCtxt->IpAddr = pRemoteIp->IpAddress;
  1751. ReturnStatus = TDI_BUFFER_OVERFLOW;
  1752. RmTmpDereferenceObject(&pRemoteIp->Hdr, pSR);
  1753. pRemoteIp = NULL;
  1754. break;
  1755. }
  1756. // Prepare the XlatEntry in ArpEntry.
  1757. //
  1758. {
  1759. ARP_ZEROSTRUCT(&ArpEntry);
  1760. ArpEntry.inme_index = pIF->ip.IFIndex;
  1761. ArpEntry.inme_addr = pRemoteIp->IpAddress;
  1762. if (CHECK_REMOTEIP_RESOLVE_STATE(pRemoteIp, ARPREMOTEIP_RESOLVED))
  1763. {
  1764. ARPCB_DEST *pDest = pRemoteIp->pDest;
  1765. TR_INFO(("ReadNext: found Remote IP Entry 0x%x, Addr %d.%d.%d.%d\n",
  1766. pRemoteIp,
  1767. ((PUCHAR)(&(pRemoteIp->IpAddress)))[0],
  1768. ((PUCHAR)(&(pRemoteIp->IpAddress)))[1],
  1769. ((PUCHAR)(&(pRemoteIp->IpAddress)))[2],
  1770. ((PUCHAR)(&(pRemoteIp->IpAddress)))[3]
  1771. ));
  1772. // We assert that
  1773. // IF lock is the same as pRemoteIp's and pDest's lock,
  1774. // and that lock is locked.
  1775. // We implicitly assert that pDest is non-NULl as well.
  1776. //
  1777. ASSERTEX(pRemoteIp->Hdr.pLock == pDest->Hdr.pLock, pRemoteIp);
  1778. RM_DBG_ASSERT_LOCKED(&pRemoteIp->Hdr, pSR);
  1779. ArpEntry.inme_physaddrlen = ARP1394_IP_PHYSADDR_LEN;
  1780. // We copy the 1st ARP1394_IP_PHYSADDR_LEN bytes of the address...
  1781. // (In the case of a channel, only the 1st 4 bytes (UINT Channel)
  1782. // are significant; The rest will be all zeros.)
  1783. //
  1784. ASSERT(sizeof(pDest->Params.HwAddr)>=ARP1394_IP_PHYSADDR_LEN);
  1785. arpCopyDestInfoIntoInmeInfo (ArpEntry.inme_physaddr,pDest);
  1786. if (CHECK_REMOTEIP_SDTYPE(pRemoteIp, ARPREMOTEIP_STATIC))
  1787. {
  1788. ArpEntry.inme_type = INME_TYPE_STATIC;
  1789. }
  1790. else
  1791. {
  1792. ArpEntry.inme_type = INME_TYPE_DYNAMIC;
  1793. }
  1794. }
  1795. else
  1796. {
  1797. ArpEntry.inme_physaddrlen = 0;
  1798. ArpEntry.inme_type = INME_TYPE_INVALID;
  1799. }
  1800. }
  1801. // Copy into the supplied ndis buffer.
  1802. //
  1803. BytesCopied += sizeof(ArpEntry);
  1804. pNdisBuffer = arpCopyToNdisBuffer(
  1805. pNdisBuffer,
  1806. (PUCHAR)&ArpEntry,
  1807. sizeof(ArpEntry),
  1808. &ByteOffset
  1809. );
  1810. // Lookup next entry's IP address and save it in our context.
  1811. //
  1812. Status = RmGetNextObjectInGroup(
  1813. &pIF->RemoteIpGroup,
  1814. &pRemoteIp->Hdr,
  1815. &(PRM_OBJECT_HEADER)pNextRemoteIp,
  1816. pSR
  1817. );
  1818. if (FAIL(Status))
  1819. {
  1820. //
  1821. // we're presumably done.
  1822. //
  1823. pNextRemoteIp = NULL;
  1824. }
  1825. // TmpDeref pRemoteIp and move on to the next one.
  1826. //
  1827. RmTmpDereferenceObject(&pRemoteIp->Hdr, pSR);
  1828. pRemoteIp = pNextRemoteIp;
  1829. }
  1830. ASSERT(pRemoteIp == NULL);
  1831. *pBufferSize = BytesCopied;
  1832. EXIT()
  1833. return ReturnStatus;
  1834. }
  1835. arpQueryIpMibStats(
  1836. ARP1394_INTERFACE * pIF, // LOCKIN LOCKOUT
  1837. IN PNDIS_BUFFER pNdisBuffer,
  1838. IN OUT PUINT pBufferSize,
  1839. PRM_STACK_RECORD pSR
  1840. )
  1841. /*++
  1842. Routine Description:
  1843. Fill out Interface-level statistics.
  1844. Arguments:
  1845. pIF - Interface
  1846. pNdisBuffer - Space for returning information
  1847. pBufferSize - Pointer to size of above. On return, we fill
  1848. it with the actual bytes copied.
  1849. Return Value:
  1850. TDI Status code.
  1851. --*/
  1852. {
  1853. ENTER("arpQueryIpMibStatus", 0xc5bc364f)
  1854. UINT ReturnStatus;
  1855. UINT BufferSize;
  1856. TR_VERB(("QueryInfo: MIB statistics\n"));
  1857. RM_DBG_ASSERT_LOCKED(&pIF->Hdr, pSR);
  1858. BufferSize = *pBufferSize;
  1859. *pBufferSize = 0;
  1860. do
  1861. {
  1862. IFEntry ife;
  1863. ARP1394_ADAPTER * pAdapter;
  1864. UINT ByteOffset;
  1865. UINT BytesCopied;
  1866. //
  1867. // Check if we have enough space.
  1868. //
  1869. if (BufferSize < IFE_FIXED_SIZE)
  1870. {
  1871. ReturnStatus = TDI_BUFFER_TOO_SMALL;
  1872. break;
  1873. }
  1874. ARP_ZEROSTRUCT(&ife);
  1875. pAdapter = (ARP1394_ADAPTER*) RM_PARENT_OBJECT(pIF);
  1876. BytesCopied = 0;
  1877. ByteOffset = 0;
  1878. //
  1879. // Fill out mib info...
  1880. //
  1881. ife.if_index = pIF->ip.IFIndex;
  1882. ife.if_mtu = pIF->ip.MTU;
  1883. ife.if_type = IF_TYPE_IEEE1394;
  1884. ife.if_speed = pAdapter->info.Speed;
  1885. // Set adminstatus and operstatus (computed from pIF->Hdr.State)
  1886. //
  1887. ife.if_adminstatus = IF_STATUS_UP;
  1888. ife.if_operstatus = IF_OPER_STATUS_OPERATIONAL;
  1889. if (CHECK_IF_PRIMARY_STATE(pIF, ARPIF_PS_DEINITING))
  1890. {
  1891. ife.if_adminstatus = IF_STATUS_DOWN;
  1892. }
  1893. if (!CHECK_IF_IP_STATE(pIF, ARPIF_IPS_OPEN))
  1894. {
  1895. ife.if_operstatus = IF_OPER_STATUS_NON_OPERATIONAL;
  1896. }
  1897. // Stats...
  1898. //
  1899. ife.if_lastchange = pIF->stats.LastChangeTime;
  1900. ife.if_inoctets = pIF->stats.InOctets;
  1901. ife.if_inucastpkts = pIF->stats.InUnicastPkts;
  1902. ife.if_innucastpkts = pIF->stats.InNonUnicastPkts;
  1903. ife.if_indiscards = pIF->stats.InDiscards;
  1904. ife.if_inerrors = pIF->stats.InErrors;
  1905. ife.if_inunknownprotos = pIF->stats.UnknownProtos;
  1906. ife.if_outoctets = pIF->stats.OutOctets;
  1907. ife.if_outucastpkts = pIF->stats.OutUnicastPkts;
  1908. ife.if_outnucastpkts = pIF->stats.OutNonUnicastPkts;
  1909. ife.if_outdiscards = pIF->stats.OutDiscards;
  1910. ife.if_outerrors = pIF->stats.OutErrors;
  1911. ife.if_outqlen = pIF->stats.OutQlen;
  1912. ife.if_descrlen = pAdapter->info.DescriptionLength;
  1913. ASSERT(ARP1394_IP_PHYSADDR_LEN <= sizeof(pAdapter->info.EthernetMacAddress));
  1914. ife.if_physaddrlen = ARP1394_IP_PHYSADDR_LEN;
  1915. #if 1 // MILLEN
  1916. //
  1917. // Win98: winipcfg doesn't like more than 6 bytes repored here.
  1918. //
  1919. if (ife.if_physaddrlen > 6)
  1920. {
  1921. ife.if_physaddrlen = 6;
  1922. }
  1923. #endif// MILLEN
  1924. //
  1925. // Tell TCPIP that the Ethernet Address is the real physical address.
  1926. // This helps us because now we have the same 'MAC' address whether
  1927. // we are in a network which is bridged to Ethernet or not.
  1928. //
  1929. NdisMoveMemory(
  1930. ife.if_physaddr,
  1931. &(pAdapter->info.EthernetMacAddress),
  1932. ife.if_physaddrlen
  1933. );
  1934. arpCopyToNdisBuffer(
  1935. pNdisBuffer,
  1936. (PUCHAR)&ife,
  1937. IFE_FIXED_SIZE,
  1938. &ByteOffset);
  1939. if (BufferSize >= (IFE_FIXED_SIZE + ife.if_descrlen))
  1940. {
  1941. if (ife.if_descrlen != 0)
  1942. {
  1943. arpCopyToNdisBuffer(
  1944. pNdisBuffer,
  1945. pAdapter->info.szDescription,
  1946. ife.if_descrlen,
  1947. &ByteOffset);
  1948. }
  1949. *pBufferSize = IFE_FIXED_SIZE + ife.if_descrlen;
  1950. ReturnStatus = TDI_SUCCESS;
  1951. }
  1952. else
  1953. {
  1954. *pBufferSize = IFE_FIXED_SIZE;
  1955. ReturnStatus = TDI_BUFFER_OVERFLOW;
  1956. }
  1957. } while (FALSE);
  1958. EXIT()
  1959. return ReturnStatus;
  1960. }
  1961. PNDIS_BUFFER
  1962. arpCopyToNdisBuffer(
  1963. IN PNDIS_BUFFER pDestBuffer,
  1964. IN PUCHAR pDataSrc,
  1965. IN UINT LenToCopy,
  1966. IN OUT PUINT pOffsetInBuffer
  1967. )
  1968. /*++
  1969. Routine Description:
  1970. Copy data into an NDIS buffer chain. Use up as much of the given
  1971. NDIS chain as needed for "LenToCopy" bytes. After copying is over,
  1972. return a pointer to the first NDIS buffer that has space for writing
  1973. into (for the next Copy operation), and the offset within this from
  1974. which to start writing.
  1975. Arguments:
  1976. pDestBuffer - First NDIS buffer in a chain of buffers
  1977. pDataSrc - Where to copy data from
  1978. LenToCopy - How much data to copy
  1979. pOffsetInBuffer - Offset in pDestBuffer where we can start copying into.
  1980. Return Value:
  1981. The NDIS buffer in the chain where the next Copy can be done. We also
  1982. set *pOffsetInBuffer to the write offset in the returned NDIS buffer.
  1983. --*/
  1984. {
  1985. //
  1986. // Size and destination for individual (contiguous) copy operations
  1987. //
  1988. UINT CopySize;
  1989. PUCHAR pDataDst;
  1990. //
  1991. // Start Virtual address for each NDIS buffer in chain.
  1992. //
  1993. PUCHAR VirtualAddress;
  1994. //
  1995. // Offset within pDestBuffer
  1996. //
  1997. UINT OffsetInBuffer = *pOffsetInBuffer;
  1998. //
  1999. // Bytes remaining in current buffer
  2000. //
  2001. UINT DestSize;
  2002. //
  2003. // Total Buffer Length
  2004. //
  2005. UINT BufferLength;
  2006. ASSERT(pDestBuffer != (PNDIS_BUFFER)NULL);
  2007. ASSERT(pDataSrc != NULL);
  2008. #if MILLEN
  2009. NdisQueryBuffer(
  2010. pDestBuffer,
  2011. &VirtualAddress,
  2012. &BufferLength
  2013. );
  2014. #else
  2015. NdisQueryBufferSafe(
  2016. pDestBuffer,
  2017. &VirtualAddress,
  2018. &BufferLength,
  2019. NormalPagePriority
  2020. );
  2021. if (VirtualAddress == NULL)
  2022. {
  2023. return (NULL);
  2024. }
  2025. #endif
  2026. ASSERT(BufferLength >= OffsetInBuffer);
  2027. pDataDst = VirtualAddress + OffsetInBuffer;
  2028. DestSize = BufferLength - OffsetInBuffer;
  2029. for (;;)
  2030. {
  2031. CopySize = LenToCopy;
  2032. if (CopySize > DestSize)
  2033. {
  2034. CopySize = DestSize;
  2035. }
  2036. NdisMoveMemory(pDataDst, pDataSrc, CopySize);
  2037. pDataDst += CopySize;
  2038. pDataSrc += CopySize;
  2039. LenToCopy -= CopySize;
  2040. if (LenToCopy == 0)
  2041. {
  2042. break;
  2043. }
  2044. DestSize -= CopySize;
  2045. if (DestSize == 0)
  2046. {
  2047. //
  2048. // Out of space in the current buffer. Move to the next.
  2049. //
  2050. pDestBuffer = NDIS_BUFFER_LINKAGE(pDestBuffer);
  2051. if (pDestBuffer == NULL)
  2052. {
  2053. ASSERT(FALSE);
  2054. return NULL;
  2055. }
  2056. else
  2057. {
  2058. #if MILLEN
  2059. NdisQueryBuffer(
  2060. pDestBuffer,
  2061. &VirtualAddress,
  2062. &BufferLength
  2063. );
  2064. #else // !MILLEN
  2065. NdisQueryBufferSafe(
  2066. pDestBuffer,
  2067. &VirtualAddress,
  2068. &BufferLength,
  2069. NormalPagePriority
  2070. );
  2071. if (VirtualAddress == NULL)
  2072. {
  2073. return NULL;
  2074. }
  2075. #endif // !MILLEN
  2076. pDataDst = VirtualAddress;
  2077. DestSize = BufferLength;
  2078. }
  2079. }
  2080. }
  2081. *pOffsetInBuffer = (UINT) (pDataDst - VirtualAddress);
  2082. return (pDestBuffer);
  2083. }
  2084. VOID
  2085. arpSendIpPkt(
  2086. IN ARP1394_INTERFACE * pIF, // LOCKIN NOLOCKOUT (IF send lk)
  2087. IN PARPCB_DEST pDest,
  2088. IN PNDIS_PACKET pNdisPacket
  2089. )
  2090. /*++
  2091. HOT PATH
  2092. Routine Description:
  2093. Send a packet to the FIFO/channel associated with destination object pDest.
  2094. Arguments:
  2095. pIF - Our interface object
  2096. pDest - Destination object on which to send packet
  2097. pNdisPacket - Packet to send
  2098. --*/
  2099. {
  2100. NDIS_STATUS Status;
  2101. MYBOOL fRet;
  2102. ARP1394_ADAPTER * pAdapter =
  2103. (ARP1394_ADAPTER*) RM_PARENT_OBJECT(pIF);
  2104. MYBOOL fBridgeMode = ARP_BRIDGE_ENABLED(pAdapter);
  2105. DBGMARK(0xdaab68c3);
  2106. //
  2107. // If we can't send now, we immediately call IP's send complete handler.
  2108. //
  2109. if (!ARP_CAN_SEND_ON_DEST(pDest))
  2110. {
  2111. ARP_FASTUNLOCK_IF_SEND_LOCK(pIF);
  2112. if (ARP_DEST_IS_FIFO(pDest))
  2113. {
  2114. LOGSTATS_SendFifoCounts(pIF, pNdisPacket, NDIS_STATUS_FAILURE);
  2115. }
  2116. else
  2117. {
  2118. LOGSTATS_SendChannelCounts(pIF, pNdisPacket, NDIS_STATUS_FAILURE);
  2119. }
  2120. #if MILLEN
  2121. ASSERT_PASSIVE();
  2122. #endif // MILLEN
  2123. NdisInterlockedIncrement (&ArpSendCompletes);
  2124. NdisInterlockedIncrement (&ArpSendFailure);
  2125. if (fBridgeMode)
  2126. {
  2127. // In bridge (ethernet emulation) mode, we created the
  2128. // packets ourselves, so we delete them here, instead
  2129. // of calling Ip's completion handler, which in fact
  2130. // is NULL.
  2131. //
  2132. RM_DECLARE_STACK_RECORD(sr)
  2133. arpFreeControlPacket(
  2134. pIF,
  2135. pNdisPacket,
  2136. &sr
  2137. );
  2138. }
  2139. else
  2140. {
  2141. (*(pIF->ip.TxCmpltHandler))(
  2142. pIF->ip.Context,
  2143. pNdisPacket,
  2144. NDIS_STATUS_FAILURE
  2145. );
  2146. }
  2147. return; // EARLY RETURN
  2148. }
  2149. arpRefSendPkt( pNdisPacket, pDest);
  2150. // Release the IF send lock.
  2151. //
  2152. ARP_FASTUNLOCK_IF_SEND_LOCK(pIF);
  2153. // NOW (with IF send lock released), we prepare the IP packet for sending....
  2154. //
  2155. // We do this only if not in ethernet emulation (bridge) mode,
  2156. // because all IP packets in bridge mode already have the
  2157. // proper 1394 header on them.
  2158. //
  2159. if (!fBridgeMode)
  2160. {
  2161. PNDIS_BUFFER pNdisBuffer; // First buffer in the IP packet
  2162. // TODO: is this safe? How about a check for the size by which this is possible!
  2163. #if !MILLEN
  2164. #define ARP_BACK_FILL_POSSIBLE(_pBuf) \
  2165. (((_pBuf)->MdlFlags & MDL_NETWORK_HEADER) != 0)
  2166. #else // MILLEN
  2167. #define ARP_BACK_FILL_POSSIBLE(_pBuf) (0)
  2168. #endif // MILLEN
  2169. //
  2170. // We look at the first buffer in the IP packet, to see whether
  2171. // it has space reserved for low-layer headers. If so, we just
  2172. // use it up. Otherwise, we allocate a header buffer of our own.
  2173. //
  2174. NdisQueryPacket(pNdisPacket, NULL, NULL, &pNdisBuffer, NULL);
  2175. ASSERTEX(pNdisBuffer != NULL, pNdisPacket);
  2176. if (ARP_BACK_FILL_POSSIBLE(pNdisBuffer))
  2177. {
  2178. const ULONG EncapLength = sizeof(Arp1394_IpEncapHeader);
  2179. #if MILLEN
  2180. ASSERT(!"We shouldn't be here -- check ARP_BACK_FILL_POSSIBLE()");
  2181. #else // !MILLEN
  2182. (PUCHAR)pNdisBuffer->MappedSystemVa -= EncapLength;
  2183. pNdisBuffer->ByteOffset -= EncapLength;
  2184. pNdisBuffer->ByteCount += EncapLength;
  2185. NdisMoveMemory(
  2186. pNdisBuffer->MappedSystemVa,
  2187. &Arp1394_IpEncapHeader,
  2188. EncapLength
  2189. );
  2190. #define LOGSTATS_BackFills(_pIF, _pNdisPacket) \
  2191. NdisInterlockedIncrement(&((_pIF)->stats.sendpkts.BackFills))
  2192. LOGSTATS_BackFills(pIF, pNdisPacket);
  2193. #endif // !MILLEN
  2194. }
  2195. else
  2196. {
  2197. //
  2198. // Backfill wasn't possible for this packet. Let's try to allocate
  2199. // an encapsulation header buffer from the IF pool...
  2200. //
  2201. pNdisBuffer = arpAllocateConstBuffer(&pIF->sendinfo.HeaderPool);
  2202. if (pNdisBuffer != (PNDIS_BUFFER)NULL)
  2203. {
  2204. // Our send complete handler relies on this assertion to decide
  2205. // whether backfill happened or not.
  2206. //
  2207. ASSERT(!ARP_BACK_FILL_POSSIBLE(pNdisBuffer));
  2208. NdisChainBufferAtFront(pNdisPacket, pNdisBuffer);
  2209. }
  2210. else
  2211. {
  2212. //
  2213. // Oops, we couldn't allocate an encapsulation buffer!
  2214. // We've already referenced the destination for sends.
  2215. //
  2216. //
  2217. // Cop out for now (we haven't implemented all the queuing
  2218. // code for now) by calling our own send complete handler with
  2219. // status failure.
  2220. //
  2221. // We use the special return value NDIS_STATUS_NOT_RESETTABLE
  2222. // to indicate that we haven't inserted our own buffer,
  2223. // (and so the packet shouldn't be "reset"). Ok this is a bit
  2224. // hacky, but it works.
  2225. //
  2226. arpCompleteSentPkt(
  2227. NDIS_STATUS_NOT_RESETTABLE,
  2228. pIF,
  2229. pDest,
  2230. pNdisPacket
  2231. );
  2232. return; // EARLY RETURN
  2233. }
  2234. }
  2235. }
  2236. // Actually send the packet
  2237. //
  2238. #if ARPDBG_FAKE_SEND
  2239. arpDbgFakeNdisCoSendPackets(
  2240. pDest->VcHdr.NdisVcHandle,
  2241. &pNdisPacket,
  2242. 1,
  2243. &pDest->Hdr,
  2244. &pDest->VcHdr
  2245. );
  2246. #else // !ARPDBG_FAKE_SEND
  2247. NdisCoSendPackets(
  2248. pDest->VcHdr.NdisVcHandle,
  2249. &pNdisPacket,
  2250. 1
  2251. );
  2252. #endif // !ARPDBG_FAKE_SEND
  2253. }
  2254. NDIS_STATUS
  2255. arpSlowIpTransmit(
  2256. IN ARP1394_INTERFACE * pIF,
  2257. IN PNDIS_PACKET pNdisPacket,
  2258. IN REMOTE_DEST_KEY Destination,
  2259. IN RouteCacheEntry * pRCE OPTIONAL
  2260. )
  2261. /*++
  2262. Routine Description:
  2263. This is the path taken (hopefully only for a small fraction of the packets)
  2264. when something has prevented the packet from being immediately sent down to
  2265. the miniport. Typically we're here for one of the following reasons:
  2266. 1. IP Address is not resolved yet.
  2267. 2. RCE entry has not been initialized yet.
  2268. 3. Couldn't allocate an encapsulation-header buffer.
  2269. 4. The Vc to the destination doesn't exist or is not ready for sending yet.
  2270. Arguments:
  2271. pIF - Our interface object
  2272. pNdisPacket - Packet to send
  2273. Destination - IP address of destination
  2274. pRCE - (OPTIONAL) Route Cache Entry associated with this
  2275. destination
  2276. Return Value:
  2277. NDIS_STATUS_SUCCESS on synchronous success.
  2278. NDIS_STATUS_PENDING if completion is asynchronous
  2279. Other ndis status code on other kinds of failure.
  2280. --*/
  2281. {
  2282. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  2283. ARP1394_ADAPTER * pAdapter = (ARP1394_ADAPTER*) RM_PARENT_OBJECT(pIF);
  2284. ENTER("arpSlowIpTransmit", 0xe635299c)
  2285. BOOLEAN fBridgeMode = ARP_BRIDGE_ENABLED(pAdapter);
  2286. ULONG LookupFlags = 0;
  2287. UINT fRemoteIpCreated = FALSE;
  2288. RM_DECLARE_STACK_RECORD(sr)
  2289. DBGMARK(0x30b6f7e2);
  2290. do
  2291. {
  2292. ARP_RCE_CONTEXT * pArpRceContext = NULL;
  2293. ARPCB_REMOTE_IP * pRemoteIp = NULL;
  2294. ARPCB_DEST * pDest = NULL;
  2295. #define LOGSTATS_SlowSends(_pIF, _pNdisPacket) \
  2296. NdisInterlockedIncrement(&((_pIF)->stats.sendpkts.SlowSends))
  2297. #define LOGSTATS_MediumSends(_pIF, _pNdisPacket) \
  2298. NdisInterlockedIncrement(&((_pIF)->stats.sendpkts.MediumSends))
  2299. //
  2300. // If there is a RCE, we try to get the pRemoteIp from it If not
  2301. // successful, we'll need to actually lookup/create the pRemoteIp from the
  2302. // IF RemoteIpGroup.
  2303. //
  2304. if (pRCE != NULL)
  2305. {
  2306. pArpRceContext = ARP_OUR_CTXT_FROM_RCE(pRCE);
  2307. // All RCE linkages are protected by the IF send lock.
  2308. //
  2309. ARP_READLOCK_IF_SEND_LOCK(pIF, &sr);
  2310. pRemoteIp = pArpRceContext->pRemoteIp;
  2311. if (pRemoteIp != NULL)
  2312. {
  2313. RmTmpReferenceObject(&pRemoteIp->Hdr, &sr);
  2314. }
  2315. ARP_UNLOCK_IF_SEND_LOCK(pIF, &sr);
  2316. }
  2317. if (pRemoteIp == NULL)
  2318. {
  2319. //
  2320. // Either there was no RCE or it was uninitialized.
  2321. // We'll lookup/create the pRemoteIp based on the destination
  2322. // IP address...
  2323. //
  2324. RM_ASSERT_NOLOCKS(&sr);
  2325. //
  2326. // Create the destination, this will cause us to resolve IP Addresses, etc/
  2327. //
  2328. LookupFlags = RM_CREATE;
  2329. if (fBridgeMode == TRUE)
  2330. {
  2331. //
  2332. // do not create a remote IP struct, only look it up
  2333. //
  2334. LookupFlags = 0;
  2335. }
  2336. // if in bridge mode
  2337. // set flags to zero , else RM_CREATE
  2338. Status = RmLookupObjectInGroup(
  2339. &pIF->RemoteIpGroup,
  2340. LookupFlags,
  2341. (PVOID) &Destination,
  2342. (PVOID) (&Destination), // pCreateParams
  2343. (RM_OBJECT_HEADER**) &pRemoteIp,
  2344. &fRemoteIpCreated, // pfCreated (unused)
  2345. &sr
  2346. );
  2347. LOGSTATS_TotalArpCacheLookups(pIF, Status);
  2348. if (FAIL(Status))
  2349. {
  2350. OBJLOG1(
  2351. pIF,
  2352. "Couldn't lookup/create localIp entry with addr 0x%lx\n",
  2353. Destination.IpAddress
  2354. );
  2355. Status = NDIS_STATUS_FAILURE;
  2356. break;
  2357. }
  2358. //
  2359. // if we are in bridge mode, then we add the Destination Ip address to
  2360. // the RemoteIP structure.
  2361. //
  2362. if (fBridgeMode && fRemoteIpCreated)
  2363. {
  2364. Status = arpAddIpAddressToRemoteIp (pRemoteIp, pNdisPacket);
  2365. if (FAIL(Status))
  2366. {
  2367. OBJLOG1(
  2368. pIF,
  2369. "Couldn't Add Dest Ip addr to Remote Ip addr 0x%lx\n",
  2370. Destination.IpAddress
  2371. );
  2372. Status = NDIS_STATUS_FAILURE;
  2373. break;
  2374. }
  2375. }
  2376. //
  2377. // If there is a RCE, we make it point to pRemoteIp.
  2378. //
  2379. if (pRCE != NULL)
  2380. {
  2381. // All RCE linkages are protected by the IF send lock.
  2382. //
  2383. ARP_WRITELOCK_IF_SEND_LOCK(pIF, &sr);
  2384. if (pArpRceContext->pRemoteIp != NULL)
  2385. {
  2386. if (pArpRceContext->pRemoteIp != pRemoteIp)
  2387. {
  2388. ARPCB_REMOTE_IP * pStaleRemoteIp;
  2389. //
  2390. // We've got a wierd situation here: initially
  2391. // pRCE didn't point to any pRemoteIp, so we looked up
  2392. // a pRemoteIp ourselves. Now that we've got the IF send
  2393. // lock, we find that pRCE is pointing to a different
  2394. // pRemoteIp than the one we looked up!
  2395. //
  2396. // What to do? We ignore pRemoteIp (the one we looked up)
  2397. // and instead use pArpRceContext->pRemoteIp...
  2398. //
  2399. ASSERTEX(!"RCE pRemoteIp mismatch", pArpRceContext);
  2400. pStaleRemoteIp = pRemoteIp;
  2401. pRemoteIp = pArpRceContext->pRemoteIp;
  2402. RmTmpReferenceObject(&pRemoteIp->Hdr, &sr);
  2403. ARP_UNLOCK_IF_SEND_LOCK(pIF, &sr);
  2404. RM_ASSERT_NOLOCKS(&sr);
  2405. RmTmpDereferenceObject(&pStaleRemoteIp->Hdr, &sr);
  2406. ARP_WRITELOCK_IF_SEND_LOCK(pIF, &sr);
  2407. }
  2408. }
  2409. else
  2410. {
  2411. // Add the association between pRCE and pRemoteIp...
  2412. //
  2413. arpAddRce(pRemoteIp, pRCE, &sr); // LOCKIN LOCKOUT (IF send lk)
  2414. }
  2415. ARP_UNLOCK_IF_SEND_LOCK(pIF, &sr);
  2416. }
  2417. }
  2418. //
  2419. // At this point, we should have a pRemoteIp, with a tmpref on it,
  2420. // and no locks held.
  2421. //
  2422. ASSERT_VALID_REMOTE_IP(pRemoteIp);
  2423. RM_ASSERT_NOLOCKS(&sr);
  2424. //
  2425. // Queue the packet on pRemoteIp's send pkt queue, and start the
  2426. // SendPkts task on this pRemoteIp if required.
  2427. //
  2428. {
  2429. LOCKOBJ(pRemoteIp, &sr);
  2430. // NOTE: This field is not always modified with the lock held -- in
  2431. // the fast send path, it's simply set to true.
  2432. // This field is used in garbage collecting pRemoteIps.
  2433. //
  2434. pRemoteIp->sendinfo.TimeLastChecked = 0;
  2435. //
  2436. // Stats.
  2437. // TODO -- we need to directly deal with "medium sends"
  2438. // instead of starting up a task just because the RCEs are NULL
  2439. // -- mcast and udp pkts have null RCEs, it turns out.
  2440. //
  2441. if ( pRemoteIp->pDest != NULL
  2442. && ARP_CAN_SEND_ON_DEST(pRemoteIp->pDest))
  2443. {
  2444. LOGSTATS_MediumSends(pIF, pNdisPacket);
  2445. }
  2446. else
  2447. {
  2448. LOGSTATS_SlowSends(pIF, pNdisPacket);
  2449. }
  2450. if (pRemoteIp->pSendPktsTask == NULL)
  2451. {
  2452. PRM_TASK pTask;
  2453. // There is no send-pkts task. Let's try to alloc and start one..
  2454. Status = arpAllocateTask(
  2455. &pRemoteIp->Hdr, // pParentObject
  2456. arpTaskSendPktsOnRemoteIp, // pfnHandler
  2457. 0, // Timeout
  2458. "Task: SendPktsOnRemoteIp", // szDescription
  2459. &pTask,
  2460. &sr
  2461. );
  2462. if (FAIL(Status))
  2463. {
  2464. // Oops, couldn't allocate task. We fail with STATUS_RESOURCES
  2465. UNLOCKOBJ(pRemoteIp, &sr);
  2466. Status = NDIS_STATUS_RESOURCES;
  2467. break;
  2468. }
  2469. //
  2470. // Queue the pkt first, THEN start the task. This makes sure that
  2471. // the packet WILL be taken care of.
  2472. // TODO: Currently, it's possible that the RemoteIp's unload
  2473. // task will not wait for send pkts to be cleared up IF it checks
  2474. // BEFORE the task before is started. This hole needs
  2475. // to be fixed.
  2476. //
  2477. arpQueuePktOnRemoteIp(
  2478. pRemoteIp, // LOCKIN LOCKOUT
  2479. pNdisPacket,
  2480. &sr
  2481. );
  2482. UNLOCKOBJ(pRemoteIp, &sr);
  2483. (VOID) RmStartTask( pTask, 0, &sr);
  2484. }
  2485. else
  2486. {
  2487. //
  2488. // There is already a send-pkts task. Simply queue the pkt.
  2489. //
  2490. arpQueuePktOnRemoteIp(
  2491. pRemoteIp, // LOCKIN LOCKOUT
  2492. pNdisPacket,
  2493. &sr
  2494. );
  2495. UNLOCKOBJ(pRemoteIp, &sr);
  2496. }
  2497. // We're done!
  2498. // Remove the tmp reference on pRemoteIp, and set status to PENDING.
  2499. //
  2500. RM_ASSERT_NOLOCKS(&sr);
  2501. RmTmpDereferenceObject(&pRemoteIp->Hdr, &sr);
  2502. Status = NDIS_STATUS_PENDING;
  2503. }
  2504. } while (FALSE);
  2505. RM_ASSERT_CLEAR(&sr)
  2506. EXIT()
  2507. return Status;
  2508. }
  2509. VOID
  2510. arpAddRce(
  2511. IN ARPCB_REMOTE_IP *pRemoteIp, // IF send lock WRITELOCKIN WRITELOCKOUT
  2512. IN RouteCacheEntry *pRce,
  2513. IN PRM_STACK_RECORD pSR
  2514. )
  2515. /*++
  2516. Routine Description:
  2517. Link the RCE pRce with the remote ip object pRemoteIp.
  2518. --*/
  2519. {
  2520. ARP_RCE_CONTEXT * pArpRceContext;
  2521. MYBOOL fDoRef;
  2522. pArpRceContext = ARP_OUR_CTXT_FROM_RCE(pRce);
  2523. fDoRef = (pRemoteIp->sendinfo.pRceList == NULL);
  2524. ASSERT(pArpRceContext->pRemoteIp == NULL);
  2525. // Add pRce to pRemoteIP's list of RCEs.
  2526. //
  2527. pArpRceContext->pNextRce = pRemoteIp->sendinfo.pRceList;
  2528. pRemoteIp->sendinfo.pRceList = pRce;
  2529. // Add pointer from pRce to pRemoteIp
  2530. //
  2531. pArpRceContext->pRemoteIp = pRemoteIp;
  2532. // The following macros are just so that we can make the proper debug association
  2533. // depending on how closely we are tracking outstanding send packets.
  2534. //
  2535. #if ARPDBG_REF_EVERY_RCE
  2536. fDoRef = TRUE;
  2537. #define OUR_EXTERNAL_ENTITY ((UINT_PTR) pRce)
  2538. #define szARPSSOC_EXTLINK_RIP_TO_RCE_FORMAT " Linked to pRce 0x%p\n"
  2539. #else // !ARPDBG_REF_EVERY_RCE
  2540. #define OUR_EXTERNAL_ENTITY ((UINT_PTR) &pRemoteIp->sendinfo)
  2541. #define szARPSSOC_EXTLINK_RIP_TO_RCE_FORMAT " Outstanding RCEs exist. &si=0x%p\n"
  2542. #endif // !ARPDBG_REF_EVERY_RCE
  2543. if (fDoRef)
  2544. {
  2545. //
  2546. // If ARPDBG_REF_EVERY_RCE
  2547. // We add an "external" link for EVERY RCE. We'll later remove this
  2548. // reference when the RCE is invalidated.
  2549. // else
  2550. // Only a transition from zero to non-zero RCEs, we
  2551. // add an "external" link. We'll later remove this link when the
  2552. // transition from non-zero to zero happens.
  2553. //
  2554. #if RM_EXTRA_CHECKING
  2555. RM_DECLARE_STACK_RECORD(sr)
  2556. RmLinkToExternalEx(
  2557. &pRemoteIp->Hdr, // pHdr
  2558. 0x22224c96, // LUID
  2559. OUR_EXTERNAL_ENTITY, // External entity
  2560. ARPASSOC_EXTLINK_RIP_TO_RCE, // AssocID
  2561. szARPSSOC_EXTLINK_RIP_TO_RCE_FORMAT,
  2562. &sr
  2563. );
  2564. #else // !RM_EXTRA_CHECKING
  2565. RmLinkToExternalFast(&pRemoteIp->Hdr);
  2566. #endif // !RM_EXTRA_CHECKING
  2567. }
  2568. #undef OUR_EXTERNAL_ENTITY
  2569. #undef szARPSSOC_EXTLINK_RIP_TO_RCE
  2570. }
  2571. VOID
  2572. arpDelRce(
  2573. IN RouteCacheEntry *pRce, // IF send lock WRITELOCKIN WRITELOCKOUTD
  2574. IN PRM_STACK_RECORD pSR
  2575. )
  2576. /*++
  2577. Routine Description:
  2578. Unlink RCE pRce from remote ip object pRemoteIp.
  2579. --*/
  2580. {
  2581. ARPCB_REMOTE_IP * pRemoteIp;
  2582. ARP_RCE_CONTEXT * pArpRceContext;
  2583. MYBOOL fDoDeref;
  2584. RouteCacheEntry ** ppRce;
  2585. pArpRceContext = ARP_OUR_CTXT_FROM_RCE(pRce);
  2586. pRemoteIp = pArpRceContext->pRemoteIp;
  2587. if (pRemoteIp == NULL)
  2588. {
  2589. // We haven't initialized this RCE yet. Nothing to do...
  2590. //
  2591. return; // EARLY RETURN
  2592. }
  2593. if (VALID_REMOTE_IP(pRemoteIp)== FALSE)
  2594. {
  2595. return;
  2596. }
  2597. // Remove pRce from pRemoteIP's list of RCEs.
  2598. //
  2599. for(
  2600. ppRce = &pRemoteIp->sendinfo.pRceList;
  2601. *ppRce != NULL;
  2602. ppRce = &(ARP_OUR_CTXT_FROM_RCE(*ppRce)->pNextRce))
  2603. {
  2604. if (*ppRce == pRce) break;
  2605. }
  2606. if (*ppRce == pRce)
  2607. {
  2608. *ppRce = pArpRceContext->pNextRce;
  2609. }
  2610. else
  2611. {
  2612. ASSERTEX(!"RCE Not in pRemoteIp's list!", pRce);
  2613. }
  2614. ARP_ZEROSTRUCT(pArpRceContext);
  2615. fDoDeref = (pRemoteIp->sendinfo.pRceList == NULL);
  2616. // The following macros are just so that we can make the proper debug association
  2617. // depending on how closely we are tracking outstanding send packets.
  2618. //
  2619. #if ARPDBG_REF_EVERY_RCE
  2620. fDoDeref = TRUE;
  2621. #define OUR_EXTERNAL_ENTITY ((UINT_PTR) pRce)
  2622. #else // !ARPDBG_REF_EVERY_RCE
  2623. #define OUR_EXTERNAL_ENTITY ((UINT_PTR) &pRemoteIp->sendinfo)
  2624. #endif // !ARPDBG_REF_EVERY_RCE
  2625. if (fDoDeref)
  2626. {
  2627. //
  2628. // If ARPDBG_REF_EVERY_RCE
  2629. // We add an "external" link for EVERY RCE. We'll later remove this
  2630. // reference when the RCE is invalidated.
  2631. // else
  2632. // Only a transition from zero to non-zero RCEs, we
  2633. // add an "external" link. We'll later remove this link when the
  2634. // transition from non-zero to zero happens.
  2635. //
  2636. #if RM_EXTRA_CHECKING
  2637. RM_DECLARE_STACK_RECORD(sr)
  2638. RmUnlinkFromExternalEx(
  2639. &pRemoteIp->Hdr, // pHdr
  2640. 0x940df668, // LUID
  2641. OUR_EXTERNAL_ENTITY, // External entity
  2642. ARPASSOC_EXTLINK_RIP_TO_RCE, // AssocID
  2643. &sr
  2644. );
  2645. #else // !RM_EXTRA_CHECKING
  2646. RmUnlinkFromExternalFast(&pRemoteIp->Hdr);
  2647. #endif // !RM_EXTRA_CHECKING
  2648. }
  2649. #undef OUR_EXTERNAL_ENTITY
  2650. }
  2651. VOID
  2652. arpDelRceList(
  2653. IN PARPCB_REMOTE_IP pRemoteIp, // IF send lock WRITELOCKIN WRITELOCKOUTD
  2654. IN PRM_STACK_RECORD pSR
  2655. )
  2656. /*++
  2657. Routine Description:
  2658. Walks the RCE List, deleting each RoutCache Entry
  2659. --*/
  2660. {
  2661. RouteCacheEntry * pRce = pRemoteIp->sendinfo.pRceList;
  2662. //
  2663. // Delete all the Rce present on this remote Ip
  2664. //
  2665. while (pRce!= NULL)
  2666. {
  2667. //
  2668. // Delete the Rce and reduce the Ref
  2669. //
  2670. arpDelRce (pRce, pSR);
  2671. //
  2672. // Get the next RCE
  2673. //
  2674. pRce = pRemoteIp->sendinfo.pRceList;
  2675. }
  2676. }
  2677. NDIS_STATUS
  2678. arpTaskSendPktsOnRemoteIp(
  2679. IN struct _RM_TASK * pTask,
  2680. IN RM_TASK_OPERATION Code,
  2681. IN UINT_PTR UserParam, // Unused
  2682. IN PRM_STACK_RECORD pSR
  2683. )
  2684. /*++
  2685. Routine Description:
  2686. Task handler responsible for sending queued packets on the pRemoteIp which
  2687. is its parent object. If required it must start the registration task and/or
  2688. the make-call task on the destination object.
  2689. Arguments:
  2690. UserParam for (Code == RM_TASKOP_START) : unused
  2691. --*/
  2692. {
  2693. ENTER("TaskSendPktsOnRemoteIp", 0xbc285d98)
  2694. NDIS_STATUS Status;
  2695. ARPCB_REMOTE_IP* pRemoteIp;
  2696. ARP1394_INTERFACE * pIF;
  2697. ARPCB_DEST * pDest;
  2698. MYBOOL fMakeCallIfRequired;
  2699. PARP1394_ADAPTER pAdapter;
  2700. MYBOOL fBridgeMode;
  2701. // Following are the list of pending states for this task.
  2702. //
  2703. enum
  2704. {
  2705. PEND_AddressResolutionComplete,
  2706. PEND_MakeCallComplete
  2707. };
  2708. Status = NDIS_STATUS_FAILURE;
  2709. pRemoteIp = (ARPCB_REMOTE_IP*) RM_PARENT_OBJECT(pTask);
  2710. pIF = (ARP1394_INTERFACE*) RM_PARENT_OBJECT(pRemoteIp);
  2711. pAdapter = (PARP1394_ADAPTER) RM_PARENT_OBJECT(pIF);
  2712. pDest = NULL;
  2713. fMakeCallIfRequired = FALSE;
  2714. fBridgeMode = ARP_BRIDGE_ENABLED(pAdapter);
  2715. ASSERT_VALID_INTERFACE(pIF);
  2716. ASSERT_VALID_REMOTE_IP(pRemoteIp);
  2717. DBGMARK(0x6f31a739);
  2718. switch(Code)
  2719. {
  2720. case RM_TASKOP_START:
  2721. {
  2722. LOCKOBJ(pRemoteIp, pSR);
  2723. // First check if pRemoteIp is still allocated, if not we go away.
  2724. //
  2725. if (RM_IS_ZOMBIE(pRemoteIp))
  2726. {
  2727. Status = NDIS_STATUS_SUCCESS;
  2728. break;
  2729. }
  2730. // pRemoteIp is allocated. Now check if there is already a
  2731. // send-pkts task attached to pRemoteIp.
  2732. //
  2733. if (pRemoteIp->pSendPktsTask != NULL)
  2734. {
  2735. //
  2736. // There is a sendpkts task. Nothing for us to do -- simply return.
  2737. //
  2738. Status = NDIS_STATUS_SUCCESS;
  2739. break;
  2740. }
  2741. // Now we check if there is an UnloadTask bound to pRemoteIP. This
  2742. // is an IMPORTANT check -- because the unload task expects that
  2743. // once it is bound to pRemoteIp, no new pSendPktsTasks will bind
  2744. // themselves to pRemoteIp -- see arpTaskUnloadRemoteIp.
  2745. //
  2746. if (pRemoteIp->pUnloadTask != NULL)
  2747. {
  2748. Status = NDIS_STATUS_SUCCESS;
  2749. break;
  2750. }
  2751. //
  2752. // There is no sendpkts task going on. Let's
  2753. // make this task THE sendpkts task.
  2754. //
  2755. pRemoteIp->pSendPktsTask = pTask;
  2756. //
  2757. // Since we're THE sendpks task, add an association to pRemoteIp,
  2758. // which will only get cleared when the pRemoteIp->pSendPktsTask field
  2759. // above is cleared.
  2760. //
  2761. DBG_ADDASSOC(
  2762. &pRemoteIp->Hdr, // pObject
  2763. pTask, // Instance1
  2764. pTask->Hdr.szDescription, // Instance2
  2765. ARPASSOC_REMOTEIP_SENDPKTS_TASK, // AssociationID
  2766. " Official sendpkts task 0x%p (%s)\n", // szFormat
  2767. pSR
  2768. );
  2769. if (pRemoteIp->pDest == NULL)
  2770. {
  2771. MYBOOL bIsDestNonUnicastAddr = FALSE;
  2772. //
  2773. // There is no pDest associated with pRemoteIp.
  2774. // If this is an on-unicast address, we link the local ip
  2775. // object to the broadcast object and proceed.
  2776. // NOTE: arpIsNonUnicastIpAddress is not a trivial operation -- it
  2777. // actually enumerates all local IP addresses. Fortunately we only
  2778. // call it for the FIRST packet sent out to an unresolved address.
  2779. //
  2780. if (fBridgeMode)
  2781. {
  2782. bIsDestNonUnicastAddr = arpIsNonUnicastEthAddress (pIF,&pRemoteIp->Key.ENetAddress,pSR);
  2783. }
  2784. else
  2785. {
  2786. ASSERT(IS_REMOTE_DEST_IP_ADDRESS(&pRemoteIp->Key) == TRUE);
  2787. bIsDestNonUnicastAddr = arpIsNonUnicastIpAddress(pIF, pRemoteIp->IpAddress, pSR);
  2788. }
  2789. if (bIsDestNonUnicastAddr == TRUE)
  2790. {
  2791. ASSERT(pIF->pBroadcastDest != NULL); // Don't really expect it.
  2792. if (pIF->pBroadcastDest != NULL)
  2793. {
  2794. //
  2795. // Note: arpLinkRemoteIpToDest expects the locks
  2796. // on both pRemoteIp and pIF->pBroadcastDest to be
  2797. // held. We know that this is the case because both
  2798. // share the same lock, which is the IF lock.
  2799. //
  2800. RM_DBG_ASSERT_LOCKED(&pIF->pBroadcastDest->Hdr, pSR);
  2801. arpLinkRemoteIpToDest(
  2802. pRemoteIp,
  2803. pIF->pBroadcastDest,
  2804. pSR
  2805. );
  2806. SET_REMOTEIP_FCTYPE(pRemoteIp, ARPREMOTEIP_CHANNEL);
  2807. SET_REMOTEIP_SDTYPE(pRemoteIp, ARPREMOTEIP_DYNAMIC);
  2808. #if 0
  2809. if (CHECK_REMOTEIP_MCAP(pRemoteIp, ARPREMOTEIP_MCAP_CAPABLE))
  2810. {
  2811. SET_REMOTEIP_SDTYPE(pRemoteIp, ARPREMOTEIP_DYNAMIC);
  2812. }
  2813. else
  2814. {
  2815. //
  2816. // We don't age out broadcast addresses.
  2817. //
  2818. SET_REMOTEIP_SDTYPE(pRemoteIp, ARPREMOTEIP_STATIC);
  2819. }
  2820. #endif // 0
  2821. }
  2822. }
  2823. }
  2824. //
  2825. // If there is a resolution task going, we wait for it to complete.
  2826. //
  2827. if (pRemoteIp->pResolutionTask != NULL)
  2828. {
  2829. PRM_TASK pOtherTask = pRemoteIp->pResolutionTask;
  2830. TR_WARN(("Resolution task %p exists; pending on it.\n", pOtherTask));
  2831. RmTmpReferenceObject(&pOtherTask->Hdr, pSR);
  2832. UNLOCKOBJ(pRemoteIp, pSR);
  2833. RmPendTaskOnOtherTask(
  2834. pTask,
  2835. PEND_AddressResolutionComplete,
  2836. pOtherTask,
  2837. pSR
  2838. );
  2839. RmTmpDereferenceObject(&pOtherTask->Hdr, pSR);
  2840. Status = NDIS_STATUS_PENDING;
  2841. break;
  2842. }
  2843. //
  2844. // There is no address resolution task. Let's see if the
  2845. // address has been resolved. If not, we need to start the address
  2846. // resolution task.
  2847. //
  2848. if (pRemoteIp->pDest == NULL)
  2849. {
  2850. //
  2851. // Let's start the address resolution task!
  2852. //
  2853. PRM_TASK pResolutionTask;
  2854. DBGMARK(0xd0da6726);
  2855. //
  2856. // Let's start a resolution task and pend on it.
  2857. //
  2858. Status = arpAllocateTask(
  2859. &pRemoteIp->Hdr, // pParentObject
  2860. arpTaskResolveIpAddress, // pfnHandler
  2861. 0, // Timeout
  2862. "Task: ResolveIpAddress", // szDescription
  2863. &pResolutionTask,
  2864. pSR
  2865. );
  2866. if (FAIL(Status))
  2867. {
  2868. // Couldn't allocate task. We fail with STATUS_RESOURCES
  2869. //
  2870. Status = NDIS_STATUS_RESOURCES;
  2871. }
  2872. else
  2873. {
  2874. UNLOCKOBJ(pRemoteIp, pSR);
  2875. RmPendTaskOnOtherTask(
  2876. pTask,
  2877. PEND_AddressResolutionComplete,
  2878. pResolutionTask,
  2879. pSR
  2880. );
  2881. (VOID)RmStartTask(
  2882. pResolutionTask,
  2883. 0, // UserParam unused
  2884. pSR
  2885. );
  2886. Status = NDIS_STATUS_PENDING;
  2887. }
  2888. break;
  2889. }
  2890. pDest = pRemoteIp->pDest;
  2891. //
  2892. // We do have a pDest. Now see if there is a make call task on that
  2893. // pDest, and if so, we pend on it.
  2894. fMakeCallIfRequired = TRUE;
  2895. //
  2896. // We're here because there is no more async work to be done.
  2897. // We simply return and finish synchronous work in the END
  2898. // handler for this task.
  2899. //
  2900. } // START
  2901. break;
  2902. case RM_TASKOP_PENDCOMPLETE:
  2903. {
  2904. switch(RM_PEND_CODE(pTask))
  2905. {
  2906. case PEND_AddressResolutionComplete:
  2907. {
  2908. //
  2909. // There was address-resolution going on, but how it's
  2910. // complete. We should be go on to try to make a call now...
  2911. //
  2912. // If we're here, that means we're THE official SendPkts
  2913. // task. Let's assert that fact.
  2914. // (no need to get the lock on the object).
  2915. //
  2916. LOCKOBJ(pRemoteIp, pSR);
  2917. ASSERT(pRemoteIp->pSendPktsTask == pTask);
  2918. // We ignore the status of address resolution -- instead
  2919. // we just check if there is a destination associated with
  2920. // pRemoteIp.
  2921. //
  2922. pDest = pRemoteIp->pDest;
  2923. if (pDest == NULL)
  2924. {
  2925. // Nope -- no pDest. We fail the packets.
  2926. Status = NDIS_STATUS_FAILURE;
  2927. }
  2928. else
  2929. {
  2930. // Yup, there is a destination. Now check if we need
  2931. // to make a call, etc...
  2932. //
  2933. fMakeCallIfRequired = TRUE;
  2934. }
  2935. }
  2936. break;
  2937. case PEND_MakeCallComplete:
  2938. {
  2939. LOCKOBJ(pRemoteIp, pSR);
  2940. //
  2941. // If we're here, that means we're THE official SendPkts
  2942. // task. Let's assert that fact.
  2943. // (no need to get the lock on the object).
  2944. //
  2945. ASSERT(pRemoteIp->pSendPktsTask == pTask);
  2946. //
  2947. // There was a make-call task going on, but how it's
  2948. // complete. We're done with async processing.
  2949. // We actually send/fail queued packets in our END handler...
  2950. //
  2951. Status = (NDIS_STATUS) UserParam;
  2952. ASSERT(!PEND(Status));
  2953. }
  2954. break;
  2955. default:
  2956. {
  2957. ASSERTEX(!"Unknown pend op", pTask);
  2958. }
  2959. break;
  2960. } // end switch(RM_PEND_CODE(pTask))
  2961. } // case RM_TASKOP_PENDCOMPLETE
  2962. break;
  2963. case RM_TASKOP_END:
  2964. {
  2965. LOCKOBJ(pRemoteIp, pSR);
  2966. //
  2967. // We're done. There should be no async activities left to do.
  2968. // At this point, if we can't immediately send packets on the FIFO,
  2969. // we simply fail all the packets.
  2970. //
  2971. //
  2972. // We don't bother to look at the Status. Instead we go ahead and
  2973. // try to send any queued packets.
  2974. //
  2975. //
  2976. // If we're THE sentpkts task, we go on actually send the packets.
  2977. //
  2978. if (pRemoteIp->pSendPktsTask == pTask)
  2979. {
  2980. DBGMARK(0xc627713c);
  2981. UNLOCKOBJ(pRemoteIp, pSR);
  2982. arpSendPktsQueuedOnRemoteIp(
  2983. pIF,
  2984. pRemoteIp,
  2985. pSR
  2986. );
  2987. LOCKOBJ(pRemoteIp, pSR);
  2988. // Delete the association we added when we set
  2989. // pRemoteIp->pSendPktsTask to pTask.
  2990. //
  2991. ASSERT(pRemoteIp->pSendPktsTask == pTask);
  2992. DBG_DELASSOC(
  2993. &pRemoteIp->Hdr, // pObject
  2994. pTask, // Instance1
  2995. pTask->Hdr.szDescription, // Instance2
  2996. ARPASSOC_REMOTEIP_SENDPKTS_TASK, // AssociationID
  2997. pSR
  2998. );
  2999. pRemoteIp->pSendPktsTask = NULL;
  3000. Status = NDIS_STATUS_SUCCESS;
  3001. }
  3002. else
  3003. {
  3004. //
  3005. // We weren't THE unload task, nothing left to do.
  3006. //
  3007. Status = NDIS_STATUS_SUCCESS;
  3008. }
  3009. }
  3010. break; // RM_TASKOP_END:
  3011. default:
  3012. {
  3013. ASSERTEX(!"Unexpected task op", pTask);
  3014. }
  3015. break;
  3016. } // switch (Code)
  3017. if (fMakeCallIfRequired)
  3018. {
  3019. //
  3020. // If necessary, make a call. If a make-call is already in process, pend
  3021. // on it.
  3022. //
  3023. // We rely on the fact that
  3024. // we share the same lock as pDest, and therefore is locked...
  3025. //
  3026. RM_DBG_ASSERT_LOCKED(&pDest->Hdr, pSR);
  3027. Status = arpMakeCallOnDest(pRemoteIp,
  3028. pDest,
  3029. pTask,
  3030. PEND_MakeCallComplete,
  3031. pSR);
  3032. }
  3033. RmUnlockAll(pSR);
  3034. EXIT()
  3035. return Status;
  3036. }
  3037. VOID
  3038. arpCompleteSentPkt(
  3039. IN NDIS_STATUS Status,
  3040. IN ARP1394_INTERFACE * pIF,
  3041. IN ARPCB_DEST * pDest,
  3042. IN PNDIS_PACKET pNdisPacket
  3043. )
  3044. /*++
  3045. Routine Description:
  3046. Handle the completion (by the miniport) of a packet sent on a FIFO or Channel VC.
  3047. We strip out the encapsulation header we had tacked on prior to sending the
  3048. packet. If the packet belongs to IP, we call IP's send complete handler, else
  3049. we return it to our packet pool.
  3050. Arguments:
  3051. Status - Status of the completed send.
  3052. pIF - Interface object
  3053. pDest - Destination object on which packet was sent
  3054. pNdisPacket - Ndis packet that was sent.
  3055. --*/
  3056. {
  3057. PacketContext *PC; // IP/ARP Info about this packet
  3058. PNDIS_BUFFER pNdisBuffer; // First Buffer in this packet
  3059. ENTER("CompleteSentPkt", 0xc2b623b6)
  3060. UINT TotalLength;
  3061. MYBOOL IsFifo;
  3062. MYBOOL IsControlPacket;
  3063. ASSERT(pNdisPacket->Private.Head != NULL);
  3064. NdisQueryPacket(
  3065. pNdisPacket,
  3066. NULL, // we don't need PhysicalBufferCount
  3067. NULL, // we don't need BufferCount
  3068. NULL, // we don't need FirstBuffer (yet)
  3069. &TotalLength
  3070. );
  3071. IsFifo = pDest->sendinfo.IsFifo;
  3072. // Update stats...
  3073. //
  3074. {
  3075. if (IsFifo)
  3076. {
  3077. LOGSTATS_SendFifoCounts(pIF, pNdisPacket, Status);
  3078. }
  3079. else
  3080. {
  3081. LOGSTATS_SendChannelCounts(pIF, pNdisPacket, Status);
  3082. }
  3083. if (Status == NDIS_STATUS_SUCCESS)
  3084. {
  3085. ARP_IF_STAT_ADD(pIF, OutOctets, TotalLength);
  3086. if (IsFifo)
  3087. {
  3088. ARP_IF_STAT_INCR(pIF, OutUnicastPkts);
  3089. }
  3090. else
  3091. {
  3092. ARP_IF_STAT_INCR(pIF, OutNonUnicastPkts);
  3093. }
  3094. }
  3095. else if (Status == NDIS_STATUS_RESOURCES)
  3096. {
  3097. ARP_IF_STAT_INCR(pIF, OutDiscards);
  3098. }
  3099. else
  3100. {
  3101. ARP_IF_STAT_INCR(pIF, OutErrors);
  3102. }
  3103. }
  3104. PC = (PacketContext *)pNdisPacket->ProtocolReserved;
  3105. TR_INFO(
  3106. ("[%s]: pDest 0x%x, Pkt 0x%x, Status 0x%x:\n",
  3107. ((PC->pc_common.pc_owner != PACKET_OWNER_LINK)? "IP": "ARP"),
  3108. pDest, pNdisPacket, Status));
  3109. NdisQueryPacket(pNdisPacket, NULL, NULL, &pNdisBuffer, NULL);
  3110. ASSERT(pNdisBuffer != NULL);
  3111. // Delete association added when sending packets.
  3112. //
  3113. {
  3114. MYBOOL DoDeref;
  3115. DoDeref =(InterlockedDecrement(&pDest->sendinfo.NumOutstandingSends)==0);
  3116. if (DoDeref)
  3117. {
  3118. MYBOOL TryResumeSuspendedCleanupTask = FALSE;
  3119. // The count of outstanding sends has touched zero. Let's
  3120. // check if there is a CleanupCall task waiting for all outstanding
  3121. // sends to complete, and if it makes sense to do so, we
  3122. // will resume it.
  3123. //
  3124. ARP_FASTREADLOCK_IF_SEND_LOCK(pIF);
  3125. if (pDest->sendinfo.pSuspendedCleanupCallTask!=NULL)
  3126. {
  3127. // It's likely that we'll need to resume this task.
  3128. //
  3129. TryResumeSuspendedCleanupTask = TRUE;
  3130. }
  3131. else
  3132. {
  3133. // We do not need to resume any task. Nothing more to do...
  3134. //
  3135. }
  3136. ARP_FASTUNLOCK_IF_SEND_LOCK(pIF);
  3137. if (TryResumeSuspendedCleanupTask)
  3138. {
  3139. arpTryResumeSuspendedCleanupTask(pIF, pDest);
  3140. }
  3141. }
  3142. // The following macros are just so that we can make the proper debug
  3143. // association depending on how closely we are tracking outstanding send
  3144. // packets.
  3145. //
  3146. #if ARPDBG_REF_EVERY_PACKET
  3147. DoDeref = TRUE;
  3148. #define OUR_EXTERNAL_ENTITY ((UINT_PTR) pNdisPacket)
  3149. #else // !ARPDBG_REF_EVERY_PACKET
  3150. #define OUR_EXTERNAL_ENTITY ((UINT_PTR) &pDest->sendinfo)
  3151. #endif // !ARPDBG_REF_EVERY_PACKET
  3152. if (DoDeref)
  3153. {
  3154. //
  3155. // If ARPDBG_REF_EVERY_PKT
  3156. // We remove the "external" link added for EVERY packet.
  3157. // else
  3158. // Only a transition from non-zero to zero outstanding sends, we
  3159. // remove the "external" link.
  3160. //
  3161. #if RM_EXTRA_CHECKING
  3162. RM_DECLARE_STACK_RECORD(sr)
  3163. RmUnlinkFromExternalEx(
  3164. &pDest->Hdr, // pHdr
  3165. 0x753db96f, // LUID
  3166. OUR_EXTERNAL_ENTITY, // External entity
  3167. ARPASSOC_EXTLINK_DEST_TO_PKT, // AssocID
  3168. &sr
  3169. );
  3170. #else // !RM_EXTRA_CHECKING
  3171. RmUnlinkFromExternalFast(&pDest->Hdr);
  3172. #endif // !RM_EXTRA_CHECKING
  3173. }
  3174. #undef OUR_EXTERNAL_ENTITY
  3175. }
  3176. //
  3177. // Check who generated this packet.
  3178. //
  3179. IsControlPacket = FALSE;
  3180. if (PC->pc_common.pc_owner == PACKET_OWNER_LINK)
  3181. {
  3182. IsControlPacket = TRUE;
  3183. }
  3184. if (IsControlPacket)
  3185. {
  3186. arpHandleControlPktSendCompletion(pIF, pNdisPacket);
  3187. }
  3188. else
  3189. {
  3190. //
  3191. // Belongs to IP.
  3192. //
  3193. DBGMARK(0x2c48c626);
  3194. //
  3195. // Now check if we had attached a header buffer or not.
  3196. // NOTE: We rely on the fact that if we DID attach a header buffer,
  3197. // ARP_BACK_FILL_POSSIBLE will be false for this buffer.
  3198. //
  3199. DBGMARK(0x2f3b96f3);
  3200. if (ARP_BACK_FILL_POSSIBLE(pNdisBuffer))
  3201. {
  3202. const UINT HeaderLength = sizeof(Arp1394_IpEncapHeader);
  3203. //
  3204. // We would have back-filled IP's buffer with the Ip encapsulation
  3205. // header.
  3206. // Remove the back-fill.
  3207. //
  3208. (PUCHAR)pNdisBuffer->MappedSystemVa += HeaderLength;
  3209. pNdisBuffer->ByteOffset += HeaderLength;
  3210. pNdisBuffer->ByteCount -= HeaderLength;
  3211. }
  3212. else if (Status != NDIS_STATUS_NOT_RESETTABLE)
  3213. {
  3214. //
  3215. // The first buffer is our header buffer. Remove
  3216. // it from the packet and return to our pool.
  3217. //
  3218. NdisUnchainBufferAtFront(pNdisPacket, &pNdisBuffer);
  3219. arpDeallocateConstBuffer(
  3220. &pIF->sendinfo.HeaderPool,
  3221. pNdisBuffer
  3222. );
  3223. }
  3224. // Inform IP of send completion.
  3225. // NOTE: we don't get here in bridge mode because we only use
  3226. // control packets in bridge mode.
  3227. //
  3228. #if MILLEN
  3229. ASSERT_PASSIVE();
  3230. #endif // MILLEN
  3231. (*(pIF->ip.TxCmpltHandler))(
  3232. pIF->ip.Context,
  3233. pNdisPacket,
  3234. Status
  3235. );
  3236. }
  3237. EXIT()
  3238. }
  3239. VOID
  3240. arpTryResumeSuspendedCleanupTask(
  3241. IN ARP1394_INTERFACE * pIF, // NOLOCKIN NOLOCKOUT
  3242. IN ARPCB_DEST * pDest // NOLOCKIN NOLOCKOUT
  3243. )
  3244. /*++
  3245. Routine Description:
  3246. If there is a cleanup task associated with destination oject pDest that
  3247. is suspended waiting for the outstanding send count to go to zero, AND
  3248. if the outstanding send count has gone to zero, we resume the task. Otherwise
  3249. we do nothing.
  3250. Arguments:
  3251. pIF - Interface object
  3252. pDest - Destination object.
  3253. --*/
  3254. {
  3255. PRM_TASK pTask;
  3256. ENTER("TryResumeSuspendedCleanupTask", 0x1eccb1aa)
  3257. RM_DECLARE_STACK_RECORD(sr)
  3258. ARP_WRITELOCK_IF_SEND_LOCK(pIF, &sr);
  3259. pTask = pDest->sendinfo.pSuspendedCleanupCallTask;
  3260. if (pTask != NULL)
  3261. {
  3262. ASSERT(!ARP_CAN_SEND_ON_DEST(pDest));
  3263. if (pDest->sendinfo.NumOutstandingSends==0)
  3264. {
  3265. // We need to resume this task...
  3266. //
  3267. pDest->sendinfo.pSuspendedCleanupCallTask = NULL;
  3268. // Clear the association added when pTask started waiting for
  3269. // outstanding sends to complete.
  3270. //
  3271. DBG_DELASSOC(
  3272. &pDest->Hdr, // pObject
  3273. pTask, // Instance1
  3274. pTask->Hdr.szDescription, // Instance2
  3275. ARPASSOC_DEST_CLEANUPCALLTASK_WAITING_ON_SENDS,
  3276. &sr
  3277. );
  3278. RmTmpReferenceObject(&pTask->Hdr, &sr);
  3279. }
  3280. else
  3281. {
  3282. // There are other outstanding sends now. No need to do anything...
  3283. //
  3284. pTask = NULL;
  3285. }
  3286. }
  3287. ARP_UNLOCK_IF_SEND_LOCK(pIF, &sr);
  3288. if (pTask != NULL)
  3289. {
  3290. // Resume the CleanupCall task...
  3291. //
  3292. RmResumeTask(pTask, NDIS_STATUS_SUCCESS, &sr);
  3293. RmTmpDereferenceObject(&pTask->Hdr, &sr);
  3294. }
  3295. RM_ASSERT_CLEAR(&sr);
  3296. EXIT()
  3297. }
  3298. VOID
  3299. arpQueuePktOnRemoteIp(
  3300. IN PARPCB_REMOTE_IP pRemoteIp, // LOCKIN LOCKOUT
  3301. IN PNDIS_PACKET pNdisPacket,
  3302. IN PRM_STACK_RECORD pSR
  3303. )
  3304. /*++
  3305. Routine Description:
  3306. Appends pkt pNdisPacket on remote object pRemoteIp's queue.
  3307. --*/
  3308. {
  3309. ARP_SEND_PKT_MPR_INFO *pOurPktInfo =
  3310. ARP_OUR_CTXT_FROM_SEND_PACKET(pNdisPacket);
  3311. RM_DBG_ASSERT_LOCKED(&pRemoteIp->Hdr, pSR);
  3312. #if RM_EXTRA_CHECKING
  3313. {
  3314. //
  3315. // If ARPDBG_REF_EVERY_PKT
  3316. // We add an dbgassociation for EVERY packet. We'll later remove
  3317. // this association when the send completes for this packet.
  3318. // else
  3319. // Only a transition from zero to non-zero queued pkts, we
  3320. // add an dbg association. We'll later remove this association when
  3321. // the transition from non-zero to zero happens.
  3322. //
  3323. MYBOOL DoAssoc;
  3324. #if ARPDBG_REF_EVERY_PACKET
  3325. DoAssoc = TRUE;
  3326. #define OUR_EXTERNAL_ENTITY ((UINT_PTR) pNdisPacket)
  3327. #define szARPSSOC_QUEUED_PKT_FORMAT " Queued pkt 0x%p\n"
  3328. #else // !ARPDBG_REF_EVERY_PACKET
  3329. #define OUR_EXTERNAL_ENTITY ((UINT_PTR) &pDest->)
  3330. #define szARPSSOC_QUEUED_PKT_FORMAT " Outstanding pkts. &si=0x%p\n"
  3331. DoAssoc = IsListEmpty(&pRemoteIp->sendinfo.listSendPkts);
  3332. #endif // !ARPDBG_REF_EVERY_PACKET
  3333. if (DoAssoc)
  3334. {
  3335. RM_DECLARE_STACK_RECORD(sr)
  3336. RmDbgAddAssociation(
  3337. 0x3c08a7f5, // LOCID
  3338. &pRemoteIp->Hdr, // pHdr
  3339. (UINT_PTR) OUR_EXTERNAL_ENTITY, // Entity1
  3340. 0, // Entity2
  3341. ARPASSOC_PKTS_QUEUED_ON_REMOTEIP, // AssocID
  3342. szARPSSOC_QUEUED_PKT_FORMAT,
  3343. &sr
  3344. );
  3345. }
  3346. #undef OUR_EXTERNAL_ENTITY
  3347. #undef szARPSSOC_EXTLINK_DEST_TO_PKT_FORMAT
  3348. }
  3349. #endif // !RM_EXTRA_CHECKING
  3350. DBGMARK(0x007a0585);
  3351. InsertHeadList(
  3352. &pRemoteIp->sendinfo.listSendPkts,
  3353. &pOurPktInfo->linkQueue
  3354. );
  3355. }
  3356. VOID
  3357. arpSendPktsQueuedOnRemoteIp(
  3358. IN ARP1394_INTERFACE * pIF, // NOLOCKIN NOLOCKOUT
  3359. IN ARPCB_REMOTE_IP * pRemoteIp, // NOLOCKIN NOLOCKOUT
  3360. IN PRM_STACK_RECORD pSR
  3361. )
  3362. /*++
  3363. Routine Description:
  3364. Send all packets queued on remote ip object pRemoteIp. If packets can't
  3365. be sent at this time for any reason, fail the sends.
  3366. ASSUMPTION: We expect pIF and pRemoteIp to be around while we're in this
  3367. function.
  3368. --*/
  3369. {
  3370. ENTER("SendPktsQueuedOnRemoteIp", 0x2b125d7f)
  3371. RM_ASSERT_NOLOCKS(pSR);
  3372. LOCKOBJ(pRemoteIp, pSR);
  3373. DBGMARK(0xe4950c47);
  3374. do
  3375. {
  3376. PARPCB_DEST pDest = NULL;
  3377. if(RM_IS_ZOMBIE(pRemoteIp))
  3378. {
  3379. break;
  3380. }
  3381. pDest = pRemoteIp->pDest;
  3382. if (pDest != NULL)
  3383. {
  3384. RmTmpReferenceObject(&pDest->Hdr, pSR);
  3385. }
  3386. //
  3387. // Send or fail all packets in our queue.
  3388. // TODO: Implement send multiple pkts.
  3389. //
  3390. while (!IsListEmpty(&pRemoteIp->sendinfo.listSendPkts))
  3391. {
  3392. PLIST_ENTRY plinkPkt;
  3393. PNDIS_PACKET pNdisPacket;
  3394. ARP_SEND_PKT_MPR_INFO * pOurPktCtxt;
  3395. //
  3396. // Extract pkt from tail and send it on it's merry way...
  3397. //
  3398. plinkPkt = RemoveTailList(&pRemoteIp->sendinfo.listSendPkts);
  3399. // From link to our pkt context...
  3400. //
  3401. pOurPktCtxt = CONTAINING_RECORD(
  3402. plinkPkt,
  3403. ARP_SEND_PKT_MPR_INFO,
  3404. linkQueue
  3405. );
  3406. // From our pkt context to the ndis pkt.
  3407. //
  3408. pNdisPacket = ARP_SEND_PKT_FROM_OUR_CTXT(pOurPktCtxt);
  3409. #if RM_EXTRA_CHECKING
  3410. {
  3411. //
  3412. // If ARPDBG_REF_EVERY_PKT
  3413. // We delete thhe dbgassociation added for EVERY packet.
  3414. // else
  3415. // Only a transition from non-zero zero queued pkts, we
  3416. // delete the dbg association added when the
  3417. // transition from zero to non-zero happened.
  3418. //
  3419. MYBOOL DoDelAssoc;
  3420. #if ARPDBG_REF_EVERY_PACKET
  3421. DoDelAssoc = TRUE;
  3422. #define OUR_EXTERNAL_ENTITY ((UINT_PTR) pNdisPacket)
  3423. #else // !ARPDBG_REF_EVERY_PACKET
  3424. #define OUR_EXTERNAL_ENTITY ((UINT_PTR) &pDest->)
  3425. DoDelAssoc = IsListEmpty(&pRemoteIp->sendinfo.listSendPkts);
  3426. #endif // !ARPDBG_REF_EVERY_PACKET
  3427. if (DoDelAssoc)
  3428. {
  3429. RM_DECLARE_STACK_RECORD(sr)
  3430. RmDbgDeleteAssociation(
  3431. 0x3c08a7f5, // LOCID
  3432. &pRemoteIp->Hdr, // pHdr
  3433. (UINT_PTR) OUR_EXTERNAL_ENTITY, // Entity1
  3434. 0, // Entity2
  3435. ARPASSOC_PKTS_QUEUED_ON_REMOTEIP, // AssocID
  3436. &sr
  3437. );
  3438. }
  3439. #undef OUR_EXTERNAL_ENTITY
  3440. }
  3441. #endif // !RM_EXTRA_CHECKING
  3442. UNLOCKOBJ(pRemoteIp, pSR);
  3443. RM_ASSERT_NOLOCKS(pSR);
  3444. if (pDest == NULL
  3445. || ( g_DiscardNonUnicastPackets
  3446. && CHECK_REMOTEIP_FCTYPE( pRemoteIp, ARPREMOTEIP_CHANNEL)))
  3447. {
  3448. ARP1394_ADAPTER * pAdapter =
  3449. (ARP1394_ADAPTER*) RM_PARENT_OBJECT(pIF);
  3450. MYBOOL fBridgeMode = ARP_BRIDGE_ENABLED(pAdapter);
  3451. // Fail the packet right here...
  3452. //
  3453. // TODO: we current update the SendFifoCounts here, because
  3454. // all non-unicast bcasts resolve to the already existing
  3455. // broadcast channel. Once we have MCAP going, we need to keep
  3456. // a flag in pRemoteIp indicating whether or not this is a
  3457. // unicast address.
  3458. //
  3459. LOGSTATS_SendFifoCounts(pIF, pNdisPacket, NDIS_STATUS_FAILURE);
  3460. if (fBridgeMode)
  3461. {
  3462. // In bridge (ethernet emulation) mode, we created the
  3463. // packets ourselves, so we delete them here, instead
  3464. // of calling Ip's completion handler, which in fact
  3465. // is NULL.
  3466. //
  3467. arpFreeControlPacket(
  3468. pIF,
  3469. pNdisPacket,
  3470. pSR
  3471. );
  3472. }
  3473. else
  3474. {
  3475. #if MILLEN
  3476. ASSERT_PASSIVE();
  3477. #endif // MILLEN
  3478. NdisInterlockedIncrement (&ArpSendCompletes);
  3479. NdisInterlockedIncrement (&ArpSendFailure);
  3480. (*(pIF->ip.TxCmpltHandler))(
  3481. pIF->ip.Context,
  3482. pNdisPacket,
  3483. NDIS_STATUS_FAILURE
  3484. );
  3485. }
  3486. }
  3487. else
  3488. {
  3489. // Get IF send lock (fast version)
  3490. //
  3491. ARP_FASTREADLOCK_IF_SEND_LOCK(pIF);
  3492. arpSendIpPkt(
  3493. pIF, // IF send lock: LOCKING NOLOCKOUT
  3494. pDest,
  3495. pNdisPacket
  3496. );
  3497. // Note that we're locking pRemoteIp's lock, not the IF send lock
  3498. // here. pRemoteIp->sendinfo.listSendPkts is protected by the
  3499. // the following lock, not the IF send lock.
  3500. //
  3501. }
  3502. LOCKOBJ(pRemoteIp, pSR);
  3503. }
  3504. if (pDest != NULL)
  3505. {
  3506. RmTmpDereferenceObject(&pDest->Hdr, pSR);
  3507. }
  3508. } while (FALSE);
  3509. UNLOCKOBJ(pRemoteIp, pSR);
  3510. RM_ASSERT_NOLOCKS(pSR);
  3511. EXIT()
  3512. }
  3513. VOID
  3514. arpLogSendFifoCounts(
  3515. IN PARP1394_INTERFACE pIF, // NOLOCKIN NOLOCKOUT
  3516. IN PNDIS_PACKET pNdisPacket,
  3517. IN NDIS_STATUS Status
  3518. )
  3519. /*++
  3520. TODO: Very similar to arpLogSendChannelCounts, consider merging these two
  3521. functions.
  3522. --*/
  3523. {
  3524. PULONG pCount;
  3525. ULONG SizeBin, TimeBin;
  3526. arpGetPktCountBins(pIF, pNdisPacket, &SizeBin, &TimeBin);
  3527. //
  3528. // Increment the count
  3529. if (Status == NDIS_STATUS_SUCCESS)
  3530. {
  3531. pCount = &(pIF->stats.sendpkts.SendFifoCounts.GoodCounts[SizeBin][TimeBin]);
  3532. }
  3533. else
  3534. {
  3535. pCount = &(pIF->stats.sendpkts.SendFifoCounts.BadCounts[SizeBin][TimeBin]);
  3536. }
  3537. NdisInterlockedIncrement(pCount);
  3538. }
  3539. VOID
  3540. arpLogRecvFifoCounts(
  3541. IN PARP1394_INTERFACE pIF, // NOLOCKIN NOLOCKOUT
  3542. IN PNDIS_PACKET pNdisPacket
  3543. )
  3544. {
  3545. PULONG pCount;
  3546. ULONG SizeBin;
  3547. arpGetPktCountBins(pIF, pNdisPacket, &SizeBin, NULL);
  3548. //
  3549. // Increment the count
  3550. pCount = &(pIF->stats.recvpkts.RecvFifoCounts.GoodCounts[SizeBin][0]);
  3551. NdisInterlockedIncrement(pCount);
  3552. }
  3553. VOID
  3554. arpLogSendChannelCounts(
  3555. IN PARP1394_INTERFACE pIF, // NOLOCKIN NOLOCKOUT
  3556. IN PNDIS_PACKET pNdisPacket,
  3557. IN NDIS_STATUS Status
  3558. )
  3559. {
  3560. PULONG pCount;
  3561. ULONG SizeBin, TimeBin;
  3562. arpGetPktCountBins(pIF, pNdisPacket, &SizeBin, &TimeBin);
  3563. //
  3564. // Increment the count
  3565. if (Status == NDIS_STATUS_SUCCESS)
  3566. {
  3567. pCount =&(pIF->stats.sendpkts.SendChannelCounts.GoodCounts[SizeBin][TimeBin]);
  3568. }
  3569. else
  3570. {
  3571. pCount =&(pIF->stats.sendpkts.SendChannelCounts.BadCounts[SizeBin][TimeBin]);
  3572. }
  3573. NdisInterlockedIncrement(pCount);
  3574. }
  3575. VOID
  3576. arpLogRecvChannelCounts(
  3577. IN PARP1394_INTERFACE pIF, // NOLOCKIN NOLOCKOUT
  3578. IN PNDIS_PACKET pNdisPacket
  3579. )
  3580. {
  3581. PULONG pCount;
  3582. ULONG SizeBin;
  3583. arpGetPktCountBins(pIF, pNdisPacket, &SizeBin, NULL);
  3584. //
  3585. // Increment the count
  3586. pCount = &(pIF->stats.recvpkts.RecvChannelCounts.GoodCounts[SizeBin][0]);
  3587. NdisInterlockedIncrement(pCount);
  3588. }
  3589. VOID
  3590. arpGetPktCountBins(
  3591. IN PARP1394_INTERFACE pIF, // NOLOCKIN NOLOCKOUT
  3592. IN PNDIS_PACKET pNdisPacket,
  3593. OUT PULONG pSizeBin,
  3594. OUT PULONG pTimeBin // OPTIONAL
  3595. )
  3596. {
  3597. ULONG Size;
  3598. ULONG SizeBin;
  3599. if (pTimeBin != NULL)
  3600. {
  3601. //
  3602. // Compute the packet send duration
  3603. //
  3604. ULONG StartSendTick, EndSendTick;
  3605. LARGE_INTEGER liTemp;
  3606. ULONG TimeDelta;
  3607. ULONG TimeBin;
  3608. liTemp = KeQueryPerformanceCounter(NULL);
  3609. EndSendTick = liTemp.LowPart;
  3610. StartSendTick = *(PULONG) ((pNdisPacket)->WrapperReservedEx);
  3611. if (EndSendTick > StartSendTick)
  3612. {
  3613. TimeDelta = EndSendTick - StartSendTick;
  3614. }
  3615. else
  3616. {
  3617. TimeDelta = (ULONG) (((ULONG) -1) - (StartSendTick - EndSendTick));
  3618. }
  3619. // Convert from ticks to microseconds.
  3620. // (Check that the frequence is non zero -- we could be in the middle
  3621. // of a stats-reset, and don't want to cause a devide-by-zero exception).
  3622. //
  3623. liTemp = pIF->stats.PerformanceFrequency;
  3624. if (liTemp.QuadPart != 0)
  3625. {
  3626. ULONGLONG ll;
  3627. ll = TimeDelta;
  3628. ll *= 1000000;
  3629. ll /= liTemp.QuadPart;
  3630. ASSERT(ll == (ULONG)ll);
  3631. TimeDelta = (ULONG) ll;
  3632. }
  3633. else
  3634. {
  3635. TimeDelta = 0; // bogus value.
  3636. }
  3637. //
  3638. // Compute the time bin based on the send duration
  3639. //
  3640. if (TimeDelta <= 100)
  3641. {
  3642. TimeBin = ARP1394_PKTTIME_100US;
  3643. }
  3644. else if (TimeDelta <= 1000)
  3645. {
  3646. TimeBin = ARP1394_PKTTIME_1MS;
  3647. }
  3648. else if (TimeDelta <= 10000)
  3649. {
  3650. TimeBin = ARP1394_PKTTIME_10MS;
  3651. }
  3652. else if (TimeDelta <= 100000)
  3653. {
  3654. TimeBin = ARP1394_PKTTIME_100MS;
  3655. }
  3656. else // (TimeDelta > 100000)
  3657. {
  3658. TimeBin = ARP1394_PKTTIME_G100MS;
  3659. }
  3660. *pTimeBin = TimeBin;
  3661. }
  3662. //
  3663. // Compute the packet size
  3664. NdisQueryPacket(
  3665. pNdisPacket,
  3666. NULL,
  3667. NULL,
  3668. NULL,
  3669. &Size
  3670. );
  3671. //
  3672. // Compute the size bin based on the packet size
  3673. if (Size <= 128)
  3674. {
  3675. SizeBin = ARP1394_PKTSIZE_128;
  3676. }
  3677. else if (Size <= 256)
  3678. {
  3679. SizeBin = ARP1394_PKTSIZE_256;
  3680. }
  3681. else if (Size <= 1024)
  3682. {
  3683. SizeBin = ARP1394_PKTSIZE_1K;
  3684. }
  3685. else if (Size <= 2048)
  3686. {
  3687. SizeBin = ARP1394_PKTSIZE_2K;
  3688. }
  3689. else // Size > 2048
  3690. {
  3691. SizeBin = ARP1394_PKTSIZE_G2K;
  3692. }
  3693. *pSizeBin = SizeBin;
  3694. }
  3695. // This table is used in the calculations to determine if a particular address is
  3696. // non-unicast.
  3697. // TODO: Make this and all other static data into const.
  3698. //
  3699. IP_MASK g_ArpIPMaskTable[] =
  3700. {
  3701. CLASSA_MASK,
  3702. CLASSA_MASK,
  3703. CLASSA_MASK,
  3704. CLASSA_MASK,
  3705. CLASSA_MASK,
  3706. CLASSA_MASK,
  3707. CLASSA_MASK,
  3708. CLASSA_MASK,
  3709. CLASSB_MASK,
  3710. CLASSB_MASK,
  3711. CLASSB_MASK,
  3712. CLASSB_MASK,
  3713. CLASSC_MASK,
  3714. CLASSC_MASK,
  3715. CLASSD_MASK,
  3716. CLASSE_MASK
  3717. };
  3718. #define ARP_IPNETMASK(a) g_ArpIPMaskTable[(*(uchar *)&(a)) >> 4]
  3719. // Context passed to the enum function for checking if a particular
  3720. // address is non-unicast.
  3721. //
  3722. typedef struct
  3723. {
  3724. IP_ADDRESS IpAddress;
  3725. IP_ADDRESS BroadcastAddress;
  3726. MYBOOL IsNonUnicast;
  3727. } ARP_NONUNICAST_CTXT, *PARP_NONUNICAST_CTXT;
  3728. // The enum function for the above operation.
  3729. //
  3730. INT
  3731. arpCheckForNonUnicastAddress(
  3732. PRM_OBJECT_HEADER pHdr,
  3733. PVOID pvContext,
  3734. PRM_STACK_RECORD pSR
  3735. )
  3736. {
  3737. PARPCB_LOCAL_IP pLocalIp;
  3738. PARP_NONUNICAST_CTXT pOurCtxt;
  3739. IP_ADDRESS Addr;
  3740. IP_ADDRESS BCast;
  3741. IP_ADDRESS LocalAddr;
  3742. IP_MASK Mask;
  3743. pLocalIp = (PARPCB_LOCAL_IP) pHdr;
  3744. // If this local ip address is non-unicast, skip it.
  3745. //
  3746. if (pLocalIp->IpAddressType != LLIP_ADDR_LOCAL)
  3747. {
  3748. return TRUE; // *** EARLY RETURN *** (continue to enumerate)
  3749. }
  3750. pOurCtxt = (PARP_NONUNICAST_CTXT) pvContext;
  3751. Addr = pOurCtxt->IpAddress;
  3752. LocalAddr= pLocalIp->IpAddress;
  3753. BCast = pOurCtxt->BroadcastAddress;
  3754. // First check for subnet bcast.
  3755. //
  3756. Mask = pLocalIp->IpMask;
  3757. if (IP_ADDR_EQUAL((LocalAddr & Mask) | (BCast & ~Mask), Addr))
  3758. {
  3759. pOurCtxt->IsNonUnicast = TRUE;
  3760. return FALSE; // Stop enumerating
  3761. }
  3762. // Now check all nets broadcast.
  3763. Mask = ARP_IPNETMASK(LocalAddr);
  3764. if (IP_ADDR_EQUAL((LocalAddr & Mask) | (BCast & ~Mask), Addr))
  3765. {
  3766. pOurCtxt->IsNonUnicast = TRUE;
  3767. return FALSE; // Stop enumerating
  3768. }
  3769. return TRUE; // Continue to enumerate.
  3770. }
  3771. MYBOOL
  3772. arpIsNonUnicastEthAddress (
  3773. IN PARP1394_INTERFACE pIF, // LOCKIN LOCKOUT
  3774. IN ENetAddr* pAddr,
  3775. IN PRM_STACK_RECORD pSR
  3776. )
  3777. /*++
  3778. Routine Description:
  3779. Check if the given IP address is a non-unicast (broadcast or multicast) address
  3780. for the interface.
  3781. Copied from IP/ATM module (atmarpc.sys)
  3782. Arguments:
  3783. Addr - The Eth Address to be checked
  3784. pInterface - Pointer to our Interface structure
  3785. Return Value:
  3786. TRUE if the address is a non-unicast address, FALSE otherwise.
  3787. --*/
  3788. {
  3789. MYBOOL fIsNonUnicastEthAddress = FALSE;
  3790. MYBOOL fIsMulticast = FALSE;
  3791. MYBOOL fIsBroadcast = FALSE;
  3792. fIsMulticast = ETH_IS_MULTICAST (pAddr);
  3793. fIsBroadcast = ETH_IS_BROADCAST (pAddr);
  3794. //
  3795. // if it is either a Multicast or a Unicast address than
  3796. // it is a non-unicast address
  3797. //
  3798. fIsNonUnicastEthAddress = (fIsMulticast || fIsBroadcast );
  3799. return (fIsNonUnicastEthAddress );
  3800. }
  3801. MYBOOL
  3802. arpIsNonUnicastIpAddress(
  3803. IN PARP1394_INTERFACE pIF, // LOCKIN LOCKOUT
  3804. IN IP_ADDRESS Addr,
  3805. IN PRM_STACK_RECORD pSR
  3806. )
  3807. /*++
  3808. Routine Description:
  3809. Check if the given IP address is a non-unicast (broadcast or multicast) address
  3810. for the interface.
  3811. Copied from IP/ATM module (atmarpc.sys)
  3812. Arguments:
  3813. Addr - The IP Address to be checked
  3814. pInterface - Pointer to our Interface structure
  3815. Return Value:
  3816. TRUE if the address is a non-unicast address, FALSE otherwise.
  3817. --*/
  3818. {
  3819. IP_ADDRESS BCast;
  3820. IP_MASK Mask;
  3821. // PIP_ADDRESS_ENTRY pIpAddressEntry;
  3822. IP_ADDRESS LocalAddr;
  3823. // Get the interface broadcast address.
  3824. BCast = pIF->ip.BroadcastAddress;
  3825. // Check for global broadcast and multicast.
  3826. if (IP_ADDR_EQUAL(BCast, Addr) || CLASSD_ADDR(Addr))
  3827. return TRUE;
  3828. // Look through all our local ip addresses, checking for subnet and net
  3829. // broadcast addresses.
  3830. //
  3831. {
  3832. ARP_NONUNICAST_CTXT Ctxt;
  3833. Ctxt.IsNonUnicast = FALSE;
  3834. Ctxt.IpAddress = Addr;
  3835. Ctxt.BroadcastAddress = BCast;
  3836. RmEnumerateObjectsInGroup(
  3837. &pIF->LocalIpGroup,
  3838. arpCheckForNonUnicastAddress,
  3839. &Ctxt,
  3840. TRUE, // Choose strong enumeration
  3841. pSR
  3842. );
  3843. return Ctxt.IsNonUnicast;
  3844. }
  3845. }
  3846. VOID
  3847. arpRefSendPkt(
  3848. PNDIS_PACKET pNdisPacket,
  3849. PARPCB_DEST pDest // LOCKIN LOCKOUT (readlock, IF Send lock)
  3850. )
  3851. {
  3852. MYBOOL DoRef;
  3853. // Note, we just have a READ lock on the IF send lock. So the following
  3854. // needs to be an interlocked operation ...
  3855. //
  3856. DoRef = (InterlockedIncrement(&pDest->sendinfo.NumOutstandingSends) == 1);
  3857. // The following macros are just so that we can make the proper debug association
  3858. // depending on how closely we are tracking outstanding send packets.
  3859. //
  3860. #if ARPDBG_REF_EVERY_PACKET
  3861. DoRef = TRUE;
  3862. #define OUR_EXTERNAL_ENTITY ((UINT_PTR) pNdisPacket)
  3863. #define szARPSSOC_EXTLINK_DEST_TO_PKT_FORMAT " Outstanding send pkt 0x%p\n"
  3864. #else // !ARPDBG_REF_EVERY_PACKET
  3865. #define OUR_EXTERNAL_ENTITY ((UINT_PTR) &pDest->sendinfo)
  3866. #define szARPSSOC_EXTLINK_DEST_TO_PKT_FORMAT " Outstanding pkts. &si=0x%p\n"
  3867. #endif // !ARPDBG_REF_EVERY_PACKET
  3868. if (DoRef)
  3869. {
  3870. //
  3871. // If ARPDBG_REF_EVERY_PKT
  3872. // We add an "external" link for EVERY packet. We'll later remove this
  3873. // reference when the send completes for this packet.
  3874. // else
  3875. // Only a transition from zero to non-zero outstanding sends, we
  3876. // add an "external" link. We'll later remove this link when the
  3877. // transition from non-zero to zero happens.
  3878. //
  3879. #if RM_EXTRA_CHECKING
  3880. RM_DECLARE_STACK_RECORD(sr)
  3881. RmLinkToExternalEx(
  3882. &pDest->Hdr, // pHdr
  3883. 0x13f839b4, // LUID
  3884. OUR_EXTERNAL_ENTITY, // External entity
  3885. ARPASSOC_EXTLINK_DEST_TO_PKT, // AssocID
  3886. szARPSSOC_EXTLINK_DEST_TO_PKT_FORMAT,
  3887. &sr
  3888. );
  3889. #else // !RM_EXTRA_CHECKING
  3890. RmLinkToExternalFast(&pDest->Hdr);
  3891. #endif // !RM_EXTRA_CHECKING
  3892. }
  3893. #undef OUR_EXTERNAL_ENTITY
  3894. #undef szARPSSOC_EXTLINK_DEST_TO_PKT_FORMAT
  3895. }
  3896. VOID
  3897. arpHandleControlPktSendCompletion(
  3898. IN ARP1394_INTERFACE * pIF,
  3899. IN PNDIS_PACKET pNdisPacket
  3900. )
  3901. {
  3902. RM_DECLARE_STACK_RECORD(sr)
  3903. arpFreeControlPacket(
  3904. pIF,
  3905. pNdisPacket,
  3906. &sr
  3907. );
  3908. }
  3909. BOOLEAN
  3910. arpCanTryMcap(
  3911. IP_ADDRESS IpAddress
  3912. )
  3913. /*++
  3914. Return TRUE IFF this is an MCAP compatible address.
  3915. For now that means that it's a class D address, but not
  3916. 224.0.0.1 or 224.0.0.2
  3917. --*/
  3918. {
  3919. // 1st check if it's a multicast address.
  3920. //
  3921. if ( (IpAddress & 0xf0) == 0xe0)
  3922. {
  3923. //
  3924. // Then check for special multicast addresses 224.0.0.1 and 224.0.0.2
  3925. // The ip/1395 rfc states that these two addresses must be
  3926. // send on the broadcast channel.
  3927. //
  3928. if ( (IpAddress != 0x010000e0) && (IpAddress != 0x020000e0))
  3929. {
  3930. return TRUE;
  3931. }
  3932. }
  3933. return FALSE;
  3934. }
  3935. VOID
  3936. arpLoopbackNdisPacket(
  3937. PARP1394_INTERFACE pIF,
  3938. PARPCB_DEST pBroadcastDest,
  3939. PNDIS_PACKET pOldPacket
  3940. )
  3941. /*++
  3942. Routine Description:
  3943. if this is being sent to a broadcast destination, then allocate a new
  3944. packet and loop it back up to the protocols.
  3945. Arguments:
  3946. pIF - Pointer to the Interface on which the packet is sent
  3947. pBroadcastDest - The Destination to which the packet is being sent.
  3948. Return Value:
  3949. TRUE if the address is a non-unicast address, FALSE otherwise.
  3950. --*/
  3951. {
  3952. PNDIS_PACKET pNewPkt = NULL;
  3953. const UINT MacHeaderLength = sizeof(NIC1394_ENCAPSULATION_HEADER);
  3954. PUCHAR pPayloadDataVa = NULL;
  3955. UINT TotalLength = 0;
  3956. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  3957. UINT HeadBufferLength = 0;
  3958. PUCHAR pHeadBufferVa = NULL;
  3959. do
  3960. {
  3961. //Allocate the packet
  3962. NdisAllocatePacket(
  3963. &Status,
  3964. &pNewPkt,
  3965. pIF->arp.PacketPool
  3966. );
  3967. if (Status != NDIS_STATUS_SUCCESS || pNewPkt == NULL)
  3968. {
  3969. pNewPkt = NULL;
  3970. break;
  3971. }
  3972. // set up the head and tail
  3973. pNewPkt->Private.Head = pOldPacket->Private.Head;
  3974. pNewPkt->Private.Tail = pOldPacket->Private.Tail;
  3975. pNewPkt->Private.ValidCounts = FALSE;
  3976. // indicate the packet with a status of resources
  3977. NDIS_SET_PACKET_STATUS (pNewPkt, NDIS_STATUS_RESOURCES);
  3978. HeadBufferLength = NdisBufferLength (pNewPkt->Private.Head);
  3979. pHeadBufferVa = NdisBufferVirtualAddressSafe (pNewPkt->Private.Head, NormalPagePriority );
  3980. if (pHeadBufferVa ==NULL)
  3981. {
  3982. Status = NDIS_STATUS_FAILURE;
  3983. break;
  3984. }
  3985. if (HeadBufferLength <= MacHeaderLength)
  3986. {
  3987. // we need to go the next NdisBuffer to get the Start of data
  3988. //
  3989. pPayloadDataVa = NdisBufferVirtualAddressSafe (pNewPkt->Private.Head->Next, NormalPagePriority );
  3990. if (pPayloadDataVa == NULL)
  3991. {
  3992. Status = NDIS_STATUS_FAILURE;
  3993. break;
  3994. }
  3995. if (HeadBufferLength != MacHeaderLength)
  3996. {
  3997. pPayloadDataVa += (MacHeaderLength - HeadBufferLength);
  3998. }
  3999. }
  4000. else
  4001. {
  4002. // The payload is within the Buffer
  4003. pPayloadDataVa += MacHeaderLength ;
  4004. }
  4005. if (pOldPacket->Private.ValidCounts == TRUE)
  4006. {
  4007. TotalLength = pOldPacket->Private.TotalLength;
  4008. }
  4009. else
  4010. {
  4011. NdisQueryPacket(pOldPacket, NULL, NULL, NULL, &TotalLength);
  4012. }
  4013. pIF->ip.RcvHandler(
  4014. pIF->ip.Context,
  4015. (PVOID)(pPayloadDataVa),
  4016. HeadBufferLength - MacHeaderLength,
  4017. TotalLength - MacHeaderLength,
  4018. (NDIS_HANDLE)pNewPkt,
  4019. MacHeaderLength,
  4020. TRUE, //IsChannel
  4021. NULL
  4022. );
  4023. }while (FALSE);
  4024. if (pNewPkt != NULL)
  4025. {
  4026. NdisFreePacket (pNewPkt);
  4027. pNewPkt = NULL;
  4028. }
  4029. }
  4030. REMOTE_DEST_KEY
  4031. RemoteIPKeyFromIPAddress (
  4032. IPAddr IpAddress
  4033. )
  4034. /*++
  4035. Routine Description:
  4036. Creates a RemoteIPKey structure from an IP Address
  4037. by tagging two constant bytes
  4038. Arguments:
  4039. Return Value:
  4040. New Remote Ip Key
  4041. --*/
  4042. {
  4043. REMOTE_DEST_KEY RemoteIpKey ={0,0,0,0,0,0} ;
  4044. ASSERT (sizeof (REMOTE_DEST_KEY)==sizeof(ENetAddr));
  4045. RemoteIpKey.IpAddress = IpAddress;
  4046. return RemoteIpKey;
  4047. }
  4048. NTSTATUS
  4049. arpDelArpEntry(
  4050. PARP1394_INTERFACE pIF,
  4051. IPAddr IpAddress,
  4052. PRM_STACK_RECORD pSR
  4053. )
  4054. {
  4055. ENTER("DelArpEntry", 0x3427306a)
  4056. NTSTATUS NtStatus;
  4057. TR_WARN(("DEL ARP ENTRY\n"));
  4058. NtStatus = STATUS_UNSUCCESSFUL;
  4059. do
  4060. {
  4061. NDIS_STATUS Status;
  4062. NIC1394_FIFO_ADDRESS FifoAddress;
  4063. PARPCB_REMOTE_IP pRemoteIp;
  4064. PRM_TASK pUnloadObjectTask;
  4065. REMOTE_DEST_KEY RemoteDestKey;
  4066. // If this is a Subnet broadcast IP address, then skip the delete
  4067. //
  4068. #define ARP1394_SUBNET_BROADCAST_IP 0xffff0000
  4069. if ((IpAddress & ARP1394_SUBNET_BROADCAST_IP ) == ARP1394_SUBNET_BROADCAST_IP )
  4070. {
  4071. break;
  4072. }
  4073. LOCKOBJ(pIF, pSR);
  4074. //
  4075. // Initialize the RemoteDestKey
  4076. //
  4077. REMOTE_DEST_KEY_INIT(&RemoteDestKey);
  4078. RemoteDestKey.IpAddress = IpAddress;
  4079. //
  4080. // Lookup the RemoteIp entry corresponding to this entry and unload
  4081. // it.
  4082. //
  4083. Status = RmLookupObjectInGroup(
  4084. &pIF->RemoteIpGroup,
  4085. 0, // Flags
  4086. (PVOID) &RemoteDestKey, // pKey
  4087. NULL, // pvCreateParams
  4088. &(PRM_OBJECT_HEADER)pRemoteIp,
  4089. NULL, // pfCreated
  4090. pSR
  4091. );
  4092. UNLOCKOBJ(pIF, pSR);
  4093. if (FAIL(Status))
  4094. {
  4095. break;
  4096. }
  4097. //
  4098. // Found pRemoteIp. Let's initiate the unload of pRemoteIp. We won't wait
  4099. // around for it to complete.
  4100. //
  4101. Status = arpAllocateTask(
  4102. &pRemoteIp->Hdr, // pParentObject,
  4103. arpTaskUnloadRemoteIp, // pfnHandler,
  4104. 0, // Timeout,
  4105. "Task:Unload RemoteIp (DelArpEntry)",
  4106. &pUnloadObjectTask,
  4107. pSR
  4108. );
  4109. RmTmpDereferenceObject(&pRemoteIp->Hdr, pSR);
  4110. if (FAIL(Status))
  4111. {
  4112. TR_WARN(("Couldn't allocate unload remoteip task."));
  4113. break;
  4114. }
  4115. RmStartTask(
  4116. pUnloadObjectTask,
  4117. 0, // UserParam (unused)
  4118. pSR
  4119. );
  4120. NtStatus = STATUS_SUCCESS; // always succeed
  4121. } while (FALSE);
  4122. EXIT()
  4123. return NtStatus;
  4124. }