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

3095 lines
66 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. arpproc.c - ARP Procedures
  5. Abstract:
  6. All Client protocol operations related to IP over ATM are here:
  7. - Registration with an ARP server
  8. - Resolving an IP address
  9. - Maintaining the ARP cache
  10. Revision History:
  11. Who When What
  12. -------- -------- ----------------------------------------------
  13. arvindm 07-17-96 Created
  14. Notes:
  15. --*/
  16. #include <precomp.h>
  17. #define _FILENUMBER 'PPRA'
  18. VOID
  19. AtmArpStartRegistration(
  20. IN PATMARP_INTERFACE pInterface LOCKIN NOLOCKOUT
  21. )
  22. /*++
  23. Routine Description:
  24. Start registering ourselves with the ARP server, on the specified
  25. interface. The caller is assume to have a lock for the Interface,
  26. and we release it here.
  27. We first check if all pre-conditions are satisfied, i.e.:
  28. 1. The Admin State for the interface is UP
  29. 2. The ATM interface is ready
  30. 3. Atleast one IP Address has been configured for the interface
  31. 4. We know the address of atleast one ARP server (SVC environment)
  32. Arguments:
  33. pInterface - Pointer to ATMARP Interface structure
  34. Return Value:
  35. None
  36. --*/
  37. {
  38. PIP_ADDRESS pIPAddress;
  39. BOOLEAN WasRunning;
  40. pIPAddress = &pInterface->LocalIPAddress.IPAddress;
  41. if (pInterface->AdminState == IF_STATUS_UP)
  42. {
  43. if (pInterface->PVCOnly)
  44. {
  45. //
  46. // PVCs only: no registration required
  47. //
  48. pInterface->State = IF_STATUS_UP;
  49. pInterface->LastChangeTime = GetTimeTicks();
  50. AA_SET_FLAG(
  51. pInterface->Flags,
  52. AA_IF_SERVER_STATE_MASK,
  53. AA_IF_SERVER_REGISTERED);
  54. AA_RELEASE_IF_LOCK(pInterface);
  55. #ifdef ATMARP_WMI
  56. AtmArpWmiSendTCIfIndication(
  57. pInterface,
  58. AAGID_QOS_TC_INTERFACE_UP_INDICATION,
  59. 0
  60. );
  61. #endif
  62. }
  63. else
  64. {
  65. //
  66. // We use SVCs; start registering if we know the
  67. // address of atleast one ARP server, and we have
  68. // atleast one local IP address to register, and
  69. // we haven't registered yet, and we are not in
  70. // the process of registering currently.
  71. //
  72. if ((pInterface->AtmInterfaceUp) &&
  73. (pInterface->ArpServerList.ListSize > 0) &&
  74. (pInterface->NumOfIPAddresses > 0) &&
  75. (AA_IS_FLAG_SET(
  76. pInterface->Flags,
  77. AA_IF_SERVER_STATE_MASK,
  78. AA_IF_SERVER_NO_CONTACT))
  79. )
  80. {
  81. AADEBUGP(AAD_INFO, ("Starting registration on IF 0x%x\n", pInterface));
  82. AA_SET_FLAG(
  83. pInterface->Flags,
  84. AA_IF_SERVER_STATE_MASK,
  85. AA_IF_SERVER_REGISTERING);
  86. //
  87. // Just in case we have left a timer running, stop it.
  88. //
  89. WasRunning = AtmArpStopTimer(
  90. &(pInterface->Timer),
  91. pInterface
  92. );
  93. AtmArpStartTimer(
  94. pInterface,
  95. &(pInterface->Timer),
  96. AtmArpRegistrationTimeout,
  97. pInterface->ServerRegistrationTimeout,
  98. (PVOID)pInterface // Context
  99. );
  100. if (!WasRunning)
  101. {
  102. AtmArpReferenceInterface(pInterface); // Timer ref
  103. }
  104. AA_RELEASE_IF_LOCK(pInterface);
  105. AtmArpSendARPRequest(
  106. pInterface,
  107. pIPAddress, // Source IP is ours
  108. pIPAddress // Target IP is ours
  109. );
  110. }
  111. else
  112. {
  113. //
  114. // We don't have all necessary preconditions for
  115. // starting registration.
  116. //
  117. AA_RELEASE_IF_LOCK(pInterface);
  118. }
  119. }
  120. }
  121. else
  122. {
  123. //
  124. // The Interface is down
  125. //
  126. AA_RELEASE_IF_LOCK(pInterface);
  127. }
  128. }
  129. VOID
  130. AtmArpRegisterOtherIPAddresses(
  131. IN PATMARP_INTERFACE pInterface LOCKIN NOLOCKOUT
  132. )
  133. /*++
  134. Routine Description:
  135. Register all unregistered IP addresses with the ARP server. The caller
  136. is assumed to hold a lock for the Interface structure, which will be
  137. released here.
  138. Arguments:
  139. pInterface - Pointer to ARMARP Interface
  140. Return Value:
  141. None
  142. --*/
  143. {
  144. PIP_ADDRESS_ENTRY pIPAddressEntry;
  145. PIP_ADDRESS pIPAddressList; // List of addresses we want to register
  146. INT AddressCount; // Size of above list
  147. PIP_ADDRESS pIPAddress; // Temp, to walk thru lists
  148. if (pInterface->NumOfIPAddresses > 1)
  149. {
  150. //
  151. // First make a copy of all addresses we want to register,
  152. // while we hold a lock to the Interface.
  153. //
  154. AA_ALLOC_MEM(
  155. pIPAddressList,
  156. IP_ADDRESS,
  157. (pInterface->NumOfIPAddresses)*sizeof(IP_ADDRESS));
  158. AddressCount = 0;
  159. if (pIPAddressList != (PIP_ADDRESS)NULL)
  160. {
  161. pIPAddress = pIPAddressList;
  162. pIPAddressEntry = &(pInterface->LocalIPAddress);
  163. while (pIPAddressEntry != (PIP_ADDRESS_ENTRY)NULL)
  164. {
  165. if (!(pIPAddressEntry->IsRegistered))
  166. {
  167. //
  168. // This one's not registered yet: copy it into our list.
  169. //
  170. AA_COPY_MEM(
  171. (PUCHAR)pIPAddress,
  172. (PUCHAR)&(pIPAddressEntry->IPAddress),
  173. sizeof(IP_ADDRESS));
  174. pIPAddress++;
  175. AddressCount++;
  176. }
  177. pIPAddressEntry = pIPAddressEntry->pNext;
  178. }
  179. }
  180. AA_RELEASE_IF_LOCK(pInterface);
  181. pIPAddress = pIPAddressList;
  182. while (AddressCount-- > 0)
  183. {
  184. AADEBUGP(AAD_INFO, ("Registering Other IP Address on IF 0x%x: %d.%d.%d.%d\n",
  185. pInterface,
  186. ((PUCHAR)pIPAddress)[0],
  187. ((PUCHAR)pIPAddress)[1],
  188. ((PUCHAR)pIPAddress)[2],
  189. ((PUCHAR)pIPAddress)[3]));
  190. AtmArpSendARPRequest(
  191. pInterface,
  192. pIPAddress, // Source IP is ours
  193. pIPAddress // Target IP is ours
  194. );
  195. pIPAddress++;
  196. }
  197. if (pIPAddressList != (PIP_ADDRESS)NULL)
  198. {
  199. AA_FREE_MEM(pIPAddressList);
  200. }
  201. }
  202. else
  203. {
  204. //
  205. // No additional addresses to register.
  206. //
  207. AA_RELEASE_IF_LOCK(pInterface);
  208. }
  209. }
  210. VOID
  211. AtmArpRetryServerRegistration(
  212. IN PATMARP_INTERFACE pInterface LOCKIN NOLOCKOUT
  213. )
  214. /*++
  215. Routine Description:
  216. Retry server registration. This is called because of a failure to
  217. register with the server (connection failure, or no response or
  218. NAK response or invalid response to our registration ARP Request).
  219. If we have tried this server enough times, we move to the next
  220. ARP server in our list. Wait for a while before retrying.
  221. Arguments:
  222. pInterface - Pointer to ARMARP Interface
  223. Return Value:
  224. None
  225. --*/
  226. {
  227. if (pInterface->AdminState == IF_STATUS_UP)
  228. {
  229. if (pInterface->RetriesLeft > 0)
  230. {
  231. //
  232. // We still have retries on this server.
  233. //
  234. pInterface->RetriesLeft--;
  235. }
  236. else
  237. {
  238. //
  239. // Out of retries on this server. Pick up the next timer in the
  240. // list.
  241. //
  242. if (pInterface->pCurrentServer->pNext != (PATMARP_SERVER_ENTRY)NULL)
  243. {
  244. pInterface->pCurrentServer = pInterface->pCurrentServer->pNext;
  245. }
  246. else
  247. {
  248. pInterface->pCurrentServer = pInterface->ArpServerList.pList;
  249. }
  250. pInterface->RetriesLeft = pInterface->MaxRegistrationAttempts - 1;
  251. }
  252. AA_SET_FLAG(
  253. pInterface->Flags,
  254. AA_IF_SERVER_STATE_MASK,
  255. AA_IF_SERVER_NO_CONTACT);
  256. //
  257. // Wait for a while before initiating another
  258. // connection to the server. When the timer elapses,
  259. // we will try again.
  260. //
  261. AtmArpStartTimer(
  262. pInterface,
  263. &(pInterface->Timer),
  264. AtmArpServerConnectTimeout,
  265. pInterface->ServerConnectInterval,
  266. (PVOID)pInterface
  267. );
  268. AtmArpReferenceInterface(pInterface); // Timer ref
  269. }
  270. //
  271. // else the Interface is going down -- do nothing.
  272. //
  273. AA_RELEASE_IF_LOCK(pInterface);
  274. }
  275. VOID
  276. AtmArpHandleServerRegistrationFailure(
  277. IN PATMARP_INTERFACE pInterface LOCKIN NOLOCKOUT,
  278. IN PATMARP_VC pVc OPTIONAL
  279. )
  280. /*++
  281. Routine Description:
  282. Handle a failure in the Registration process. We close the VC to the
  283. ARP server, if one exists, and wait for a while before starting the
  284. registration process again.
  285. Arguments:
  286. pInterface - Pointer to ATMARP interface
  287. pVc - (Optional) pointer to VC to ARP Server.
  288. Return Value:
  289. None
  290. --*/
  291. {
  292. BOOLEAN TimerWasRunning;
  293. ULONG rc; // Ref Count on Interface.
  294. TimerWasRunning = AtmArpStopTimer(&(pInterface->Timer), pInterface);
  295. if (TimerWasRunning)
  296. {
  297. rc = AtmArpDereferenceInterface(pInterface); // Timer reference
  298. AA_ASSERT(rc > 0);
  299. }
  300. AtmArpRetryServerRegistration(pInterface);
  301. //
  302. // The IF lock is released within the above.
  303. //
  304. if (pVc != NULL_PATMARP_VC)
  305. {
  306. //
  307. // Tear down this VC (to an ARP server).
  308. //
  309. // NOTE: We do this now even though we called RetryServerRegistration
  310. // above because we have the knowledge that the routine above
  311. // doesn't really start registration: it only starts a timer
  312. // on whose expiry we start registration.
  313. //
  314. // First unlink this VC from the ATM Entry it's linked to.
  315. //
  316. AA_ACQUIRE_VC_LOCK(pVc);
  317. //
  318. // Now close the call
  319. //
  320. AtmArpCloseCall(pVc);
  321. //
  322. // the VC lock is released above
  323. //
  324. }
  325. }
  326. BOOLEAN
  327. AtmArpIsZeroIPAddress(
  328. IN UCHAR UNALIGNED * pIPAddress
  329. )
  330. /*++
  331. Routine Description:
  332. Check if the given IP address is all zeros.
  333. Arguments:
  334. pIPAddress - Pointer to IP address in question
  335. Return Value:
  336. TRUE if the address is all 0's, FALSE otherwise.
  337. --*/
  338. {
  339. IP_ADDRESS UNALIGNED * pIPAddrStruct;
  340. pIPAddrStruct = (IP_ADDRESS UNALIGNED *)pIPAddress;
  341. return (BOOLEAN)(*pIPAddrStruct == (IP_ADDRESS)0);
  342. }
  343. BOOLEAN
  344. AtmArpIsLocalIPAddress(
  345. IN PATMARP_INTERFACE pInterface,
  346. IN UCHAR UNALIGNED * pIPAddress
  347. )
  348. /*++
  349. Routine Description:
  350. Check if the given IP address is one of those assigned to this
  351. interface.
  352. Arguments:
  353. pInterface - Pointer to Interface structure
  354. pIPAddress - Pointer to IP address in question
  355. Return Value:
  356. TRUE if the IP address is one of ours, FALSE otherwise.
  357. --*/
  358. {
  359. PIP_ADDRESS_ENTRY pIPAddrEntry;
  360. IP_ADDRESS UNALIGNED * pIPAddrStruct;
  361. BOOLEAN IsLocal;
  362. if (pIPAddress != (PUCHAR)NULL)
  363. {
  364. pIPAddrStruct = (IP_ADDRESS UNALIGNED *)pIPAddress;
  365. AA_ACQUIRE_IF_LOCK(pInterface);
  366. pIPAddrEntry = &(pInterface->LocalIPAddress);
  367. IsLocal = FALSE;
  368. do
  369. {
  370. if (pIPAddrEntry->IPAddress == *pIPAddrStruct)
  371. {
  372. IsLocal = TRUE;
  373. break;
  374. }
  375. else
  376. {
  377. pIPAddrEntry = pIPAddrEntry->pNext;
  378. }
  379. }
  380. while (pIPAddrEntry != (PIP_ADDRESS_ENTRY)NULL);
  381. AA_RELEASE_IF_LOCK(pInterface);
  382. }
  383. else
  384. {
  385. IsLocal = FALSE;
  386. }
  387. AADEBUGP(AAD_VERY_LOUD, ("IsLocalIP(%d:%d:%d:%d): returning %d\n",
  388. (IsLocal? pIPAddress[0] : 0),
  389. (IsLocal? pIPAddress[1] : 0),
  390. (IsLocal? pIPAddress[2] : 0),
  391. (IsLocal? pIPAddress[3] : 0),
  392. IsLocal));
  393. return (IsLocal);
  394. }
  395. BOOLEAN
  396. AtmArpIsLocalAtmAddress(
  397. IN PATMARP_INTERFACE pInterface,
  398. IN PUCHAR pAtmAddrString,
  399. IN UCHAR AtmAddrTypeLen
  400. )
  401. /*++
  402. Routine Description:
  403. Check if the given ATM address (in "packet" format) is the same as
  404. our local ATM address.
  405. Arguments:
  406. pInterface - Pointer to Interface structure for which the check
  407. is being made.
  408. pAtmAddrString - String of bytes representing an ATM address
  409. AtmAddrTypeLen - Type and Length (ARP packet format) of ATM address
  410. Return Value:
  411. TRUE if the given address matches the local ATM address for the
  412. specified interface, FALSE otherwise.
  413. --*/
  414. {
  415. ATM_ADDRESSTYPE AddressType;
  416. ULONG AddressLength;
  417. AA_PKT_TYPE_LEN_TO_ATM_ADDRESS(AtmAddrTypeLen, &AddressType, &AddressLength);
  418. if ((AddressType == pInterface->LocalAtmAddress.AddressType) &&
  419. (AddressLength == pInterface->LocalAtmAddress.NumberOfDigits) &&
  420. (AA_MEM_CMP(
  421. pAtmAddrString,
  422. pInterface->LocalAtmAddress.Address,
  423. AddressLength) == 0)
  424. )
  425. {
  426. return (TRUE);
  427. }
  428. else
  429. {
  430. return (FALSE);
  431. }
  432. }
  433. NDIS_STATUS
  434. AtmArpSendPacketOnAtmEntry(
  435. IN PATMARP_INTERFACE pInterface,
  436. IN PATMARP_ATM_ENTRY pAtmEntry,
  437. IN PNDIS_PACKET pNdisPacket,
  438. IN PATMARP_FLOW_SPEC pFlowSpec,
  439. IN PATMARP_FILTER_SPEC pFilterSpec OPTIONAL,
  440. IN PATMARP_FLOW_INFO pFlowInfo OPTIONAL,
  441. IN BOOLEAN IsBroadcast
  442. )
  443. /*++
  444. Routine Description:
  445. Send a packet with the specified Filter-Spec and Flow-Spec to
  446. the ATM address denoted by the ATM Entry. We look for a VC that
  447. matches the given Specs, and send/queue this packet on the VC.
  448. If no such VC exists, we make a call with this Flow-Spec.
  449. NOTE: The caller is assumed to hold a lock to the ATM Entry, which
  450. we will release here.
  451. Arguments:
  452. pInterface - Pointer to ATMARP Interface
  453. pAtmEntry - Pointer to ATM Entry on which this packet
  454. should be sent
  455. pNdisPacket - Packet to be sent
  456. pFlowSpec - Flow-Spec for this packet.
  457. pFilterSpec - Filter-Spec for this packet.
  458. pFlowInfo - Flow to which this packet belongs.
  459. IsBroadcast - Is this to a Class-D or broadcast address?
  460. Locks on entry:
  461. Locks on exit:
  462. Return Value:
  463. None
  464. --*/
  465. {
  466. PATMARP_VC pVc; // VC to send this packet on
  467. PNDIS_BUFFER pHeaderBuffer; // For LLC/SNAP header
  468. PNDIS_BUFFER pNdisBuffer; // First buffer in the IP packet
  469. NDIS_HANDLE NdisVcHandle;
  470. NDIS_STATUS Status;
  471. PUCHAR pHeader;
  472. AA_HEADER_TYPE HdrType;
  473. do
  474. {
  475. Status = NDIS_STATUS_SUCCESS;
  476. //
  477. // TODO -- the atm entry may not be ACTIVE at this time,
  478. // you may want to check for this and if so fail the call and free
  479. // the packet (call AtmArpFreeSendPackets) here itself.
  480. // As it happens we go on and make a call if possible, etc.
  481. //
  482. // Prepend an LLC/SNAP header if required.
  483. //
  484. if (pFlowSpec->Encapsulation == ENCAPSULATION_TYPE_LLCSNAP)
  485. {
  486. HdrType = (IsBroadcast? AA_HEADER_TYPE_NUNICAST: AA_HEADER_TYPE_UNICAST);
  487. #ifdef BACK_FILL
  488. //
  489. // We look at the first buffer in the IP packet, to see whether
  490. // it has space reserved for low-layer headers. If so, we just
  491. // use it up. Otherwise, we allocate a header buffer of our own.
  492. //
  493. NdisQueryPacket(pNdisPacket, NULL, NULL, &pNdisBuffer, NULL);
  494. AA_ASSERT(pNdisBuffer != NULL);
  495. if (AtmArpDoBackFill && AA_BACK_FILL_POSSIBLE(pNdisBuffer))
  496. {
  497. PUCHAR pArpHeader;
  498. ULONG ArpHeaderLength;
  499. AtmArpBackFillCount++;
  500. if (HdrType == AA_HEADER_TYPE_UNICAST)
  501. {
  502. pArpHeader = (PUCHAR)&AtmArpLlcSnapHeader;
  503. ArpHeaderLength = sizeof(AtmArpLlcSnapHeader);
  504. }
  505. #ifdef IPMCAST
  506. else
  507. {
  508. pArpHeader = (PUCHAR)&AtmArpMcType1ShortHeader;
  509. ArpHeaderLength = sizeof(AtmArpMcType1ShortHeader);
  510. }
  511. #endif // IPMCAST
  512. (PUCHAR)pNdisBuffer->MappedSystemVa -= ArpHeaderLength;
  513. pNdisBuffer->ByteOffset -= ArpHeaderLength;
  514. pNdisBuffer->ByteCount += ArpHeaderLength;
  515. pHeader = pNdisBuffer->MappedSystemVa;
  516. AA_COPY_MEM(pHeader,
  517. pArpHeader,
  518. ArpHeaderLength);
  519. }
  520. else
  521. {
  522. pHeaderBuffer = AtmArpAllocateHeader(pInterface, HdrType, &pHeader);
  523. if (pHeaderBuffer != (PNDIS_BUFFER)NULL)
  524. {
  525. NdisChainBufferAtFront(pNdisPacket, pHeaderBuffer);
  526. }
  527. else
  528. {
  529. pHeader = NULL;
  530. }
  531. }
  532. if (pHeader != NULL)
  533. {
  534. #else
  535. pHeaderBuffer = AtmArpAllocateHeader(pInterface, HdrType, &pHeader);
  536. if (pHeaderBuffer != (PNDIS_BUFFER)NULL)
  537. {
  538. NdisChainBufferAtFront(pNdisPacket, pHeaderBuffer);
  539. #endif // BACK_FILL
  540. #ifdef IPMCAST
  541. if (HdrType == AA_HEADER_TYPE_NUNICAST)
  542. {
  543. PAA_MC_PKT_TYPE1_SHORT_HEADER pDataHeader;
  544. //
  545. // Fill in our Cluster Member ID
  546. //
  547. AAMCDEBUGP(AAD_EXTRA_LOUD+10,
  548. ("(MC)SendPkt: pAtmEntry 0x%x, pHeaderBuffer 0x%x, pHeader 0x%x\n",
  549. pAtmEntry, pHeaderBuffer, pHeader));
  550. pDataHeader = (PAA_MC_PKT_TYPE1_SHORT_HEADER)pHeader;
  551. pDataHeader->cmi = (USHORT)(pInterface->ClusterMemberId);
  552. }
  553. #endif // IPMCAST
  554. }
  555. else
  556. {
  557. AA_RELEASE_AE_LOCK(pAtmEntry);
  558. AADEBUGP(AAD_WARNING, ("FAILED TO ALLOCATE HEADER ON IF 0x%x\n",
  559. pInterface));
  560. Status = NDIS_STATUS_RESOURCES;
  561. break;
  562. }
  563. }
  564. //
  565. // Search for a VC that has matching flow/filter specs.
  566. //
  567. for (pVc = pAtmEntry->pVcList;
  568. pVc != NULL_PATMARP_VC;
  569. pVc = pVc->pNextVc)
  570. {
  571. #ifdef GPC
  572. PVOID VcFlowHandle;
  573. VcFlowHandle = pVc->FlowHandle;
  574. #endif // GPC
  575. if ((!AA_IS_VC_GOING_DOWN(pVc)) &&
  576. (pVc->FlowSpec.SendPeakBandwidth > 0))
  577. {
  578. #ifdef GPC
  579. if (VcFlowHandle == (PVOID)pFlowInfo)
  580. {
  581. //
  582. // This VC was made for this flow.
  583. //
  584. break;
  585. }
  586. if (IsBroadcast)
  587. {
  588. //
  589. // We don't support multiple VCs to a multicast IP
  590. // destination. So, stop at the first available VC.
  591. //
  592. break;
  593. }
  594. //
  595. // If this VC is associated with a flow already, don't
  596. // send traffic belonging to another flow (explicit or
  597. // unclassified best effort) on it.
  598. //
  599. if (VcFlowHandle != NULL)
  600. {
  601. continue;
  602. }
  603. #endif // GPC
  604. if ((pFilterSpec == (PATMARP_FILTER_SPEC)NULL) ||
  605. AA_FILTER_SPEC_MATCH(pInterface, pFilterSpec, &(pVc->FilterSpec)))
  606. {
  607. if (AA_FLOW_SPEC_MATCH(pInterface, pFlowSpec, &(pVc->FlowSpec)))
  608. {
  609. break;
  610. }
  611. }
  612. }
  613. AADEBUGP(AAD_LOUD,
  614. ("pVc %x did not match pkt, Vc has VcHandle %x, SendPeak %d, SendMaxSize %d\n",
  615. pVc,
  616. pVc->NdisVcHandle,
  617. pVc->FlowSpec.SendPeakBandwidth,
  618. pVc->FlowSpec.SendMaxSize));
  619. AADEBUGP(AAD_LOUD,
  620. ("Target FlowSpec %x has SendPeak %d, SendMaxSize %d\n",
  621. pFlowSpec,
  622. pFlowSpec->SendPeakBandwidth,
  623. pFlowSpec->SendMaxSize));
  624. }
  625. if (pVc != NULL_PATMARP_VC)
  626. {
  627. //
  628. // Found a VC that matches this packet's requirements.
  629. //
  630. AA_ACQUIRE_VC_LOCK_DPC(pVc);
  631. #ifdef GPC
  632. //
  633. // See if the VC and the Flow are unassociated. If so, link
  634. // together the VC and the Flow, to speed up future packets.
  635. // Take care not to reassociate a VC that's just been unlinked
  636. // from a flow.
  637. //
  638. if ((pFlowInfo != NULL) &&
  639. (pVc->FlowHandle == NULL) &&
  640. (!AA_IS_FLAG_SET(
  641. pVc->Flags,
  642. AA_VC_GPC_MASK,
  643. AA_VC_GPC_IS_UNLINKED_FROM_FLOW))
  644. )
  645. {
  646. if (NULL == InterlockedCompareExchangePointer(
  647. &(pFlowInfo->VcContext),
  648. pVc,
  649. NULL
  650. ))
  651. {
  652. AADEBUGP( AAD_LOUD,
  653. ("SendPktOnAtmEntry: linking VC x%x and FlowInfo x%x\n",
  654. pVc, pFlowInfo));
  655. pVc->FlowHandle = (PVOID)pFlowInfo;
  656. AtmArpReferenceVc(pVc); // GPC FlowInfo ref
  657. }
  658. else
  659. {
  660. //
  661. // We couldn't associate the vc with the flow, so we need
  662. // to enable the ageing timer for this vc, because we'll
  663. // never get notified when the flow is removed/modified.
  664. //
  665. if (!AA_IS_TIMER_ACTIVE(&(pVc->Timer)))
  666. {
  667. AADEBUGP( AAD_INFO,
  668. ("SendPktOnAtmEntry: Enabling ageing timer on VC x%x "
  669. "because we could not associate with FlowInfo x%x\n",
  670. pVc, pFlowInfo));
  671. AtmArpStartTimer(
  672. pVc->pInterface,
  673. &(pVc->Timer),
  674. AtmArpVcAgingTimeout,
  675. pInterface->DefaultFlowSpec.AgingTime,
  676. (PVOID)pVc
  677. );
  678. AtmArpReferenceVc(pVc); // GPC Flow remove decay timer ref
  679. }
  680. }
  681. }
  682. #endif // GPC
  683. if (AA_IS_FLAG_SET(
  684. pVc->Flags,
  685. AA_VC_CALL_STATE_MASK,
  686. AA_VC_CALL_STATE_ACTIVE))
  687. {
  688. #ifdef VC_REFS_ON_SENDS
  689. AtmArpReferenceVc(pVc); // SendPacketOnAtmEntry
  690. #endif // VC_REFS_ON_SENDS
  691. pVc->OutstandingSends++; // SendPacketOnAtmEntry
  692. NdisVcHandle = pVc->NdisVcHandle;
  693. AtmArpRefreshTimer(&(pVc->Timer));
  694. }
  695. else
  696. {
  697. AtmArpQueuePacketOnVc(pVc, pNdisPacket);
  698. NdisVcHandle = NULL; // to signify we are queueing this packet
  699. }
  700. AA_RELEASE_VC_LOCK_DPC(pVc);
  701. AA_RELEASE_AE_LOCK(pAtmEntry);
  702. if (NdisVcHandle != NULL)
  703. {
  704. //
  705. // A call is active on this VC, so send the packet.
  706. //
  707. #if DBG
  708. if (AaDataDebugLevel & (AAD_DATA_OUT))
  709. {
  710. AADEBUGP(AAD_FATAL,
  711. ("Will send Pkt %x on VC %x, Handle %x, sendBW %d, sendMax %d\n",
  712. pNdisPacket,
  713. pVc,
  714. NdisVcHandle,
  715. pVc->FlowSpec.SendPeakBandwidth,
  716. pVc->FlowSpec.SendMaxSize));
  717. }
  718. #endif
  719. AADEBUGP(AAD_EXTRA_LOUD+50,
  720. ("SendPktOnAtmEntry: will send Pkt 0x%x on VC 0x%x, VcHandle 0x%x\n",
  721. pNdisPacket,
  722. pVc,
  723. NdisVcHandle));
  724. #ifdef PERF
  725. AadLogSendUpdate(pNdisPacket);
  726. #endif // PERF
  727. NDIS_CO_SEND_PACKETS(
  728. NdisVcHandle,
  729. &pNdisPacket,
  730. 1
  731. );
  732. }
  733. else
  734. {
  735. //
  736. // The packet would have been queued.
  737. //
  738. }
  739. Status = NDIS_STATUS_PENDING;
  740. }
  741. else
  742. {
  743. //
  744. // No matching VC exists; create a new one.
  745. //
  746. #ifdef IPMCAST
  747. if (AA_IS_FLAG_SET(pAtmEntry->Flags,
  748. AA_ATM_ENTRY_TYPE_MASK,
  749. AA_ATM_ENTRY_TYPE_UCAST))
  750. {
  751. Status = AtmArpMakeCall(
  752. pInterface,
  753. pAtmEntry,
  754. pFlowSpec,
  755. pNdisPacket
  756. );
  757. //
  758. // AE lock is released within the above.
  759. //
  760. }
  761. else
  762. {
  763. //
  764. // Multicast ATM Entry: we shouldn't be here, ideally..
  765. //
  766. AA_RELEASE_AE_LOCK(pAtmEntry);
  767. AAMCDEBUGP(AAD_WARNING,
  768. ("SendPacket: pAtmEntry 0x%x, Flags 0x%x, dropping pkt 0x%x\n",
  769. pAtmEntry, pAtmEntry->Flags, pNdisPacket));
  770. AA_SET_NEXT_PACKET(pNdisPacket, NULL);
  771. AtmArpFreeSendPackets(
  772. pInterface,
  773. pNdisPacket,
  774. TRUE // header present
  775. );
  776. }
  777. #else
  778. Status = AtmArpMakeCall(
  779. pInterface,
  780. pAtmEntry,
  781. pFlowSpec,
  782. pNdisPacket
  783. );
  784. //
  785. // The ATM Entry lock is released within the above.
  786. //
  787. #endif // IPMCAST
  788. Status = NDIS_STATUS_PENDING;
  789. }
  790. break;
  791. }
  792. while (FALSE);
  793. return (Status);
  794. }
  795. VOID
  796. AtmArpQueuePacketOnVc(
  797. IN PATMARP_VC pVc,
  798. IN PNDIS_PACKET pNdisPacket
  799. )
  800. /*++
  801. Routine Description:
  802. Queue a packet on the VC's transmit queue.
  803. Arguments:
  804. pVc - Pointer to ATMARP VC
  805. pNdisPacket - The packet to be queued.
  806. Return Value:
  807. None
  808. --*/
  809. {
  810. PNDIS_PACKET pPrevPacket;
  811. AADEBUGP(AAD_EXTRA_LOUD, ("Queueing Pkt 0x%x on VC 0x%x\n",
  812. pNdisPacket, pVc));
  813. if (pVc->PacketList == (PNDIS_PACKET)NULL)
  814. {
  815. //
  816. // No packets on this VC.
  817. //
  818. pVc->PacketList = pNdisPacket;
  819. }
  820. else
  821. {
  822. //
  823. // Go to the end of the packet list on this VC.
  824. //
  825. pPrevPacket = pVc->PacketList;
  826. while (AA_GET_NEXT_PACKET(pPrevPacket) != (PNDIS_PACKET)NULL)
  827. {
  828. pPrevPacket = AA_GET_NEXT_PACKET(pPrevPacket);
  829. }
  830. //
  831. // Found the last packet in the list. Chain this packet
  832. // to it.
  833. //
  834. AA_SET_NEXT_PACKET(pPrevPacket, pNdisPacket);
  835. }
  836. AA_SET_NEXT_PACKET(pNdisPacket, NULL);
  837. }
  838. VOID
  839. AtmArpStartSendsOnVc(
  840. IN PATMARP_VC pVc LOCKIN NOLOCKOUT
  841. )
  842. /*++
  843. Routine Description:
  844. Send all packets queued on a VC. It is assumed that there is
  845. a call active on the VC, and the Interface state is OK.
  846. Arguments:
  847. pVc - Pointer to ATMARP VC
  848. Locks on entry:
  849. VC Lock.
  850. Locks on exit:
  851. None
  852. Return Value:
  853. None
  854. --*/
  855. {
  856. PNDIS_PACKET pNdisPacket;
  857. PNDIS_PACKET pNextNdisPacket;
  858. NDIS_HANDLE NdisVcHandle;
  859. ULONG rc; // Ref Count to VC
  860. //
  861. // Remove the entire list of packets queued on the VC.
  862. //
  863. pNdisPacket = pVc->PacketList;
  864. pVc->PacketList = (PNDIS_PACKET)NULL;
  865. #ifdef VC_REFS_ON_SENDS
  866. //
  867. // Reference the VC for all these packets.
  868. //
  869. {
  870. PNDIS_PACKET pPacket;
  871. for (pPacket = pNdisPacket;
  872. pPacket != NULL;
  873. pPacket = AA_GET_NEXT_PACKET(pPacket))
  874. {
  875. AtmArpReferenceVc(pVc); // StartSendsOnVc
  876. pVc->OutstandingSends++;// StartSendsOnVc
  877. }
  878. }
  879. #else
  880. {
  881. PNDIS_PACKET pPacket;
  882. for (pPacket = pNdisPacket;
  883. pPacket != NULL;
  884. pPacket = AA_GET_NEXT_PACKET(pPacket))
  885. {
  886. pVc->OutstandingSends++;// StartSendsOnVc (!VC_REFS_ON_SENDS)
  887. }
  888. }
  889. #endif // VC_REFS_ON_SENDS
  890. AtmArpRefreshTimer(&(pVc->Timer));
  891. NdisVcHandle = pVc->NdisVcHandle;
  892. //
  893. // We have got all that we need from the VC.
  894. //
  895. AA_RELEASE_VC_LOCK(pVc);
  896. while (pNdisPacket != (PNDIS_PACKET)NULL)
  897. {
  898. pNextNdisPacket = AA_GET_NEXT_PACKET(pNdisPacket);
  899. AA_SET_NEXT_PACKET(pNdisPacket, NULL);
  900. AADEBUGP(AAD_EXTRA_LOUD+10, ("StartSendsOnVc: pVc 0x%x, Pkt 0x%x\n",
  901. pVc, pNdisPacket));
  902. #ifdef PERF
  903. AadLogSendUpdate(pNdisPacket);
  904. #endif // PERF
  905. NDIS_CO_SEND_PACKETS(
  906. NdisVcHandle,
  907. &pNdisPacket,
  908. 1
  909. );
  910. pNdisPacket = pNextNdisPacket;
  911. }
  912. }
  913. VOID
  914. AtmArpSendPacketListOnAtmEntry(
  915. IN PATMARP_INTERFACE pInterface,
  916. IN PATMARP_ATM_ENTRY pAtmEntry,
  917. IN PNDIS_PACKET pPacketList,
  918. IN BOOLEAN IsBroadcast
  919. )
  920. /*++
  921. Routine Description:
  922. Send a list of packets towards a destination identified by an
  923. ATM Entry.
  924. Arguments:
  925. pInterface - Pointer to ATMARP Interface
  926. pAtmEntry - ATM Entry on which the packets are to be sent
  927. pPacketList - List of packets to be sent.
  928. IsBroadcast - Are these directed to Class D/broadcast addresses?
  929. Return Value:
  930. None
  931. --*/
  932. {
  933. PATMARP_FLOW_INFO pFlowInfo;
  934. PATMARP_FLOW_SPEC pFlowSpec;
  935. PATMARP_FILTER_SPEC pFilterSpec;
  936. PNDIS_PACKET pNdisPacket;
  937. PNDIS_PACKET pNextNdisPacket;
  938. NDIS_STATUS Status;
  939. for (pNdisPacket = pPacketList;
  940. pNdisPacket != (PNDIS_PACKET)NULL;
  941. pNdisPacket = pNextNdisPacket)
  942. {
  943. pNextNdisPacket = AA_GET_NEXT_PACKET(pNdisPacket);
  944. AA_SET_NEXT_PACKET(pNdisPacket, NULL);
  945. //
  946. // Get the Filter and Flow specs for this packet
  947. //
  948. AA_GET_PACKET_SPECS(pInterface, pNdisPacket, &pFlowInfo, &pFlowSpec, &pFilterSpec);
  949. AADEBUGP(AAD_EXTRA_LOUD+10, ("PktListOnAtmEntry: AtmEntry 0x%x, Pkt 0x%x\n",
  950. pAtmEntry, pNdisPacket));
  951. //
  952. // Send it off
  953. //
  954. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  955. Status = AtmArpSendPacketOnAtmEntry(
  956. pInterface,
  957. pAtmEntry,
  958. pNdisPacket,
  959. pFlowSpec,
  960. pFilterSpec,
  961. pFlowInfo,
  962. IsBroadcast
  963. );
  964. //
  965. // AE lock is released within the above.
  966. //
  967. if ((Status != NDIS_STATUS_PENDING) &&
  968. (Status != NDIS_STATUS_SUCCESS))
  969. {
  970. AADEBUGP(AAD_INFO, ("PktListOnAtmEntry: pIf %x, Pkt %x, Send failure %x\n",
  971. pInterface, pNdisPacket, Status));
  972. AtmArpFreeSendPackets(pInterface, pNdisPacket, FALSE);
  973. }
  974. }
  975. return;
  976. }
  977. PATMARP_IP_ENTRY
  978. AtmArpLearnIPToAtm(
  979. IN PATMARP_INTERFACE pInterface,
  980. IN IP_ADDRESS UNALIGNED * pIPAddress,
  981. IN UCHAR AtmAddressTypeLength,
  982. IN UCHAR UNALIGNED * pAtmAddress,
  983. IN UCHAR AtmSubaddressTypeLength,
  984. IN UCHAR UNALIGNED * pAtmSubaddress,
  985. IN BOOLEAN IsStaticEntry
  986. )
  987. /*++
  988. Routine Description:
  989. Learn an IP address to ATM address mapping. This is normally
  990. called when we receive an ARP reply from the ARP server.
  991. It may also be called to set up a static mapping.
  992. We take care of the case where either the IP address or the
  993. ATM address (or both) may already exist in the ARP Table: we
  994. only create the entries that are not present. For example, it
  995. is possible for multiple IP addresses to map to the same ATM
  996. address -- in this case, we might find an existing ATM entry
  997. for a new IP entry.
  998. Arguments:
  999. pInterface - Pointer to ATMARP Interface
  1000. pIPAddress - IP address
  1001. AtmAddressTypeLength - Type+Length (ARP packet format) for ATM address
  1002. pAtmAddress - ATM Number
  1003. AtmSubaddressTypeLength - Type+Length (ARP packet format) for ATM subaddress
  1004. pAtmSubaddress - ATM Subaddress
  1005. IsStaticEntry - Is this a static mapping?
  1006. Return Value:
  1007. A pointer to the IP Entry that was learned/refreshed.
  1008. --*/
  1009. {
  1010. PATMARP_IP_ENTRY pIpEntry; // Entry for this IP Address
  1011. PATMARP_ATM_ENTRY pAtmEntry; // Entry for this ATM Address
  1012. NDIS_STATUS Status;
  1013. BOOLEAN TimerWasRunning; // Was a timer running on IP Entry?
  1014. ULONG rc; // Ref Count
  1015. PNDIS_PACKET pPacketList;// List of queued packets, if any
  1016. BOOLEAN IsBroadcast;// Is the IP address broadcast/multicast?
  1017. #ifdef CUBDD
  1018. SINGLE_LIST_ENTRY PendingIrpList;
  1019. PATM_ADDRESS pResolvedAddress;
  1020. #endif // CUBDD
  1021. AADEBUGP(AAD_LOUD, ("LearnIPToAtm: pIf 0x%x, IP Addr: %d:%d:%d:%d, ATM Addr:\n",
  1022. pInterface,
  1023. *((PUCHAR)pIPAddress),
  1024. *((PUCHAR)pIPAddress+1),
  1025. *((PUCHAR)pIPAddress+2),
  1026. *((PUCHAR)pIPAddress+3)));
  1027. AADEBUGPDUMP(AAD_LOUD, pAtmAddress, (AtmAddressTypeLength & ~AA_PKT_ATM_ADDRESS_BIT));
  1028. //
  1029. // Initialize
  1030. //
  1031. Status = NDIS_STATUS_SUCCESS;
  1032. pPacketList = (PNDIS_PACKET)NULL;
  1033. IsBroadcast = FALSE;
  1034. pIpEntry = NULL_PATMARP_IP_ENTRY;
  1035. #ifdef CUBDD
  1036. PendingIrpList.Next = (PSINGLE_LIST_ENTRY)NULL;
  1037. #endif // CUBDD
  1038. AA_ACQUIRE_IF_TABLE_LOCK(pInterface);
  1039. //
  1040. // Get an ATM Entry. AtmArpSearchForAtmAddress addrefs
  1041. // the entry, so be sure to dereference it if
  1042. // we're not going to be using it.
  1043. //
  1044. pAtmEntry = AtmArpSearchForAtmAddress(
  1045. pInterface,
  1046. AtmAddressTypeLength,
  1047. pAtmAddress,
  1048. AtmSubaddressTypeLength,
  1049. pAtmSubaddress,
  1050. AE_REFTYPE_IE,
  1051. TRUE // Create new entry if not found
  1052. );
  1053. if (pAtmEntry != NULL_PATMARP_ATM_ENTRY)
  1054. {
  1055. AADEBUGPMAP(AAD_INFO, "Learnt", pIPAddress, &pAtmEntry->ATMAddress);
  1056. //
  1057. // Now get an IP Address Entry. AtmArpSeachForIPAddress addrefs
  1058. // the entry, so be sure to deref it if we're not going to be
  1059. // using it.
  1060. //
  1061. pIpEntry = AtmArpSearchForIPAddress(
  1062. pInterface,
  1063. pIPAddress,
  1064. IE_REFTYPE_AE,
  1065. FALSE, // this isn't multicast/broadcast
  1066. TRUE // Create new entry if not found
  1067. );
  1068. if (pIpEntry != NULL_PATMARP_IP_ENTRY)
  1069. {
  1070. AA_ACQUIRE_IE_LOCK_DPC(pIpEntry);
  1071. AA_ASSERT(AA_IE_IS_ALIVE(pIpEntry));
  1072. //
  1073. // Got both entries.
  1074. //
  1075. // Check for conflict: if the IP Entry existed before, see if
  1076. // it is linked to a different ATM Entry. If so, we have a new
  1077. // mapping that violates an existing mapping. We discard this
  1078. // new information.
  1079. //
  1080. if (pIpEntry->pAtmEntry != NULL_PATMARP_ATM_ENTRY)
  1081. {
  1082. if (pIpEntry->pAtmEntry != pAtmEntry)
  1083. {
  1084. AADEBUGP(AAD_ERROR,
  1085. ("IP Entry 0x%x linked to ATM Entry 0x%x, new ATM Entry 0x%x\n",
  1086. pIpEntry, pIpEntry->pAtmEntry, pAtmEntry));
  1087. Status = NDIS_STATUS_FAILURE;
  1088. }
  1089. else
  1090. {
  1091. //
  1092. // An existing mapping has been reconfirmed.
  1093. //
  1094. AADEBUGP(AAD_INFO,
  1095. ("Revalidated IP Entry 0x%x, Addr: %d.%d.%d.%d, PktList 0x%x\n",
  1096. pIpEntry,
  1097. ((PUCHAR)pIPAddress)[0],
  1098. ((PUCHAR)pIPAddress)[1],
  1099. ((PUCHAR)pIPAddress)[2],
  1100. ((PUCHAR)pIPAddress)[3],
  1101. pIpEntry->PacketList
  1102. ));
  1103. #ifdef CUBDD
  1104. //
  1105. // Remove the list of IRPs pending on this IP Entry, if any.
  1106. //
  1107. PendingIrpList = pIpEntry->PendingIrpList;
  1108. pIpEntry->PendingIrpList.Next = (PSINGLE_LIST_ENTRY)NULL;
  1109. #endif // CUBDD
  1110. //
  1111. // Update IP Entry state.
  1112. //
  1113. AA_SET_FLAG(
  1114. pIpEntry->Flags,
  1115. AA_IP_ENTRY_STATE_MASK,
  1116. AA_IP_ENTRY_RESOLVED);
  1117. //
  1118. // Remove the list of packets queued on this entry.
  1119. //
  1120. pPacketList = pIpEntry->PacketList;
  1121. pIpEntry->PacketList = (PNDIS_PACKET)NULL;
  1122. if (pPacketList)
  1123. {
  1124. //
  1125. // We'll be sending out these packets on the
  1126. // atm entry, so better put a tempref on the atm
  1127. // entry now. It is derefed when the packet
  1128. // list is finished being sent on the atm entry.
  1129. //
  1130. AA_ACQUIRE_AE_LOCK_DPC(pAtmEntry);
  1131. AA_REF_AE(pAtmEntry, AE_REFTYPE_TMP);// Temp ref: Pkt list.
  1132. AA_RELEASE_AE_LOCK_DPC(pAtmEntry);
  1133. }
  1134. //
  1135. // We will start the IP Entry aging timer on this
  1136. // entry.
  1137. //
  1138. //
  1139. // Stop the Address resolution timer running here
  1140. //
  1141. TimerWasRunning = AtmArpStopTimer(&(pIpEntry->Timer), pInterface);
  1142. if (TimerWasRunning)
  1143. {
  1144. rc = AA_DEREF_IE(pIpEntry, IE_REFTYPE_TIMER); // timer ref.
  1145. AA_ASSERT(rc != 0);
  1146. }
  1147. //
  1148. // Start the Aging timer.
  1149. //
  1150. AtmArpStartTimer(
  1151. pInterface,
  1152. &(pIpEntry->Timer),
  1153. AtmArpIPEntryAgingTimeout,
  1154. pInterface->ARPEntryAgingTimeout,
  1155. (PVOID)pIpEntry
  1156. );
  1157. //
  1158. // Altough we got the initial ref in SearchForIPAddress
  1159. // for IE_REFTYPE_AE, we're actually using it for
  1160. // the timer reference. So we need to switch the reftype
  1161. // here...
  1162. //
  1163. // This reftype stuff is just for tracking purposes.
  1164. //
  1165. AA_SWITCH_IE_REFTYPE(
  1166. pIpEntry,
  1167. IE_REFTYPE_AE,
  1168. IE_REFTYPE_TIMER
  1169. );
  1170. }
  1171. }
  1172. else
  1173. {
  1174. //
  1175. // This IP Entry wasn't mapped to an ATM Entry previously.
  1176. // Link entries together: first, make the IP entry point
  1177. // to this ATM Entry.
  1178. //
  1179. AA_ACQUIRE_AE_LOCK_DPC(pAtmEntry);
  1180. //
  1181. // Check if this is still a valid entry....
  1182. //
  1183. if (AA_IS_FLAG_SET(
  1184. pAtmEntry->Flags,
  1185. AA_ATM_ENTRY_STATE_MASK,
  1186. AA_ATM_ENTRY_CLOSING))
  1187. {
  1188. AA_RELEASE_AE_LOCK_DPC(pAtmEntry);
  1189. Status = NDIS_STATUS_FAILURE;
  1190. }
  1191. else
  1192. {
  1193. pIpEntry->pAtmEntry = pAtmEntry;
  1194. AA_SET_FLAG(
  1195. pAtmEntry->Flags,
  1196. AA_ATM_ENTRY_STATE_MASK,
  1197. AA_ATM_ENTRY_ACTIVE);
  1198. //
  1199. // Add the IP Entry to the ATM Entry's list of IP Entries
  1200. // (multiple IP entries could point to the same ATM Entry).
  1201. //
  1202. pIpEntry->pNextToAtm = pAtmEntry->pIpEntryList;
  1203. pAtmEntry->pIpEntryList = pIpEntry;
  1204. //
  1205. // Remove the list of packets queued on this IP entry.
  1206. //
  1207. pPacketList = pIpEntry->PacketList;
  1208. pIpEntry->PacketList = (PNDIS_PACKET)NULL;
  1209. if (pPacketList)
  1210. {
  1211. AA_REF_AE(pAtmEntry, AE_REFTYPE_TMP);// Temp ref: Pkt list.
  1212. }
  1213. AA_RELEASE_AE_LOCK_DPC(pAtmEntry);
  1214. //
  1215. // Update IP Entry state.
  1216. //
  1217. AA_SET_FLAG(
  1218. pIpEntry->Flags,
  1219. AA_IP_ENTRY_STATE_MASK,
  1220. AA_IP_ENTRY_RESOLVED);
  1221. TimerWasRunning = AtmArpStopTimer(&(pIpEntry->Timer), pInterface);
  1222. if (TimerWasRunning)
  1223. {
  1224. ULONG rc;
  1225. rc = AA_DEREF_IE(pIpEntry, IE_REFTYPE_TIMER); // Timer reference
  1226. AA_ASSERT(rc > 0);
  1227. }
  1228. IsBroadcast = AA_IS_FLAG_SET(pIpEntry->Flags,
  1229. AA_IP_ENTRY_ADDR_TYPE_MASK,
  1230. AA_IP_ENTRY_ADDR_TYPE_NUCAST);
  1231. #ifdef CUBDD
  1232. //
  1233. // Remove the list of IRPs pending on this IP Entry, if any.
  1234. //
  1235. PendingIrpList = pIpEntry->PendingIrpList;
  1236. pIpEntry->PendingIrpList.Next = (PSINGLE_LIST_ENTRY)NULL;
  1237. #endif // CUBDD
  1238. if (IsStaticEntry)
  1239. {
  1240. pIpEntry->Flags |= AA_IP_ENTRY_IS_STATIC;
  1241. }
  1242. else
  1243. {
  1244. //
  1245. // Start the aging timer on this IP Entry.
  1246. //
  1247. AtmArpStartTimer(
  1248. pInterface,
  1249. &(pIpEntry->Timer),
  1250. AtmArpIPEntryAgingTimeout,
  1251. pInterface->ARPEntryAgingTimeout,
  1252. (PVOID)pIpEntry
  1253. );
  1254. AA_REF_IE(pIpEntry, IE_REFTYPE_TIMER); // Timer reference
  1255. }
  1256. }
  1257. }
  1258. AA_RELEASE_IE_LOCK_DPC(pIpEntry);
  1259. }
  1260. else
  1261. {
  1262. //
  1263. // Failed to locate/allocate IP Entry
  1264. //
  1265. Status = NDIS_STATUS_RESOURCES;
  1266. }
  1267. }
  1268. else
  1269. {
  1270. //
  1271. // Failed to locate/allocate ATM Entry
  1272. //
  1273. Status = NDIS_STATUS_RESOURCES;
  1274. }
  1275. AA_RELEASE_IF_TABLE_LOCK(pInterface);
  1276. if (Status == NDIS_STATUS_SUCCESS)
  1277. {
  1278. //
  1279. // If we have any queued packets to send, send them now.
  1280. //
  1281. if (pPacketList != (PNDIS_PACKET)NULL)
  1282. {
  1283. AtmArpSendPacketListOnAtmEntry(
  1284. pInterface,
  1285. pAtmEntry,
  1286. pPacketList,
  1287. IsBroadcast
  1288. );
  1289. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  1290. rc = AA_DEREF_AE(pAtmEntry, AE_REFTYPE_TMP); // Send pkt list.
  1291. if (rc>0)
  1292. {
  1293. AA_RELEASE_AE_LOCK(pAtmEntry);
  1294. }
  1295. }
  1296. }
  1297. else
  1298. {
  1299. if (pIpEntry)
  1300. {
  1301. AA_ACQUIRE_IE_LOCK(pIpEntry);
  1302. AA_ASSERT(AA_IE_IS_ALIVE(pIpEntry));
  1303. rc = AA_DEREF_IE(pIpEntry, IE_REFTYPE_AE); // LearnIPAtm
  1304. if (rc>0)
  1305. {
  1306. AA_RELEASE_IE_LOCK(pIpEntry);
  1307. }
  1308. }
  1309. if (pAtmEntry)
  1310. {
  1311. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  1312. rc = AA_DEREF_AE(pAtmEntry, AE_REFTYPE_IE); // LearnIPAtm
  1313. if (rc>0)
  1314. {
  1315. AA_RELEASE_AE_LOCK(pAtmEntry);
  1316. }
  1317. }
  1318. //
  1319. // Prepare the return value.
  1320. //
  1321. pIpEntry = NULL_PATMARP_IP_ENTRY;
  1322. }
  1323. #if !BINARY_COMPATIBLE
  1324. #ifdef CUBDD
  1325. if (PendingIrpList.Next != (PSINGLE_LIST_ENTRY)NULL)
  1326. {
  1327. AA_ALLOC_MEM(pResolvedAddress, ATM_ADDRESS, sizeof(ATM_ADDRESS));
  1328. if (pResolvedAddress != (PATM_ADDRESS)NULL)
  1329. {
  1330. AA_PKT_TYPE_LEN_TO_ATM_ADDRESS(
  1331. AtmAddressTypeLength,
  1332. &(pResolvedAddress->AddressType),
  1333. &(pResolvedAddress->NumberOfDigits));
  1334. AA_COPY_MEM(
  1335. pResolvedAddress->Address,
  1336. pAtmAddress,
  1337. ATM_ADDRESS_LENGTH);
  1338. }
  1339. AtmArpCompleteArpIrpList(
  1340. PendingIrpList,
  1341. pResolvedAddress
  1342. );
  1343. }
  1344. #endif // CUBDD
  1345. #endif // !BINARY_COMPATIBLE
  1346. return (pIpEntry);
  1347. }
  1348. NDIS_STATUS
  1349. AtmArpQueuePacketOnIPEntry(
  1350. IN PATMARP_IP_ENTRY pIpEntry,
  1351. IN PNDIS_PACKET pNdisPacket
  1352. )
  1353. /*++
  1354. Routine Description:
  1355. Queue a packet on an unresolved IP Entry, unless one of the following
  1356. conditions holds:
  1357. - We recently got an ARP NAK while trying to resolve this entry. In this
  1358. case, there is no point in queueing up this packet and sending another
  1359. ARP Request, because we might immediately get back another NAK.
  1360. If we did queue this packet, we check if address resolution is in progress
  1361. on this entry. If not, start it.
  1362. Arguments:
  1363. pIpEntry - Pointer to ATMARP IP Entry
  1364. pNdisPacket - Packet to be queued
  1365. Locks on entry:
  1366. IP Entry
  1367. Locks on exit:
  1368. None
  1369. Return Value:
  1370. NDIS_STATUS_PENDING if we did queue the packet, NDIS_STATUS_FAILURE
  1371. otherwise.
  1372. --*/
  1373. {
  1374. PATMARP_INTERFACE pInterface;
  1375. PNDIS_PACKET pPrevPacket; // For queueing this packet
  1376. NDIS_STATUS Status; // Return value
  1377. IP_ADDRESS SrcIPAddress; // For ARP Request, if required
  1378. IP_ADDRESS DstIPAddress; // For ARP Request, if required
  1379. pInterface = pIpEntry->pInterface;
  1380. //
  1381. // Check if this IP address has experienced an ARP NAK recently.
  1382. // If not, we queue this packet, else we discard it.
  1383. //
  1384. // We also make sure that the ip entry is in ARP table (it had better be,
  1385. // but it's possible that we enter this code path just after the ip
  1386. // entry has been).
  1387. //
  1388. if (!AA_IS_FLAG_SET(pIpEntry->Flags,
  1389. AA_IP_ENTRY_STATE_MASK,
  1390. AA_IP_ENTRY_SEEN_NAK)
  1391. && AA_IE_IS_ALIVE(pIpEntry))
  1392. {
  1393. //
  1394. // Queue the packet.
  1395. //
  1396. if (pIpEntry->PacketList == (PNDIS_PACKET)NULL)
  1397. {
  1398. //
  1399. // No packets on this IP Entry.
  1400. //
  1401. pIpEntry->PacketList = pNdisPacket;
  1402. }
  1403. else
  1404. {
  1405. //
  1406. // Go to the end of the packet list on this IP Entry.
  1407. //
  1408. pPrevPacket = pIpEntry->PacketList;
  1409. while (AA_GET_NEXT_PACKET(pPrevPacket) != (PNDIS_PACKET)NULL)
  1410. {
  1411. pPrevPacket = AA_GET_NEXT_PACKET(pPrevPacket);
  1412. }
  1413. //
  1414. // Found the last packet in the list. Chain this packet
  1415. // to it.
  1416. //
  1417. AA_SET_NEXT_PACKET(pPrevPacket, pNdisPacket);
  1418. }
  1419. AA_SET_NEXT_PACKET(pNdisPacket, NULL);
  1420. Status = NDIS_STATUS_PENDING;
  1421. //
  1422. // If needed, start resolving this IP address.
  1423. //
  1424. AtmArpResolveIpEntry(pIpEntry);
  1425. //
  1426. // The IE Lock is released within the above.
  1427. //
  1428. }
  1429. else
  1430. {
  1431. //
  1432. // We have seen an ARP NAK for this IP address recently, or
  1433. // this pIpEntry is not alive.
  1434. // Drop this packet.
  1435. //
  1436. AA_RELEASE_IE_LOCK(pIpEntry);
  1437. Status = NDIS_STATUS_FAILURE;
  1438. }
  1439. return (Status);
  1440. }
  1441. BOOLEAN
  1442. AtmArpAtmEntryIsReallyClosing(
  1443. PATMARP_ATM_ENTRY pAtmEntry
  1444. )
  1445. {
  1446. BOOLEAN fRet = FALSE;
  1447. if (AA_IS_FLAG_SET(
  1448. pAtmEntry->Flags,
  1449. AA_ATM_ENTRY_STATE_MASK,
  1450. AA_ATM_ENTRY_CLOSING))
  1451. {
  1452. AADEBUGP(AAD_INFO, ("IsReallyClosing -- ENTRY (0x%08lx) is CLOSING\n",
  1453. pAtmEntry));
  1454. //
  1455. // Decide whether we want to clear the CLOSING state here..
  1456. // We clear the closing state because we saw a case where the
  1457. // entry was permanently in the closing state (a ref count problem).
  1458. // So we will clear this state if it is basically an idle entry,
  1459. // so that it may be reused.
  1460. //
  1461. if ( pAtmEntry->pIpEntryList == NULL
  1462. && pAtmEntry->pVcList == NULL
  1463. && ( pAtmEntry->pMcAtmInfo == NULL
  1464. || pAtmEntry->pMcAtmInfo->pMcAtmMigrateList == NULL))
  1465. {
  1466. AADEBUGP(AAD_INFO,
  1467. ("IsReallyClosing -- ENTRY (0x%08lx) CLEARING CLOSING STATE\n",
  1468. pAtmEntry));
  1469. AA_SET_FLAG(
  1470. pAtmEntry->Flags,
  1471. AA_ATM_ENTRY_STATE_MASK,
  1472. AA_ATM_ENTRY_ACTIVE);
  1473. }
  1474. else
  1475. {
  1476. fRet = TRUE;
  1477. }
  1478. }
  1479. return fRet;
  1480. }
  1481. PATMARP_ATM_ENTRY
  1482. AtmArpSearchForAtmAddress(
  1483. IN PATMARP_INTERFACE pInterface,
  1484. IN UCHAR AtmAddressTypeLength,
  1485. IN UCHAR UNALIGNED * pAtmAddress,
  1486. IN UCHAR AtmSubaddressTypeLength,
  1487. IN UCHAR UNALIGNED * pAtmSubaddress,
  1488. IN AE_REFTYPE RefType,
  1489. IN BOOLEAN CreateNew
  1490. )
  1491. /*++
  1492. Routine Description:
  1493. Search for an ATM Entry that matches the given ATM number+subaddress.
  1494. Optionally, create one if there is no match.
  1495. The caller is assumed to hold a lock to the IF Table.
  1496. Arguments:
  1497. pInterface - Pointer to ATMARP Interface
  1498. AtmAddressTypeLength - Type+Length (ARP packet format) for the ATM number
  1499. pAtmAddress - ATM Number
  1500. AtmSubaddressTypeLength - Type+Length (ARP packet format) for the ATM subaddress
  1501. pAtmSubaddress - ATM Subaddress
  1502. CreateNew - Do we create a new entry if we don't find one?
  1503. RefType - Type of reference
  1504. Return Value:
  1505. Pointer to a matching ATM Entry if found (or created anew).
  1506. --*/
  1507. {
  1508. PATMARP_ATM_ENTRY pAtmEntry;
  1509. BOOLEAN Found;
  1510. ATM_ADDRESSTYPE AddressType;
  1511. ULONG AddressLen;
  1512. ATM_ADDRESSTYPE SubaddressType;
  1513. ULONG SubaddressLen;
  1514. AA_PKT_TYPE_LEN_TO_ATM_ADDRESS(AtmAddressTypeLength, &AddressType, &AddressLen);
  1515. AA_PKT_TYPE_LEN_TO_ATM_ADDRESS(AtmSubaddressTypeLength, &SubaddressType, &SubaddressLen);
  1516. AA_ACQUIRE_IF_ATM_LIST_LOCK(pInterface);
  1517. //
  1518. // Go through the list of ATM Entries on this interface, provided the
  1519. // list is "up." The list is not up when shutting down the interface.
  1520. //
  1521. Found = FALSE;
  1522. if (pInterface->AtmEntryListUp)
  1523. {
  1524. pAtmEntry = pInterface->pAtmEntryList;
  1525. }
  1526. else
  1527. {
  1528. pAtmEntry = NULL;
  1529. }
  1530. for (; pAtmEntry != NULL_PATMARP_ATM_ENTRY; pAtmEntry = pAtmEntry->pNext)
  1531. {
  1532. //
  1533. // Compare the ATM Addresses
  1534. //
  1535. if ((AddressType == pAtmEntry->ATMAddress.AddressType) &&
  1536. (AddressLen == pAtmEntry->ATMAddress.NumberOfDigits) &&
  1537. (AA_MEM_CMP(pAtmAddress, pAtmEntry->ATMAddress.Address, AddressLen) == 0))
  1538. {
  1539. //
  1540. // Compare the Subaddress parts
  1541. //
  1542. if ((SubaddressType == pAtmEntry->ATMSubaddress.AddressType) &&
  1543. (SubaddressLen == pAtmEntry->ATMSubaddress.NumberOfDigits) &&
  1544. (AA_MEM_CMP(pAtmSubaddress, pAtmEntry->ATMSubaddress.Address, SubaddressLen) == 0))
  1545. {
  1546. Found = TRUE;
  1547. //
  1548. // WARNING: AtmArpAtmEntryIsReallyClosing may clear the
  1549. // CLOSING state (if the entry is basically idle) --
  1550. // see comments in that function.
  1551. //
  1552. if (AtmArpAtmEntryIsReallyClosing(pAtmEntry))
  1553. {
  1554. //
  1555. // We don't allow creating a new entry in this case...
  1556. //
  1557. CreateNew = FALSE;
  1558. pAtmEntry = NULL;
  1559. Found = FALSE;
  1560. }
  1561. break;
  1562. }
  1563. }
  1564. }
  1565. if (!Found && CreateNew && pInterface->AtmEntryListUp)
  1566. {
  1567. pAtmEntry = AtmArpAllocateAtmEntry(
  1568. pInterface,
  1569. FALSE // Not multicast
  1570. );
  1571. if (pAtmEntry != NULL_PATMARP_ATM_ENTRY)
  1572. {
  1573. //
  1574. // Fill in this new entry.
  1575. //
  1576. pAtmEntry->Flags = AA_ATM_ENTRY_ACTIVE;
  1577. //
  1578. // The ATM Address.
  1579. //
  1580. pAtmEntry->ATMAddress.AddressType = AddressType;
  1581. pAtmEntry->ATMAddress.NumberOfDigits = AddressLen;
  1582. AA_COPY_MEM(pAtmEntry->ATMAddress.Address,
  1583. pAtmAddress,
  1584. AddressLen);
  1585. //
  1586. // The ATM Subaddress.
  1587. //
  1588. pAtmEntry->ATMSubaddress.AddressType = SubaddressType;
  1589. pAtmEntry->ATMSubaddress.NumberOfDigits = SubaddressLen;
  1590. AA_COPY_MEM(pAtmEntry->ATMSubaddress.Address,
  1591. pAtmSubaddress,
  1592. SubaddressLen);
  1593. //
  1594. // Link in this entry to the Interface
  1595. //
  1596. pAtmEntry->pNext = pInterface->pAtmEntryList;
  1597. pInterface->pAtmEntryList = pAtmEntry;
  1598. }
  1599. }
  1600. if (pAtmEntry)
  1601. {
  1602. AA_ACQUIRE_AE_LOCK_DPC(pAtmEntry);
  1603. AA_REF_AE(pAtmEntry,RefType); // AtmArpSearchForAtmAddress
  1604. AA_RELEASE_AE_LOCK_DPC(pAtmEntry);
  1605. }
  1606. AA_RELEASE_IF_ATM_LIST_LOCK(pInterface);
  1607. AADEBUGP(AAD_VERY_LOUD, ("SearchForAtm: returning (%s) ATM Entry 0x%x for addr:\n",
  1608. (Found? "Old": "New"), pAtmEntry));
  1609. AADEBUGPDUMP(AAD_VERY_LOUD, pAtmAddress, AddressLen);
  1610. return (pAtmEntry);
  1611. }
  1612. PATMARP_IP_ENTRY
  1613. AtmArpSearchForIPAddress(
  1614. PATMARP_INTERFACE pInterface,
  1615. IP_ADDRESS UNALIGNED * pIPAddress,
  1616. IE_REFTYPE RefType,
  1617. BOOLEAN IsMulticast,
  1618. BOOLEAN CreateNew
  1619. )
  1620. /*++
  1621. Routine Description:
  1622. Search for an IP Address in the ARP Table. Optionally, create one
  1623. if a match is not found.
  1624. The caller is assumed to hold a lock to the IF Table.
  1625. Arguments:
  1626. pInterface - Pointer to ATMARP Interface
  1627. pIPAddress - what we are looking for
  1628. IsMulticast - Is this IP address broadcast or multicast?
  1629. RefType - Type of reference to use when we addref the entry.
  1630. CreateNew - Should a new entry be created if no match?
  1631. Return Value:
  1632. Pointer to a matching IP Entry if found (or created anew).
  1633. --*/
  1634. {
  1635. ULONG HashIndex;
  1636. PATMARP_IP_ENTRY pIpEntry;
  1637. BOOLEAN Found;
  1638. #ifdef IPMCAST
  1639. PATMARP_ATM_ENTRY pAtmEntry;
  1640. IP_ADDRESS IPAddressValue;
  1641. PATMARP_IP_ENTRY * ppIpEntry;
  1642. #endif // IPMCAST
  1643. HashIndex = ATMARP_HASH(*pIPAddress);
  1644. Found = FALSE;
  1645. pIpEntry = pInterface->pArpTable[HashIndex];
  1646. //
  1647. // Go through the addresses in this hash list.
  1648. //
  1649. while (pIpEntry != NULL_PATMARP_IP_ENTRY)
  1650. {
  1651. if (IP_ADDR_EQUAL(pIpEntry->IPAddress, *pIPAddress))
  1652. {
  1653. Found = TRUE;
  1654. break;
  1655. }
  1656. pIpEntry = pIpEntry->pNextEntry;
  1657. }
  1658. if (!Found && CreateNew && pInterface->ArpTableUp)
  1659. {
  1660. do
  1661. {
  1662. pIpEntry = AtmArpAllocateIPEntry(pInterface);
  1663. if (pIpEntry == NULL_PATMARP_IP_ENTRY)
  1664. {
  1665. break;
  1666. }
  1667. #ifdef IPMCAST
  1668. if (IsMulticast)
  1669. {
  1670. AAMCDEBUGP(AAD_INFO,
  1671. ("SearchForIpAddr: Creating new MC IP Entry 0x%x for Addr %d.%d.%d.%d\n",
  1672. pIpEntry,
  1673. ((PUCHAR)pIPAddress)[0],
  1674. ((PUCHAR)pIPAddress)[1],
  1675. ((PUCHAR)pIPAddress)[2],
  1676. ((PUCHAR)pIPAddress)[3]));
  1677. pIpEntry->Flags |= AA_IP_ENTRY_ADDR_TYPE_NUCAST;
  1678. //
  1679. // Also link this IP Entry into the per-Interface list
  1680. // of multicast addresses. This is sorted in ascending
  1681. // order of "IP Address value", to help processing
  1682. // <Min, Max> pairs of addresses in JOIN/LEAVE messages.
  1683. //
  1684. IPAddressValue = NET_LONG(*pIPAddress);
  1685. //
  1686. // Find the place to insert this entry at.
  1687. //
  1688. for (ppIpEntry = &(pInterface->pMcSendList);
  1689. *ppIpEntry != NULL_PATMARP_IP_ENTRY;
  1690. ppIpEntry = &((*ppIpEntry)->pNextMcEntry))
  1691. {
  1692. if (NET_LONG((*ppIpEntry)->IPAddress) > IPAddressValue)
  1693. {
  1694. //
  1695. // Found it.
  1696. //
  1697. break;
  1698. }
  1699. }
  1700. pIpEntry->pNextMcEntry = *ppIpEntry;
  1701. *ppIpEntry = pIpEntry;
  1702. }
  1703. else
  1704. {
  1705. AAMCDEBUGP(AAD_INFO,
  1706. ("SearchForIpAddr: Creating new UNI IP Entry 0x%x for Addr %d.%d.%d.%d\n",
  1707. pIpEntry,
  1708. ((PUCHAR)pIPAddress)[0],
  1709. ((PUCHAR)pIPAddress)[1],
  1710. ((PUCHAR)pIPAddress)[2],
  1711. ((PUCHAR)pIPAddress)[3]));
  1712. }
  1713. #endif // IPMCAST
  1714. //
  1715. // Fill in the rest of the IP entry.
  1716. //
  1717. pIpEntry->IPAddress = *pIPAddress;
  1718. //
  1719. // This signifies that it is in the arp table.
  1720. //
  1721. AA_SET_FLAG(pIpEntry->Flags,
  1722. AA_IP_ENTRY_STATE_MASK,
  1723. AA_IP_ENTRY_IDLE2);
  1724. AA_REF_IE(pIpEntry, IE_REFTYPE_TABLE); // ARP Table linkage
  1725. //
  1726. // Link it to the hash table.
  1727. //
  1728. pIpEntry->pNextEntry = pInterface->pArpTable[HashIndex];
  1729. pInterface->pArpTable[HashIndex] = pIpEntry;
  1730. pInterface->NumOfArpEntries++;
  1731. break;
  1732. }
  1733. while (FALSE);
  1734. } // if creating new
  1735. if (pIpEntry)
  1736. {
  1737. AA_ACQUIRE_IE_LOCK_DPC(pIpEntry);
  1738. AA_REF_IE(pIpEntry, RefType); // AtmArpSearchForIPAddress
  1739. AA_RELEASE_IE_LOCK_DPC(pIpEntry);
  1740. }
  1741. AADEBUGP(AAD_LOUD,
  1742. ("Search for IP Addr: %d.%d.%d.%d, hash ind %d, Found %d, IPEnt 0x%x\n",
  1743. ((PUCHAR)pIPAddress)[0],
  1744. ((PUCHAR)pIPAddress)[1],
  1745. ((PUCHAR)pIPAddress)[2],
  1746. ((PUCHAR)pIPAddress)[3],
  1747. HashIndex, Found, pIpEntry));
  1748. return (pIpEntry);
  1749. }
  1750. VOID
  1751. AtmArpAbortIPEntry(
  1752. IN PATMARP_IP_ENTRY pIpEntry
  1753. )
  1754. /*++
  1755. Routine Description:
  1756. Clean up and delete an IP entry. This is called when we invalidate
  1757. an ARP mapping.
  1758. NOTE: The caller is assumed to hold a lock to the IP Entry,
  1759. which will be released here.
  1760. Arguments:
  1761. pIpEntry - Pointer to IP Entry to be deleted.
  1762. Return Value:
  1763. None
  1764. --*/
  1765. {
  1766. PATMARP_INTERFACE pInterface;
  1767. PATMARP_IP_ENTRY * ppNextIpEntry;
  1768. PATMARP_ATM_ENTRY pAtmEntry;
  1769. RouteCacheEntry * pRCE;
  1770. PNDIS_PACKET PacketList;
  1771. ULONG rc; // Ref Count on IP Entry.
  1772. BOOLEAN IsMulticastIpEntry;
  1773. BOOLEAN Found;
  1774. BOOLEAN TimerWasRunning;
  1775. BOOLEAN IfTableLockReleased;
  1776. ULONG HashIndex; // For this IP Entry in ARP Table
  1777. AADEBUGP(AAD_INFO,
  1778. ("Abort IP entry 0x%x, Flags 0x%x, ATM Entry 0x%x, IP Addr %d:%d:%d:%d\n",
  1779. pIpEntry,
  1780. pIpEntry->Flags,
  1781. pIpEntry->pAtmEntry,
  1782. ((PUCHAR)&(pIpEntry->IPAddress))[0],
  1783. ((PUCHAR)&(pIpEntry->IPAddress))[1],
  1784. ((PUCHAR)&(pIpEntry->IPAddress))[2],
  1785. ((PUCHAR)&(pIpEntry->IPAddress))[3]
  1786. ));
  1787. //
  1788. // Initialize.
  1789. //
  1790. rc = pIpEntry->RefCount;
  1791. pInterface = pIpEntry->pInterface;
  1792. #ifdef IPMCAST
  1793. IsMulticastIpEntry = (AA_IS_FLAG_SET(pIpEntry->Flags,
  1794. AA_IP_ENTRY_ADDR_TYPE_MASK,
  1795. AA_IP_ENTRY_ADDR_TYPE_NUCAST));
  1796. #endif
  1797. IfTableLockReleased = FALSE;
  1798. //
  1799. // Reacquire the desired locks in the right order.
  1800. //
  1801. AA_RELEASE_IE_LOCK(pIpEntry);
  1802. AA_ACQUIRE_IF_TABLE_LOCK(pInterface);
  1803. AA_ACQUIRE_IE_LOCK(pIpEntry);
  1804. AA_ASSERT(AA_IE_IS_ALIVE(pIpEntry));
  1805. //
  1806. // Remove any packets queued on this IP Entry.
  1807. //
  1808. PacketList = pIpEntry->PacketList;
  1809. pIpEntry->PacketList = (PNDIS_PACKET)NULL;
  1810. do
  1811. {
  1812. #ifdef IPMCAST
  1813. //
  1814. // If this is a Non-unicast entry, unlink it from the list
  1815. // of Multicast IP Entries on this Interface.
  1816. //
  1817. if (IsMulticastIpEntry)
  1818. {
  1819. for (ppNextIpEntry = &(pInterface->pMcSendList);
  1820. *ppNextIpEntry != NULL_PATMARP_IP_ENTRY;
  1821. ppNextIpEntry = &((*ppNextIpEntry)->pNextMcEntry))
  1822. {
  1823. if (*ppNextIpEntry == pIpEntry)
  1824. {
  1825. //
  1826. // Unlink it.
  1827. //
  1828. *ppNextIpEntry = pIpEntry->pNextMcEntry;
  1829. break;
  1830. }
  1831. }
  1832. AAMCDEBUGP(AAD_VERY_LOUD,
  1833. ("AbortIPEntry (MC): pIpEntry 0x%x: unlinked from MC list\n", pIpEntry));
  1834. }
  1835. #endif // IPMCAST
  1836. //
  1837. // Unlink this IP Entry from all Route Cache Entries
  1838. // that point to it.
  1839. //
  1840. pRCE = pIpEntry->pRCEList;
  1841. while (pRCE != (RouteCacheEntry *)NULL)
  1842. {
  1843. Found = AtmArpUnlinkRCE(pRCE, pIpEntry);
  1844. AA_ASSERT(Found);
  1845. rc = AA_DEREF_IE(pIpEntry, IE_REFTYPE_RCE); // RCE linkage ref
  1846. if (rc > 0)
  1847. {
  1848. pRCE = pIpEntry->pRCEList;
  1849. }
  1850. else
  1851. {
  1852. pRCE = (RouteCacheEntry *)NULL;
  1853. }
  1854. }
  1855. if (rc == 0)
  1856. {
  1857. // The IP Entry is gone.
  1858. break;
  1859. }
  1860. //
  1861. // Stop any timer running on the IP Entry.
  1862. //
  1863. TimerWasRunning = AtmArpStopTimer(&(pIpEntry->Timer), pInterface);
  1864. if (TimerWasRunning)
  1865. {
  1866. rc = AA_DEREF_IE(pIpEntry, IE_REFTYPE_TIMER); // Timer ref
  1867. if (rc == 0)
  1868. {
  1869. break;
  1870. }
  1871. }
  1872. //
  1873. // Unlink this IP Entry from the ARP Table, if needed.
  1874. //
  1875. Found = FALSE;
  1876. HashIndex = ATMARP_HASH(pIpEntry->IPAddress);
  1877. ppNextIpEntry = &(pInterface->pArpTable[HashIndex]);
  1878. while (*ppNextIpEntry != NULL_PATMARP_IP_ENTRY)
  1879. {
  1880. if (*ppNextIpEntry == pIpEntry)
  1881. {
  1882. //
  1883. // Make the predecessor point to the next
  1884. // in the list.
  1885. //
  1886. *ppNextIpEntry = pIpEntry->pNextEntry;
  1887. Found = TRUE;
  1888. pInterface->NumOfArpEntries--;
  1889. //
  1890. // Once it's off the arp table, we set the flag to IDLE.
  1891. //
  1892. AA_SET_FLAG(pIpEntry->Flags,
  1893. AA_IP_ENTRY_STATE_MASK,
  1894. AA_IP_ENTRY_IDLE);
  1895. break;
  1896. }
  1897. else
  1898. {
  1899. ppNextIpEntry = &((*ppNextIpEntry)->pNextEntry);
  1900. }
  1901. }
  1902. if (Found)
  1903. {
  1904. rc = AA_DEREF_IE(pIpEntry, IE_REFTYPE_TABLE); // ARP Table ref
  1905. if (rc == 0)
  1906. {
  1907. break;
  1908. }
  1909. }
  1910. //
  1911. // Do this last:
  1912. // ------------
  1913. // If this IP Entry is linked to an ATM Entry, unlink it.
  1914. // If this is a multicast ATM entry, shut down the ATM Entry, too.
  1915. //
  1916. pAtmEntry = pIpEntry->pAtmEntry;
  1917. if (pAtmEntry != NULL_PATMARP_ATM_ENTRY)
  1918. {
  1919. #ifdef IPMCAST
  1920. BOOLEAN IsMulticastAtmEntry;
  1921. pIpEntry->pAtmEntry = NULL;
  1922. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  1923. IsMulticastAtmEntry = AA_IS_FLAG_SET(pAtmEntry->Flags,
  1924. AA_ATM_ENTRY_TYPE_MASK,
  1925. AA_ATM_ENTRY_TYPE_NUCAST);
  1926. if (IsMulticastAtmEntry)
  1927. {
  1928. //
  1929. // We do this because we'll access the ATM
  1930. // Entry below, but only for the PMP case.
  1931. //
  1932. AA_REF_AE(pAtmEntry, AE_REFTYPE_TMP); // Temp ref: Abort IP Entry
  1933. }
  1934. #else
  1935. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  1936. #endif // IPMCAST
  1937. //
  1938. // Locate the position of this IP Entry in the ATM Entry's list.
  1939. //
  1940. ppNextIpEntry = &(pAtmEntry->pIpEntryList);
  1941. while (*ppNextIpEntry != NULL && *ppNextIpEntry != pIpEntry)
  1942. {
  1943. ppNextIpEntry = &((*ppNextIpEntry)->pNextToAtm);
  1944. }
  1945. if (*ppNextIpEntry == pIpEntry)
  1946. {
  1947. //
  1948. // Make the predecessor point to the next entry.
  1949. //
  1950. *ppNextIpEntry = pIpEntry->pNextToAtm;
  1951. rc = AA_DEREF_AE(pAtmEntry, AE_REFTYPE_IE); // IP Entry ref
  1952. if (rc != 0)
  1953. {
  1954. AA_RELEASE_AE_LOCK(pAtmEntry);
  1955. }
  1956. rc = AA_DEREF_IE(pIpEntry, IE_REFTYPE_AE); // ATM Entry linkage ref
  1957. if (rc != 0)
  1958. {
  1959. AA_ASSERT (FALSE); // we expect rc to be 0, but could be a tmp ref.
  1960. AA_RELEASE_IE_LOCK(pIpEntry);
  1961. }
  1962. }
  1963. else
  1964. {
  1965. //
  1966. // We didn't find this IP entry in the atm entry list!
  1967. // Presumably the linkage has been broken by some other
  1968. // path (probably AtmArpInvalidateAtmEntry) while we were
  1969. // in this function.
  1970. //
  1971. // We don't deref here because these two are now not linked.
  1972. //
  1973. //
  1974. AA_RELEASE_AE_LOCK(pAtmEntry);
  1975. AA_RELEASE_IE_LOCK(pIpEntry);
  1976. }
  1977. //
  1978. // IE Lock would have been released above.
  1979. //
  1980. AA_RELEASE_IF_TABLE_LOCK(pInterface);
  1981. IfTableLockReleased = TRUE;
  1982. #ifdef IPMCAST
  1983. //
  1984. // If this was a multicast entry, shut down the ATM Entry
  1985. //
  1986. if (IsMulticastAtmEntry)
  1987. {
  1988. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  1989. rc = AA_DEREF_AE(pAtmEntry, AE_REFTYPE_TMP); // Temp ref: Abort IP Entry
  1990. if (rc != 0)
  1991. {
  1992. AtmArpInvalidateAtmEntry(pAtmEntry, FALSE);
  1993. //
  1994. // AE Lock is released within the above.
  1995. //
  1996. }
  1997. }
  1998. #endif // IPMCAST
  1999. }
  2000. else
  2001. {
  2002. //
  2003. // No ATM entry linked to this IP entry.
  2004. //
  2005. AA_RELEASE_IE_LOCK(pIpEntry);
  2006. break;
  2007. }
  2008. break;
  2009. }
  2010. while (FALSE);
  2011. if (!IfTableLockReleased)
  2012. {
  2013. AA_RELEASE_IF_TABLE_LOCK(pInterface);
  2014. }
  2015. //
  2016. // Free all packets that were queued on the IP Entry.
  2017. //
  2018. AtmArpFreeSendPackets(
  2019. pInterface,
  2020. PacketList,
  2021. FALSE // No LLC/SNAP header on these
  2022. );
  2023. return;
  2024. }
  2025. VOID
  2026. AtmArpInvalidateAtmEntry(
  2027. IN PATMARP_ATM_ENTRY pAtmEntry,
  2028. IN BOOLEAN ShuttingDown
  2029. )
  2030. /*++
  2031. Routine Description:
  2032. Invalidate an ATM Entry by unlinking it from IP entries.
  2033. Typical situation:
  2034. A non-normal communication problem has been detected on a Vc going to
  2035. this ATM destination. The RFC says that we need to invalidate all IP
  2036. entries for this destination, and let them get re-resolved before sending
  2037. any traffic to them. We implement this by unlinking this ATM entry from
  2038. all IP entries it is linked to. Each such IP entry will get re-resolved
  2039. if+when we try to send a packet to it.
  2040. The only exceptions are IP Entries that have been statically mapped
  2041. to this ATM Entry: we don't unlink these, unless we are shutting down
  2042. now, as indicated by "ShuttingDown".
  2043. If we end up with no IP Entries pointing to this ATM Entry, we close all
  2044. SVCs linked to the ATM Entry. If ShuttingDown is TRUE, we close all PVCs
  2045. as well.
  2046. Arguments:
  2047. pAtmEntry - The ATM Entry needing invalidating.
  2048. ShuttingDown - TRUE iff the interface is being shut down.
  2049. Return Value:
  2050. None
  2051. --*/
  2052. {
  2053. PATMARP_IP_ENTRY pIpEntry;
  2054. PATMARP_IP_ENTRY pNextIpEntry;
  2055. ULONG rc; // Ref Count of ATM Entry
  2056. INT IPEntriesUnlinked;
  2057. PATMARP_IP_ENTRY pStaticIpEntryList; // List of static IP Entries
  2058. AA_STRUCT_ASSERT(pAtmEntry, aae);
  2059. AADEBUGP(AAD_INFO,
  2060. ("InvalidateAtmEntry: pAtmEntry 0x%x, Flags 0x%x, ShutDown %d, pIpEntryList 0x%x\n",
  2061. pAtmEntry,
  2062. pAtmEntry->Flags,
  2063. ShuttingDown,
  2064. pAtmEntry->pIpEntryList));
  2065. #ifndef PROTECT_ATM_ENTRY_IN_CLOSE_CALL
  2066. //
  2067. // Check if we are already closing this ATM Entry. If so,
  2068. // we don't do anything here.
  2069. //
  2070. if (AA_IS_FLAG_SET(
  2071. pAtmEntry->Flags,
  2072. AA_ATM_ENTRY_STATE_MASK,
  2073. AA_ATM_ENTRY_CLOSING))
  2074. {
  2075. AA_RELEASE_AE_LOCK(pAtmEntry);
  2076. return;
  2077. }
  2078. //
  2079. // Mark this ATM Entry so that we don't use it anymore.
  2080. //
  2081. AA_SET_FLAG(pAtmEntry->Flags,
  2082. AA_ATM_ENTRY_STATE_MASK,
  2083. AA_ATM_ENTRY_CLOSING);
  2084. #endif // PROTECT_ATM_ENTRY_IN_CLOSE_CALL
  2085. //
  2086. // Initialize.
  2087. //
  2088. pStaticIpEntryList = NULL_PATMARP_IP_ENTRY;
  2089. IPEntriesUnlinked = 0;
  2090. //
  2091. // Take the IP Entry list out of the ATM Entry.
  2092. //
  2093. pIpEntry = pAtmEntry->pIpEntryList;
  2094. pAtmEntry->pIpEntryList = NULL_PATMARP_IP_ENTRY;
  2095. #ifdef IPMCAST
  2096. //
  2097. // Delete the Migrate list, if any.
  2098. //
  2099. if (AA_IS_FLAG_SET(pAtmEntry->Flags,
  2100. AA_ATM_ENTRY_TYPE_MASK,
  2101. AA_ATM_ENTRY_TYPE_NUCAST))
  2102. {
  2103. PATMARP_IPMC_ATM_ENTRY pMcAtmEntry;
  2104. PATMARP_IPMC_ATM_ENTRY pNextMcAtmEntry;
  2105. for (pMcAtmEntry = pAtmEntry->pMcAtmInfo->pMcAtmMigrateList;
  2106. pMcAtmEntry != NULL_PATMARP_IPMC_ATM_ENTRY;
  2107. pMcAtmEntry = pNextMcAtmEntry)
  2108. {
  2109. pNextMcAtmEntry = pMcAtmEntry->pNextMcAtmEntry;
  2110. AA_ASSERT(!AA_IS_TIMER_ACTIVE(&pMcAtmEntry->Timer));
  2111. AA_CHECK_TIMER_IN_ACTIVE_LIST(&pMcAtmEntry->Timer, pAtmEntry->pInterface, pMcAtmEntry, "MC ATM Entry");
  2112. AA_FREE_MEM(pMcAtmEntry);
  2113. }
  2114. pAtmEntry->pMcAtmInfo->pMcAtmMigrateList = NULL_PATMARP_IPMC_ATM_ENTRY;
  2115. }
  2116. #endif // IPMCAST
  2117. //
  2118. // We let go of the ATM Entry lock here because we'll need
  2119. // to lock each IP Entry in the above list, and we need to make
  2120. // sure that we don't deadlock.
  2121. //
  2122. // However, we make sure that the ATM Entry doesn't go away
  2123. // by adding a reference to it.
  2124. //
  2125. AA_REF_AE(pAtmEntry, AE_REFTYPE_TMP); // Temp ref
  2126. AA_RELEASE_AE_LOCK(pAtmEntry);
  2127. //
  2128. // Now, unlink all IP entries that are "dynamic", and filter
  2129. // out a list of static mappings.
  2130. //
  2131. while (pIpEntry != NULL_PATMARP_IP_ENTRY)
  2132. {
  2133. AA_ACQUIRE_IE_LOCK(pIpEntry);
  2134. AA_ASSERT(AA_IE_IS_ALIVE(pIpEntry));
  2135. pNextIpEntry = pIpEntry->pNextToAtm;
  2136. if (ShuttingDown || (!AA_IS_FLAG_SET(pIpEntry->Flags,
  2137. AA_IP_ENTRY_TYPE_MASK,
  2138. AA_IP_ENTRY_IS_STATIC)))
  2139. {
  2140. AADEBUGP(AAD_INFO,
  2141. ("InvalidateATMEntry: Unlinking IP entry 0x%x, Flags 0x%x, ATM Entry 0x%x, IP Addr %d:%d:%d:%d; rc=%lu\n",
  2142. pIpEntry,
  2143. pIpEntry->Flags,
  2144. pIpEntry->pAtmEntry,
  2145. ((PUCHAR)&(pIpEntry->IPAddress))[0],
  2146. ((PUCHAR)&(pIpEntry->IPAddress))[1],
  2147. ((PUCHAR)&(pIpEntry->IPAddress))[2],
  2148. ((PUCHAR)&(pIpEntry->IPAddress))[3],
  2149. pIpEntry->RefCount
  2150. ));
  2151. //
  2152. // Remove the mapping.
  2153. //
  2154. AA_SET_FLAG(pIpEntry->Flags,
  2155. AA_IP_ENTRY_STATE_MASK,
  2156. AA_IP_ENTRY_IDLE2);
  2157. AA_SET_FLAG(pIpEntry->Flags,
  2158. AA_IP_ENTRY_MC_RESOLVE_MASK,
  2159. AA_IP_ENTRY_MC_IDLE);
  2160. pIpEntry->pAtmEntry = NULL_PATMARP_ATM_ENTRY;
  2161. pIpEntry->pNextToAtm = NULL_PATMARP_IP_ENTRY;
  2162. //
  2163. // Stop any active timer on the IP entry now that we have clobbered
  2164. // its state.
  2165. //
  2166. if (AtmArpStopTimer(&pIpEntry->Timer, pIpEntry->pInterface))
  2167. {
  2168. ULONG IpEntryRc;
  2169. IpEntryRc = AA_DEREF_IE(pIpEntry, IE_REFTYPE_TIMER);
  2170. AA_ASSERT(IpEntryRc != 0);
  2171. }
  2172. //
  2173. // Remove the ATM Entry linkage reference.
  2174. //
  2175. if (AA_DEREF_IE(pIpEntry, IE_REFTYPE_AE) != 0)
  2176. {
  2177. AA_RELEASE_IE_LOCK(pIpEntry);
  2178. }
  2179. //
  2180. // else the IP Entry is gone
  2181. //
  2182. IPEntriesUnlinked++;
  2183. }
  2184. else
  2185. {
  2186. //
  2187. // Static ARP entry, retain it.
  2188. //
  2189. pIpEntry->pNextToAtm = pStaticIpEntryList;
  2190. pStaticIpEntryList = pIpEntry;
  2191. AA_RELEASE_IE_LOCK(pIpEntry);
  2192. }
  2193. pIpEntry = pNextIpEntry;
  2194. }
  2195. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  2196. //
  2197. // Put back the static IP entries on the ATM Entry.
  2198. //
  2199. AA_ASSERT(pAtmEntry->pIpEntryList == NULL_PATMARP_IP_ENTRY);
  2200. pAtmEntry->pIpEntryList = pStaticIpEntryList;
  2201. //
  2202. // Now dereference the ATM Entry as many times as we unlinked
  2203. // IP Entries from it.
  2204. //
  2205. rc = pAtmEntry->RefCount;
  2206. while (IPEntriesUnlinked-- > 0)
  2207. {
  2208. rc = AA_DEREF_AE(pAtmEntry, AE_REFTYPE_IE); // IP Entry ref
  2209. }
  2210. AA_ASSERT(rc != 0);
  2211. //
  2212. // Take out the reference we added at the beginning of
  2213. // this routine.
  2214. //
  2215. rc = AA_DEREF_AE(pAtmEntry, AE_REFTYPE_TMP); // Temp ref
  2216. //
  2217. // Now, the only IP Entries pointing at this ATM Entry would be
  2218. // static entries. If there are no such IP entries, close all SVCs
  2219. // attached to the ATM Entry. But do all this only if the ATM Entry
  2220. // hasn't been dereferenced away already.
  2221. //
  2222. if (rc != 0)
  2223. {
  2224. //
  2225. // The ATM Entry still exists.
  2226. //
  2227. AADEBUGP(AAD_LOUD,
  2228. ("InvalidateAtmEntry: nonzero rc on exit.\n"
  2229. "\t pAE=0x%x; rc=%lu; pIpList=0x%x\n",
  2230. pAtmEntry,
  2231. pAtmEntry->RefCount,
  2232. pAtmEntry->pIpEntryList
  2233. ));
  2234. if (pAtmEntry->pIpEntryList == NULL_PATMARP_IP_ENTRY)
  2235. {
  2236. //
  2237. // No IP Entries pointing to this ATM Entry.
  2238. //
  2239. AtmArpCloseVCsOnAtmEntry(pAtmEntry, ShuttingDown);
  2240. //
  2241. // The ATM Entry lock is released within the above.
  2242. //
  2243. }
  2244. else
  2245. {
  2246. AADEBUGP(AAD_LOUD,
  2247. ("InvalidateAtmEnt: AtmEnt %x has nonempty IP list %x, reactivating\n",
  2248. pAtmEntry, pAtmEntry->pIpEntryList));
  2249. AA_SET_FLAG(
  2250. pAtmEntry->Flags,
  2251. AA_ATM_ENTRY_STATE_MASK,
  2252. AA_ATM_ENTRY_ACTIVE);
  2253. AA_RELEASE_AE_LOCK(pAtmEntry);
  2254. }
  2255. }
  2256. //
  2257. // else the ATM Entry is gone
  2258. //
  2259. return;
  2260. }
  2261. VOID
  2262. AtmArpCloseVCsOnAtmEntry(
  2263. IN PATMARP_ATM_ENTRY pAtmEntry LOCKIN NOLOCKOUT,
  2264. IN BOOLEAN ShuttingDown
  2265. )
  2266. /*++
  2267. Routine Description:
  2268. Go through the list of VCs chained to an ATM Entry, and close all
  2269. VCs that are SVCs. If the interface is being shut down, close all
  2270. PVCs as well.
  2271. NOTE: the caller is assumed to hold a lock to the ATM Entry,
  2272. which will be released here.
  2273. Arguments:
  2274. pAtmEntry - Pointer to ATM Entry on which we want to close SVCs.
  2275. ShuttingDown - TRUE iff the interface is being shut down.
  2276. Return Value:
  2277. None
  2278. --*/
  2279. {
  2280. PATMARP_VC pVc; // Used to walk the list of VCs on the ATM Entry
  2281. PATMARP_VC pCloseVcList; // List of VCs on the ATM Entry to be closed
  2282. PATMARP_VC *ppNextVc;
  2283. PATMARP_VC pNextVc;
  2284. ULONG rc; // Ref count on ATM Entry
  2285. do
  2286. {
  2287. //
  2288. // Reference the ATM Entry so that it cannot go away.
  2289. //
  2290. AA_REF_AE(pAtmEntry, AE_REFTYPE_TMP); // Temp ref: InvalidateAtmEntry
  2291. #ifdef PROTECT_ATM_ENTRY_IN_CLOSE_CALL
  2292. //
  2293. // Check if we are already closing this ATM Entry. If so,
  2294. // we don't do anything here.
  2295. //
  2296. if (AA_IS_FLAG_SET(
  2297. pAtmEntry->Flags,
  2298. AA_ATM_ENTRY_STATE_MASK,
  2299. AA_ATM_ENTRY_CLOSING))
  2300. {
  2301. break;
  2302. }
  2303. //
  2304. // Mark this ATM Entry so that we don't use it anymore.
  2305. //
  2306. AA_SET_FLAG(pAtmEntry->Flags,
  2307. AA_ATM_ENTRY_STATE_MASK,
  2308. AA_ATM_ENTRY_CLOSING);
  2309. #endif // PROTECT_ATM_ENTRY_IN_CLOSE_CALL
  2310. //
  2311. // Go through the list of VCs on this ATM Entry,
  2312. // close all SVCs, and if we are shutting down,
  2313. // all PVCs, too.
  2314. //
  2315. if (pAtmEntry->pVcList != NULL_PATMARP_VC)
  2316. {
  2317. pVc = pAtmEntry->pVcList;
  2318. AA_ACQUIRE_VC_LOCK_DPC(pVc);
  2319. AtmArpReferenceVc(pVc); // temp: CloseVCsOnAtmEntry
  2320. AA_RELEASE_VC_LOCK_DPC(pVc);
  2321. }
  2322. for (pVc = pAtmEntry->pVcList;
  2323. pVc != NULL_PATMARP_VC;
  2324. pVc = pNextVc)
  2325. {
  2326. pNextVc = pVc->pNextVc;
  2327. //
  2328. // Make sure we do not follow a stale link after
  2329. // we are done with the current VC.
  2330. //
  2331. if (pNextVc != NULL_PATMARP_VC)
  2332. {
  2333. AA_ACQUIRE_VC_LOCK_DPC(pNextVc);
  2334. AtmArpReferenceVc(pNextVc); // temp: CloseVCsOnAtmEntry
  2335. AA_RELEASE_VC_LOCK_DPC(pNextVc);
  2336. }
  2337. if (ShuttingDown || (AA_IS_FLAG_SET(pVc->Flags,
  2338. AA_VC_TYPE_MASK,
  2339. AA_VC_TYPE_SVC)))
  2340. {
  2341. AA_RELEASE_AE_LOCK(pAtmEntry);
  2342. AA_ACQUIRE_VC_LOCK(pVc);
  2343. if (AtmArpDereferenceVc(pVc) != 0)
  2344. {
  2345. AtmArpCloseCall(pVc);
  2346. //
  2347. // The VC Lock is released within the above.
  2348. //
  2349. }
  2350. }
  2351. else
  2352. {
  2353. AA_RELEASE_AE_LOCK(pAtmEntry);
  2354. AA_ACQUIRE_VC_LOCK(pVc);
  2355. if (AtmArpDereferenceVc(pVc) != 0)
  2356. {
  2357. AA_RELEASE_VC_LOCK(pVc);
  2358. }
  2359. }
  2360. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  2361. }
  2362. break;
  2363. }
  2364. while (FALSE);
  2365. //
  2366. // Remove the temp reference
  2367. //
  2368. rc = AA_DEREF_AE(pAtmEntry, AE_REFTYPE_TMP); // Temp ref: InvalidateAtmEntry
  2369. if (rc != 0)
  2370. {
  2371. AA_RELEASE_AE_LOCK(pAtmEntry);
  2372. }
  2373. //
  2374. // else the ATM Entry is gone.
  2375. //
  2376. return;
  2377. }
  2378. VOID
  2379. AtmArpResolveIpEntry(
  2380. IN PATMARP_IP_ENTRY pIpEntry LOCKIN NOLOCKOUT
  2381. )
  2382. /*++
  2383. Routine Description:
  2384. Trigger off address resolution of an IP entry, unless it's already
  2385. going on. Based on the IP address class, we either go to the ARP
  2386. server or to MARS.
  2387. NOTE: The caller is assumed to hold a lock to the IP Entry, and it
  2388. will be released here.
  2389. Arguments:
  2390. pIpEntry - IP Entry on which we want to start resolution.
  2391. Return Value:
  2392. None
  2393. --*/
  2394. {
  2395. PATMARP_INTERFACE pInterface;
  2396. IP_ADDRESS DstIPAddress;
  2397. IP_ADDRESS SrcIPAddress;
  2398. BOOLEAN WasRunning;
  2399. ULONG Flags; // From IP Entry
  2400. Flags = pIpEntry->Flags;
  2401. if (!AA_IS_FLAG_SET(
  2402. Flags,
  2403. AA_IP_ENTRY_STATE_MASK,
  2404. AA_IP_ENTRY_ARPING) &&
  2405. !AA_IS_FLAG_SET(
  2406. Flags,
  2407. AA_IP_ENTRY_STATE_MASK,
  2408. AA_IP_ENTRY_INARPING) &&
  2409. AA_IE_IS_ALIVE(pIpEntry))
  2410. {
  2411. pInterface = pIpEntry->pInterface;
  2412. //
  2413. // Get the source and destination IP addresses for
  2414. // the ARP Request.
  2415. //
  2416. DstIPAddress = pIpEntry->IPAddress;
  2417. SrcIPAddress = pInterface->LocalIPAddress.IPAddress;
  2418. //
  2419. // An aging timer might be running on this IP Entry.
  2420. // [We start one in the NakDelayTimeout routine].
  2421. // Stop it.
  2422. //
  2423. WasRunning = AtmArpStopTimer(&(pIpEntry->Timer), pInterface);
  2424. //
  2425. // Start an ARP Wait timer.
  2426. //
  2427. AtmArpStartTimer(
  2428. pInterface,
  2429. &(pIpEntry->Timer),
  2430. AtmArpAddressResolutionTimeout,
  2431. pInterface->AddressResolutionTimeout,
  2432. (PVOID)pIpEntry
  2433. );
  2434. if (!WasRunning)
  2435. {
  2436. AA_REF_IE(pIpEntry, IE_REFTYPE_TIMER); // timer ref
  2437. }
  2438. pIpEntry->RetriesLeft = pInterface->MaxResolutionAttempts - 1;
  2439. //
  2440. // Update the state on this IP Entry.
  2441. //
  2442. AA_SET_FLAG(
  2443. pIpEntry->Flags,
  2444. AA_IP_ENTRY_STATE_MASK,
  2445. AA_IP_ENTRY_ARPING);
  2446. AA_RELEASE_IE_LOCK(pIpEntry);
  2447. #ifdef IPMCAST
  2448. if (AA_IS_FLAG_SET(Flags,
  2449. AA_IP_ENTRY_ADDR_TYPE_MASK,
  2450. AA_IP_ENTRY_ADDR_TYPE_UCAST))
  2451. {
  2452. //
  2453. // Unicast address: send out an ARP Request
  2454. //
  2455. AtmArpSendARPRequest(
  2456. pInterface,
  2457. &SrcIPAddress,
  2458. &DstIPAddress
  2459. );
  2460. }
  2461. else
  2462. {
  2463. //
  2464. // Multicast/broadcast address: send a MARS Request
  2465. //
  2466. AtmArpMcSendRequest(
  2467. pInterface,
  2468. &DstIPAddress
  2469. );
  2470. }
  2471. #else
  2472. //
  2473. // Now send out the ARP Request
  2474. //
  2475. AtmArpSendARPRequest(
  2476. pInterface,
  2477. &SrcIPAddress,
  2478. &DstIPAddress
  2479. );
  2480. #endif // IPMCAST
  2481. }
  2482. else
  2483. {
  2484. //
  2485. // The IP Address is either not alived or being resolved.
  2486. // No more action needed
  2487. // here.
  2488. //
  2489. AA_RELEASE_IE_LOCK(pIpEntry);
  2490. }
  2491. return;
  2492. }
  2493. EXTERN
  2494. VOID
  2495. AtmArpCleanupArpTable(
  2496. IN PATMARP_INTERFACE pInterface
  2497. )
  2498. /*++
  2499. Routine Description:
  2500. Go through the ARP Table, deleting all multicast IP entries that
  2501. are stale (currently defined as having no link to an AtmEntry).
  2502. These IP entries stay around because mulicast entries don't have ageing timers.
  2503. Arguments:
  2504. pInterface
  2505. Return Value:
  2506. None
  2507. --*/
  2508. {
  2509. BOOLEAN fTableLockWasReleased;
  2510. AA_ACQUIRE_IF_TABLE_LOCK(pInterface);
  2511. do
  2512. {
  2513. PATMARP_IP_ENTRY pIpEntry;
  2514. fTableLockWasReleased = FALSE;
  2515. for (pIpEntry = pInterface->pMcSendList;
  2516. pIpEntry != NULL;
  2517. pIpEntry = pIpEntry->pNextMcEntry)
  2518. {
  2519. //
  2520. // NOTE: by design, we don't claim the ip entry lock when checking
  2521. // whether we should abort the entry or not.
  2522. //
  2523. if ( pIpEntry->pAtmEntry == NULL
  2524. && !AA_IS_FLAG_SET(
  2525. pIpEntry->Flags,
  2526. AA_IP_ENTRY_STATE_MASK,
  2527. AA_IP_ENTRY_ARPING))
  2528. {
  2529. //
  2530. // Get locks in the right order.
  2531. //
  2532. AA_ACQUIRE_IE_LOCK_DPC(pIpEntry);
  2533. AA_ASSERT(AA_IE_IS_ALIVE(pIpEntry));
  2534. AA_REF_IE(pIpEntry, IE_REFTYPE_TMP); // TmpRef
  2535. AA_RELEASE_IE_LOCK_DPC(pIpEntry);
  2536. AA_RELEASE_IF_TABLE_LOCK(pInterface);
  2537. AA_ACQUIRE_IE_LOCK(pIpEntry);
  2538. AA_ASSERT(AA_IE_IS_ALIVE(pIpEntry));
  2539. if (AA_DEREF_IE(pIpEntry, IE_REFTYPE_TMP)) // TmpRef
  2540. {
  2541. AADEBUGP(AAD_WARNING,
  2542. ("CleanupArpTable: Aborting stale IP %d:%d:%d:%d\n",
  2543. ((PUCHAR)&(pIpEntry->IPAddress))[0],
  2544. ((PUCHAR)&(pIpEntry->IPAddress))[1],
  2545. ((PUCHAR)&(pIpEntry->IPAddress))[2],
  2546. ((PUCHAR)&(pIpEntry->IPAddress))[3]
  2547. ));
  2548. AtmArpAbortIPEntry(pIpEntry);
  2549. //
  2550. // IE Lock is released within the above.
  2551. //
  2552. }
  2553. //
  2554. // Since we let go of the table lock, we must re-start our search
  2555. // through pMcSendList.
  2556. //
  2557. fTableLockWasReleased = TRUE;
  2558. AA_ACQUIRE_IF_TABLE_LOCK(pInterface);
  2559. break;
  2560. }
  2561. }
  2562. } while (fTableLockWasReleased);
  2563. AA_RELEASE_IF_TABLE_LOCK(pInterface);
  2564. }