Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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