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.

3049 lines
68 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. AADEBUGP(AAD_LOUD, ("LearnIPToAtm: pIf 0x%x, IP Addr: %d:%d:%d:%d, ATM Addr:\n",
  1018. pInterface,
  1019. *((PUCHAR)pIPAddress),
  1020. *((PUCHAR)pIPAddress+1),
  1021. *((PUCHAR)pIPAddress+2),
  1022. *((PUCHAR)pIPAddress+3)));
  1023. AADEBUGPDUMP(AAD_LOUD, pAtmAddress, (AtmAddressTypeLength & ~AA_PKT_ATM_ADDRESS_BIT));
  1024. //
  1025. // Initialize
  1026. //
  1027. Status = NDIS_STATUS_SUCCESS;
  1028. pPacketList = (PNDIS_PACKET)NULL;
  1029. IsBroadcast = FALSE;
  1030. pIpEntry = NULL_PATMARP_IP_ENTRY;
  1031. AA_ACQUIRE_IF_TABLE_LOCK(pInterface);
  1032. //
  1033. // Get an ATM Entry. AtmArpSearchForAtmAddress addrefs
  1034. // the entry, so be sure to dereference it if
  1035. // we're not going to be using it.
  1036. //
  1037. pAtmEntry = AtmArpSearchForAtmAddress(
  1038. pInterface,
  1039. AtmAddressTypeLength,
  1040. pAtmAddress,
  1041. AtmSubaddressTypeLength,
  1042. pAtmSubaddress,
  1043. AE_REFTYPE_IE,
  1044. TRUE // Create new entry if not found
  1045. );
  1046. if (pAtmEntry != NULL_PATMARP_ATM_ENTRY)
  1047. {
  1048. AADEBUGPMAP(AAD_INFO, "Learnt", pIPAddress, &pAtmEntry->ATMAddress);
  1049. //
  1050. // Now get an IP Address Entry. AtmArpSeachForIPAddress addrefs
  1051. // the entry, so be sure to deref it if we're not going to be
  1052. // using it.
  1053. //
  1054. pIpEntry = AtmArpSearchForIPAddress(
  1055. pInterface,
  1056. pIPAddress,
  1057. IE_REFTYPE_AE,
  1058. FALSE, // this isn't multicast/broadcast
  1059. TRUE // Create new entry if not found
  1060. );
  1061. if (pIpEntry != NULL_PATMARP_IP_ENTRY)
  1062. {
  1063. AA_ACQUIRE_IE_LOCK_DPC(pIpEntry);
  1064. AA_ASSERT(AA_IE_IS_ALIVE(pIpEntry));
  1065. //
  1066. // Got both entries.
  1067. //
  1068. // Check for conflict: if the IP Entry existed before, see if
  1069. // it is linked to a different ATM Entry. If so, we have a new
  1070. // mapping that violates an existing mapping. We discard this
  1071. // new information.
  1072. //
  1073. if (pIpEntry->pAtmEntry != NULL_PATMARP_ATM_ENTRY)
  1074. {
  1075. if (pIpEntry->pAtmEntry != pAtmEntry)
  1076. {
  1077. AADEBUGP(AAD_ERROR,
  1078. ("IP Entry 0x%x linked to ATM Entry 0x%x, new ATM Entry 0x%x\n",
  1079. pIpEntry, pIpEntry->pAtmEntry, pAtmEntry));
  1080. Status = NDIS_STATUS_FAILURE;
  1081. }
  1082. else
  1083. {
  1084. //
  1085. // An existing mapping has been reconfirmed.
  1086. //
  1087. AADEBUGP(AAD_INFO,
  1088. ("Revalidated IP Entry 0x%x, Addr: %d.%d.%d.%d, PktList 0x%x\n",
  1089. pIpEntry,
  1090. ((PUCHAR)pIPAddress)[0],
  1091. ((PUCHAR)pIPAddress)[1],
  1092. ((PUCHAR)pIPAddress)[2],
  1093. ((PUCHAR)pIPAddress)[3],
  1094. pIpEntry->PacketList
  1095. ));
  1096. //
  1097. // Update IP Entry state.
  1098. //
  1099. AA_SET_FLAG(
  1100. pIpEntry->Flags,
  1101. AA_IP_ENTRY_STATE_MASK,
  1102. AA_IP_ENTRY_RESOLVED);
  1103. //
  1104. // Remove the list of packets queued on this entry.
  1105. //
  1106. pPacketList = pIpEntry->PacketList;
  1107. pIpEntry->PacketList = (PNDIS_PACKET)NULL;
  1108. if (pPacketList)
  1109. {
  1110. //
  1111. // We'll be sending out these packets on the
  1112. // atm entry, so better put a tempref on the atm
  1113. // entry now. It is derefed when the packet
  1114. // list is finished being sent on the atm entry.
  1115. //
  1116. AA_ACQUIRE_AE_LOCK_DPC(pAtmEntry);
  1117. AA_REF_AE(pAtmEntry, AE_REFTYPE_TMP);// Temp ref: Pkt list.
  1118. AA_RELEASE_AE_LOCK_DPC(pAtmEntry);
  1119. }
  1120. //
  1121. // We will start the IP Entry aging timer on this
  1122. // entry.
  1123. //
  1124. //
  1125. // Stop the Address resolution timer running here
  1126. //
  1127. TimerWasRunning = AtmArpStopTimer(&(pIpEntry->Timer), pInterface);
  1128. if (TimerWasRunning)
  1129. {
  1130. rc = AA_DEREF_IE(pIpEntry, IE_REFTYPE_TIMER); // timer ref.
  1131. AA_ASSERT(rc != 0);
  1132. }
  1133. //
  1134. // Start the Aging timer.
  1135. //
  1136. AtmArpStartTimer(
  1137. pInterface,
  1138. &(pIpEntry->Timer),
  1139. AtmArpIPEntryAgingTimeout,
  1140. pInterface->ARPEntryAgingTimeout,
  1141. (PVOID)pIpEntry
  1142. );
  1143. //
  1144. // Altough we got the initial ref in SearchForIPAddress
  1145. // for IE_REFTYPE_AE, we're actually using it for
  1146. // the timer reference. So we need to switch the reftype
  1147. // here...
  1148. //
  1149. // This reftype stuff is just for tracking purposes.
  1150. //
  1151. AA_SWITCH_IE_REFTYPE(
  1152. pIpEntry,
  1153. IE_REFTYPE_AE,
  1154. IE_REFTYPE_TIMER
  1155. );
  1156. }
  1157. }
  1158. else
  1159. {
  1160. //
  1161. // This IP Entry wasn't mapped to an ATM Entry previously.
  1162. // Link entries together: first, make the IP entry point
  1163. // to this ATM Entry.
  1164. //
  1165. AA_ACQUIRE_AE_LOCK_DPC(pAtmEntry);
  1166. //
  1167. // Check if this is still a valid entry....
  1168. //
  1169. if (AA_IS_FLAG_SET(
  1170. pAtmEntry->Flags,
  1171. AA_ATM_ENTRY_STATE_MASK,
  1172. AA_ATM_ENTRY_CLOSING))
  1173. {
  1174. AA_RELEASE_AE_LOCK_DPC(pAtmEntry);
  1175. Status = NDIS_STATUS_FAILURE;
  1176. }
  1177. else
  1178. {
  1179. pIpEntry->pAtmEntry = pAtmEntry;
  1180. AA_SET_FLAG(
  1181. pAtmEntry->Flags,
  1182. AA_ATM_ENTRY_STATE_MASK,
  1183. AA_ATM_ENTRY_ACTIVE);
  1184. //
  1185. // Add the IP Entry to the ATM Entry's list of IP Entries
  1186. // (multiple IP entries could point to the same ATM Entry).
  1187. //
  1188. pIpEntry->pNextToAtm = pAtmEntry->pIpEntryList;
  1189. pAtmEntry->pIpEntryList = pIpEntry;
  1190. //
  1191. // Remove the list of packets queued on this IP entry.
  1192. //
  1193. pPacketList = pIpEntry->PacketList;
  1194. pIpEntry->PacketList = (PNDIS_PACKET)NULL;
  1195. if (pPacketList)
  1196. {
  1197. AA_REF_AE(pAtmEntry, AE_REFTYPE_TMP);// Temp ref: Pkt list.
  1198. }
  1199. AA_RELEASE_AE_LOCK_DPC(pAtmEntry);
  1200. //
  1201. // Update IP Entry state.
  1202. //
  1203. AA_SET_FLAG(
  1204. pIpEntry->Flags,
  1205. AA_IP_ENTRY_STATE_MASK,
  1206. AA_IP_ENTRY_RESOLVED);
  1207. TimerWasRunning = AtmArpStopTimer(&(pIpEntry->Timer), pInterface);
  1208. if (TimerWasRunning)
  1209. {
  1210. ULONG IeRefCount;
  1211. IeRefCount = AA_DEREF_IE(pIpEntry, IE_REFTYPE_TIMER); // Timer reference
  1212. AA_ASSERT(IeRefCount > 0);
  1213. }
  1214. IsBroadcast = AA_IS_FLAG_SET(pIpEntry->Flags,
  1215. AA_IP_ENTRY_ADDR_TYPE_MASK,
  1216. AA_IP_ENTRY_ADDR_TYPE_NUCAST);
  1217. if (IsStaticEntry)
  1218. {
  1219. pIpEntry->Flags |= AA_IP_ENTRY_IS_STATIC;
  1220. }
  1221. else
  1222. {
  1223. //
  1224. // Start the aging timer on this IP Entry.
  1225. //
  1226. AtmArpStartTimer(
  1227. pInterface,
  1228. &(pIpEntry->Timer),
  1229. AtmArpIPEntryAgingTimeout,
  1230. pInterface->ARPEntryAgingTimeout,
  1231. (PVOID)pIpEntry
  1232. );
  1233. AA_REF_IE(pIpEntry, IE_REFTYPE_TIMER); // Timer reference
  1234. }
  1235. }
  1236. }
  1237. AA_RELEASE_IE_LOCK_DPC(pIpEntry);
  1238. }
  1239. else
  1240. {
  1241. //
  1242. // Failed to locate/allocate IP Entry
  1243. //
  1244. Status = NDIS_STATUS_RESOURCES;
  1245. }
  1246. }
  1247. else
  1248. {
  1249. //
  1250. // Failed to locate/allocate ATM Entry
  1251. //
  1252. Status = NDIS_STATUS_RESOURCES;
  1253. }
  1254. AA_RELEASE_IF_TABLE_LOCK(pInterface);
  1255. if (Status == NDIS_STATUS_SUCCESS)
  1256. {
  1257. //
  1258. // If we have any queued packets to send, send them now.
  1259. //
  1260. if (pPacketList != (PNDIS_PACKET)NULL)
  1261. {
  1262. AtmArpSendPacketListOnAtmEntry(
  1263. pInterface,
  1264. pAtmEntry,
  1265. pPacketList,
  1266. IsBroadcast
  1267. );
  1268. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  1269. rc = AA_DEREF_AE(pAtmEntry, AE_REFTYPE_TMP); // Send pkt list.
  1270. if (rc>0)
  1271. {
  1272. AA_RELEASE_AE_LOCK(pAtmEntry);
  1273. }
  1274. }
  1275. }
  1276. else
  1277. {
  1278. if (pIpEntry)
  1279. {
  1280. AA_ACQUIRE_IE_LOCK(pIpEntry);
  1281. AA_ASSERT(AA_IE_IS_ALIVE(pIpEntry));
  1282. rc = AA_DEREF_IE(pIpEntry, IE_REFTYPE_AE); // LearnIPAtm
  1283. if (rc>0)
  1284. {
  1285. AA_RELEASE_IE_LOCK(pIpEntry);
  1286. }
  1287. }
  1288. if (pAtmEntry)
  1289. {
  1290. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  1291. rc = AA_DEREF_AE(pAtmEntry, AE_REFTYPE_IE); // LearnIPAtm
  1292. if (rc>0)
  1293. {
  1294. AA_RELEASE_AE_LOCK(pAtmEntry);
  1295. }
  1296. }
  1297. //
  1298. // Prepare the return value.
  1299. //
  1300. pIpEntry = NULL_PATMARP_IP_ENTRY;
  1301. }
  1302. return (pIpEntry);
  1303. }
  1304. NDIS_STATUS
  1305. AtmArpQueuePacketOnIPEntry(
  1306. IN PATMARP_IP_ENTRY pIpEntry,
  1307. IN PNDIS_PACKET pNdisPacket
  1308. )
  1309. /*++
  1310. Routine Description:
  1311. Queue a packet on an unresolved IP Entry, unless one of the following
  1312. conditions holds:
  1313. - We recently got an ARP NAK while trying to resolve this entry. In this
  1314. case, there is no point in queueing up this packet and sending another
  1315. ARP Request, because we might immediately get back another NAK.
  1316. If we did queue this packet, we check if address resolution is in progress
  1317. on this entry. If not, start it.
  1318. Arguments:
  1319. pIpEntry - Pointer to ATMARP IP Entry
  1320. pNdisPacket - Packet to be queued
  1321. Locks on entry:
  1322. IP Entry
  1323. Locks on exit:
  1324. None
  1325. Return Value:
  1326. NDIS_STATUS_PENDING if we did queue the packet, NDIS_STATUS_FAILURE
  1327. otherwise.
  1328. --*/
  1329. {
  1330. PATMARP_INTERFACE pInterface;
  1331. PNDIS_PACKET pPrevPacket; // For queueing this packet
  1332. NDIS_STATUS Status; // Return value
  1333. IP_ADDRESS SrcIPAddress; // For ARP Request, if required
  1334. IP_ADDRESS DstIPAddress; // For ARP Request, if required
  1335. pInterface = pIpEntry->pInterface;
  1336. //
  1337. // Check if this IP address has experienced an ARP NAK recently.
  1338. // If not, we queue this packet, else we discard it.
  1339. //
  1340. // We also make sure that the ip entry is in ARP table (it had better be,
  1341. // but it's possible that we enter this code path just after the ip
  1342. // entry has been).
  1343. //
  1344. if (!AA_IS_FLAG_SET(pIpEntry->Flags,
  1345. AA_IP_ENTRY_STATE_MASK,
  1346. AA_IP_ENTRY_SEEN_NAK)
  1347. && AA_IE_IS_ALIVE(pIpEntry))
  1348. {
  1349. //
  1350. // Queue the packet.
  1351. //
  1352. if (pIpEntry->PacketList == (PNDIS_PACKET)NULL)
  1353. {
  1354. //
  1355. // No packets on this IP Entry.
  1356. //
  1357. pIpEntry->PacketList = pNdisPacket;
  1358. }
  1359. else
  1360. {
  1361. //
  1362. // Go to the end of the packet list on this IP Entry.
  1363. //
  1364. pPrevPacket = pIpEntry->PacketList;
  1365. while (AA_GET_NEXT_PACKET(pPrevPacket) != (PNDIS_PACKET)NULL)
  1366. {
  1367. pPrevPacket = AA_GET_NEXT_PACKET(pPrevPacket);
  1368. }
  1369. //
  1370. // Found the last packet in the list. Chain this packet
  1371. // to it.
  1372. //
  1373. AA_SET_NEXT_PACKET(pPrevPacket, pNdisPacket);
  1374. }
  1375. AA_SET_NEXT_PACKET(pNdisPacket, NULL);
  1376. Status = NDIS_STATUS_PENDING;
  1377. //
  1378. // If needed, start resolving this IP address.
  1379. //
  1380. AtmArpResolveIpEntry(pIpEntry);
  1381. //
  1382. // The IE Lock is released within the above.
  1383. //
  1384. }
  1385. else
  1386. {
  1387. //
  1388. // We have seen an ARP NAK for this IP address recently, or
  1389. // this pIpEntry is not alive.
  1390. // Drop this packet.
  1391. //
  1392. AA_RELEASE_IE_LOCK(pIpEntry);
  1393. Status = NDIS_STATUS_FAILURE;
  1394. }
  1395. return (Status);
  1396. }
  1397. BOOLEAN
  1398. AtmArpAtmEntryIsReallyClosing(
  1399. PATMARP_ATM_ENTRY pAtmEntry
  1400. )
  1401. {
  1402. BOOLEAN fRet = FALSE;
  1403. if (AA_IS_FLAG_SET(
  1404. pAtmEntry->Flags,
  1405. AA_ATM_ENTRY_STATE_MASK,
  1406. AA_ATM_ENTRY_CLOSING))
  1407. {
  1408. AADEBUGP(AAD_INFO, ("IsReallyClosing -- ENTRY (0x%08lx) is CLOSING\n",
  1409. pAtmEntry));
  1410. //
  1411. // Decide whether we want to clear the CLOSING state here..
  1412. // We clear the closing state because we saw a case where the
  1413. // entry was permanently in the closing state (a ref count problem).
  1414. // So we will clear this state if it is basically an idle entry,
  1415. // so that it may be reused.
  1416. //
  1417. if ( pAtmEntry->pIpEntryList == NULL
  1418. && pAtmEntry->pVcList == NULL
  1419. && ( pAtmEntry->pMcAtmInfo == NULL
  1420. || pAtmEntry->pMcAtmInfo->pMcAtmMigrateList == NULL))
  1421. {
  1422. AADEBUGP(AAD_INFO,
  1423. ("IsReallyClosing -- ENTRY (0x%08lx) CLEARING CLOSING STATE\n",
  1424. pAtmEntry));
  1425. AA_SET_FLAG(
  1426. pAtmEntry->Flags,
  1427. AA_ATM_ENTRY_STATE_MASK,
  1428. AA_ATM_ENTRY_ACTIVE);
  1429. }
  1430. else
  1431. {
  1432. fRet = TRUE;
  1433. }
  1434. }
  1435. return fRet;
  1436. }
  1437. PATMARP_ATM_ENTRY
  1438. AtmArpSearchForAtmAddress(
  1439. IN PATMARP_INTERFACE pInterface,
  1440. IN UCHAR AtmAddressTypeLength,
  1441. IN UCHAR UNALIGNED * pAtmAddress,
  1442. IN UCHAR AtmSubaddressTypeLength,
  1443. IN UCHAR UNALIGNED * pAtmSubaddress,
  1444. IN AE_REFTYPE RefType,
  1445. IN BOOLEAN CreateNew
  1446. )
  1447. /*++
  1448. Routine Description:
  1449. Search for an ATM Entry that matches the given ATM number+subaddress.
  1450. Optionally, create one if there is no match.
  1451. The caller is assumed to hold a lock to the IF Table.
  1452. Arguments:
  1453. pInterface - Pointer to ATMARP Interface
  1454. AtmAddressTypeLength - Type+Length (ARP packet format) for the ATM number
  1455. pAtmAddress - ATM Number
  1456. AtmSubaddressTypeLength - Type+Length (ARP packet format) for the ATM subaddress
  1457. pAtmSubaddress - ATM Subaddress
  1458. CreateNew - Do we create a new entry if we don't find one?
  1459. RefType - Type of reference
  1460. Return Value:
  1461. Pointer to a matching ATM Entry if found (or created anew).
  1462. --*/
  1463. {
  1464. PATMARP_ATM_ENTRY pAtmEntry;
  1465. BOOLEAN Found;
  1466. ATM_ADDRESSTYPE AddressType;
  1467. ULONG AddressLen;
  1468. ATM_ADDRESSTYPE SubaddressType;
  1469. ULONG SubaddressLen;
  1470. AA_PKT_TYPE_LEN_TO_ATM_ADDRESS(AtmAddressTypeLength, &AddressType, &AddressLen);
  1471. AA_PKT_TYPE_LEN_TO_ATM_ADDRESS(AtmSubaddressTypeLength, &SubaddressType, &SubaddressLen);
  1472. AA_ACQUIRE_IF_ATM_LIST_LOCK(pInterface);
  1473. //
  1474. // Go through the list of ATM Entries on this interface, provided the
  1475. // list is "up." The list is not up when shutting down the interface.
  1476. //
  1477. Found = FALSE;
  1478. if (pInterface->AtmEntryListUp)
  1479. {
  1480. pAtmEntry = pInterface->pAtmEntryList;
  1481. }
  1482. else
  1483. {
  1484. pAtmEntry = NULL;
  1485. }
  1486. for (; pAtmEntry != NULL_PATMARP_ATM_ENTRY; pAtmEntry = pAtmEntry->pNext)
  1487. {
  1488. //
  1489. // Compare the ATM Addresses
  1490. //
  1491. if ((AddressType == pAtmEntry->ATMAddress.AddressType) &&
  1492. (AddressLen == pAtmEntry->ATMAddress.NumberOfDigits) &&
  1493. (AA_MEM_CMP(pAtmAddress, pAtmEntry->ATMAddress.Address, AddressLen) == 0))
  1494. {
  1495. //
  1496. // Compare the Subaddress parts
  1497. //
  1498. if ((SubaddressType == pAtmEntry->ATMSubaddress.AddressType) &&
  1499. (SubaddressLen == pAtmEntry->ATMSubaddress.NumberOfDigits) &&
  1500. (AA_MEM_CMP(pAtmSubaddress, pAtmEntry->ATMSubaddress.Address, SubaddressLen) == 0))
  1501. {
  1502. Found = TRUE;
  1503. //
  1504. // WARNING: AtmArpAtmEntryIsReallyClosing may clear the
  1505. // CLOSING state (if the entry is basically idle) --
  1506. // see comments in that function.
  1507. //
  1508. if (AtmArpAtmEntryIsReallyClosing(pAtmEntry))
  1509. {
  1510. //
  1511. // We don't allow creating a new entry in this case...
  1512. //
  1513. CreateNew = FALSE;
  1514. pAtmEntry = NULL;
  1515. Found = FALSE;
  1516. }
  1517. break;
  1518. }
  1519. }
  1520. }
  1521. if (!Found && CreateNew && pInterface->AtmEntryListUp)
  1522. {
  1523. pAtmEntry = AtmArpAllocateAtmEntry(
  1524. pInterface,
  1525. FALSE // Not multicast
  1526. );
  1527. if (pAtmEntry != NULL_PATMARP_ATM_ENTRY)
  1528. {
  1529. //
  1530. // Fill in this new entry.
  1531. //
  1532. pAtmEntry->Flags = AA_ATM_ENTRY_ACTIVE;
  1533. //
  1534. // The ATM Address.
  1535. //
  1536. pAtmEntry->ATMAddress.AddressType = AddressType;
  1537. pAtmEntry->ATMAddress.NumberOfDigits = AddressLen;
  1538. AA_COPY_MEM(pAtmEntry->ATMAddress.Address,
  1539. pAtmAddress,
  1540. AddressLen);
  1541. //
  1542. // The ATM Subaddress.
  1543. //
  1544. pAtmEntry->ATMSubaddress.AddressType = SubaddressType;
  1545. pAtmEntry->ATMSubaddress.NumberOfDigits = SubaddressLen;
  1546. AA_COPY_MEM(pAtmEntry->ATMSubaddress.Address,
  1547. pAtmSubaddress,
  1548. SubaddressLen);
  1549. //
  1550. // Link in this entry to the Interface
  1551. //
  1552. pAtmEntry->pNext = pInterface->pAtmEntryList;
  1553. pInterface->pAtmEntryList = pAtmEntry;
  1554. }
  1555. }
  1556. if (pAtmEntry)
  1557. {
  1558. AA_ACQUIRE_AE_LOCK_DPC(pAtmEntry);
  1559. AA_REF_AE(pAtmEntry,RefType); // AtmArpSearchForAtmAddress
  1560. AA_RELEASE_AE_LOCK_DPC(pAtmEntry);
  1561. }
  1562. AA_RELEASE_IF_ATM_LIST_LOCK(pInterface);
  1563. AADEBUGP(AAD_VERY_LOUD, ("SearchForAtm: returning (%s) ATM Entry 0x%x for addr:\n",
  1564. (Found? "Old": "New"), pAtmEntry));
  1565. AADEBUGPDUMP(AAD_VERY_LOUD, pAtmAddress, AddressLen);
  1566. return (pAtmEntry);
  1567. }
  1568. PATMARP_IP_ENTRY
  1569. AtmArpSearchForIPAddress(
  1570. PATMARP_INTERFACE pInterface,
  1571. IP_ADDRESS UNALIGNED * pIPAddress,
  1572. IE_REFTYPE RefType,
  1573. BOOLEAN IsMulticast,
  1574. BOOLEAN CreateNew
  1575. )
  1576. /*++
  1577. Routine Description:
  1578. Search for an IP Address in the ARP Table. Optionally, create one
  1579. if a match is not found.
  1580. The caller is assumed to hold a lock to the IF Table.
  1581. Arguments:
  1582. pInterface - Pointer to ATMARP Interface
  1583. pIPAddress - what we are looking for
  1584. IsMulticast - Is this IP address broadcast or multicast?
  1585. RefType - Type of reference to use when we addref the entry.
  1586. CreateNew - Should a new entry be created if no match?
  1587. Return Value:
  1588. Pointer to a matching IP Entry if found (or created anew).
  1589. --*/
  1590. {
  1591. ULONG HashIndex;
  1592. PATMARP_IP_ENTRY pIpEntry;
  1593. BOOLEAN Found;
  1594. #ifdef IPMCAST
  1595. PATMARP_ATM_ENTRY pAtmEntry;
  1596. IP_ADDRESS IPAddressValue;
  1597. PATMARP_IP_ENTRY * ppIpEntry;
  1598. #endif // IPMCAST
  1599. HashIndex = ATMARP_HASH(*pIPAddress);
  1600. Found = FALSE;
  1601. pIpEntry = pInterface->pArpTable[HashIndex];
  1602. //
  1603. // Go through the addresses in this hash list.
  1604. //
  1605. while (pIpEntry != NULL_PATMARP_IP_ENTRY)
  1606. {
  1607. if (IP_ADDR_EQUAL(pIpEntry->IPAddress, *pIPAddress))
  1608. {
  1609. Found = TRUE;
  1610. break;
  1611. }
  1612. pIpEntry = pIpEntry->pNextEntry;
  1613. }
  1614. if (!Found && CreateNew && pInterface->ArpTableUp)
  1615. {
  1616. do
  1617. {
  1618. pIpEntry = AtmArpAllocateIPEntry(pInterface);
  1619. if (pIpEntry == NULL_PATMARP_IP_ENTRY)
  1620. {
  1621. break;
  1622. }
  1623. #ifdef IPMCAST
  1624. if (IsMulticast)
  1625. {
  1626. AAMCDEBUGP(AAD_INFO,
  1627. ("SearchForIpAddr: Creating new MC IP Entry 0x%x for Addr %d.%d.%d.%d\n",
  1628. pIpEntry,
  1629. ((PUCHAR)pIPAddress)[0],
  1630. ((PUCHAR)pIPAddress)[1],
  1631. ((PUCHAR)pIPAddress)[2],
  1632. ((PUCHAR)pIPAddress)[3]));
  1633. pIpEntry->Flags |= AA_IP_ENTRY_ADDR_TYPE_NUCAST;
  1634. //
  1635. // Also link this IP Entry into the per-Interface list
  1636. // of multicast addresses. This is sorted in ascending
  1637. // order of "IP Address value", to help processing
  1638. // <Min, Max> pairs of addresses in JOIN/LEAVE messages.
  1639. //
  1640. IPAddressValue = NET_LONG(*pIPAddress);
  1641. //
  1642. // Find the place to insert this entry at.
  1643. //
  1644. for (ppIpEntry = &(pInterface->pMcSendList);
  1645. *ppIpEntry != NULL_PATMARP_IP_ENTRY;
  1646. ppIpEntry = &((*ppIpEntry)->pNextMcEntry))
  1647. {
  1648. if (NET_LONG((*ppIpEntry)->IPAddress) > IPAddressValue)
  1649. {
  1650. //
  1651. // Found it.
  1652. //
  1653. break;
  1654. }
  1655. }
  1656. pIpEntry->pNextMcEntry = *ppIpEntry;
  1657. *ppIpEntry = pIpEntry;
  1658. }
  1659. else
  1660. {
  1661. AAMCDEBUGP(AAD_INFO,
  1662. ("SearchForIpAddr: Creating new UNI IP Entry 0x%x for Addr %d.%d.%d.%d\n",
  1663. pIpEntry,
  1664. ((PUCHAR)pIPAddress)[0],
  1665. ((PUCHAR)pIPAddress)[1],
  1666. ((PUCHAR)pIPAddress)[2],
  1667. ((PUCHAR)pIPAddress)[3]));
  1668. }
  1669. #endif // IPMCAST
  1670. //
  1671. // Fill in the rest of the IP entry.
  1672. //
  1673. pIpEntry->IPAddress = *pIPAddress;
  1674. //
  1675. // This signifies that it is in the arp table.
  1676. //
  1677. AA_SET_FLAG(pIpEntry->Flags,
  1678. AA_IP_ENTRY_STATE_MASK,
  1679. AA_IP_ENTRY_IDLE2);
  1680. AA_REF_IE(pIpEntry, IE_REFTYPE_TABLE); // ARP Table linkage
  1681. //
  1682. // Link it to the hash table.
  1683. //
  1684. pIpEntry->pNextEntry = pInterface->pArpTable[HashIndex];
  1685. pInterface->pArpTable[HashIndex] = pIpEntry;
  1686. pInterface->NumOfArpEntries++;
  1687. break;
  1688. }
  1689. while (FALSE);
  1690. } // if creating new
  1691. if (pIpEntry)
  1692. {
  1693. AA_ACQUIRE_IE_LOCK_DPC(pIpEntry);
  1694. AA_REF_IE(pIpEntry, RefType); // AtmArpSearchForIPAddress
  1695. AA_RELEASE_IE_LOCK_DPC(pIpEntry);
  1696. }
  1697. AADEBUGP(AAD_LOUD,
  1698. ("Search for IP Addr: %d.%d.%d.%d, hash ind %d, Found %d, IPEnt 0x%x\n",
  1699. ((PUCHAR)pIPAddress)[0],
  1700. ((PUCHAR)pIPAddress)[1],
  1701. ((PUCHAR)pIPAddress)[2],
  1702. ((PUCHAR)pIPAddress)[3],
  1703. HashIndex, Found, pIpEntry));
  1704. return (pIpEntry);
  1705. }
  1706. VOID
  1707. AtmArpAbortIPEntry(
  1708. IN PATMARP_IP_ENTRY pIpEntry
  1709. )
  1710. /*++
  1711. Routine Description:
  1712. Clean up and delete an IP entry. This is called when we invalidate
  1713. an ARP mapping.
  1714. NOTE: The caller is assumed to hold a lock to the IP Entry,
  1715. which will be released here.
  1716. Arguments:
  1717. pIpEntry - Pointer to IP Entry to be deleted.
  1718. Return Value:
  1719. None
  1720. --*/
  1721. {
  1722. PATMARP_INTERFACE pInterface;
  1723. PATMARP_IP_ENTRY * ppNextIpEntry;
  1724. PATMARP_ATM_ENTRY pAtmEntry;
  1725. RouteCacheEntry * pRCE;
  1726. PNDIS_PACKET PacketList;
  1727. ULONG rc; // Ref Count on IP Entry.
  1728. BOOLEAN IsMulticastIpEntry;
  1729. BOOLEAN Found;
  1730. BOOLEAN TimerWasRunning;
  1731. BOOLEAN IfTableLockReleased;
  1732. ULONG HashIndex; // For this IP Entry in ARP Table
  1733. AADEBUGP(AAD_INFO,
  1734. ("Abort IP entry 0x%x, Flags 0x%x, ATM Entry 0x%x, IP Addr %d:%d:%d:%d\n",
  1735. pIpEntry,
  1736. pIpEntry->Flags,
  1737. pIpEntry->pAtmEntry,
  1738. ((PUCHAR)&(pIpEntry->IPAddress))[0],
  1739. ((PUCHAR)&(pIpEntry->IPAddress))[1],
  1740. ((PUCHAR)&(pIpEntry->IPAddress))[2],
  1741. ((PUCHAR)&(pIpEntry->IPAddress))[3]
  1742. ));
  1743. //
  1744. // Initialize.
  1745. //
  1746. rc = pIpEntry->RefCount;
  1747. pInterface = pIpEntry->pInterface;
  1748. #ifdef IPMCAST
  1749. IsMulticastIpEntry = (AA_IS_FLAG_SET(pIpEntry->Flags,
  1750. AA_IP_ENTRY_ADDR_TYPE_MASK,
  1751. AA_IP_ENTRY_ADDR_TYPE_NUCAST));
  1752. #endif
  1753. IfTableLockReleased = FALSE;
  1754. //
  1755. // Reacquire the desired locks in the right order.
  1756. //
  1757. AA_RELEASE_IE_LOCK(pIpEntry);
  1758. AA_ACQUIRE_IF_TABLE_LOCK(pInterface);
  1759. AA_ACQUIRE_IE_LOCK(pIpEntry);
  1760. AA_ASSERT(AA_IE_IS_ALIVE(pIpEntry));
  1761. //
  1762. // Remove any packets queued on this IP Entry.
  1763. //
  1764. PacketList = pIpEntry->PacketList;
  1765. pIpEntry->PacketList = (PNDIS_PACKET)NULL;
  1766. do
  1767. {
  1768. #ifdef IPMCAST
  1769. //
  1770. // If this is a Non-unicast entry, unlink it from the list
  1771. // of Multicast IP Entries on this Interface.
  1772. //
  1773. if (IsMulticastIpEntry)
  1774. {
  1775. for (ppNextIpEntry = &(pInterface->pMcSendList);
  1776. *ppNextIpEntry != NULL_PATMARP_IP_ENTRY;
  1777. ppNextIpEntry = &((*ppNextIpEntry)->pNextMcEntry))
  1778. {
  1779. if (*ppNextIpEntry == pIpEntry)
  1780. {
  1781. //
  1782. // Unlink it.
  1783. //
  1784. *ppNextIpEntry = pIpEntry->pNextMcEntry;
  1785. break;
  1786. }
  1787. }
  1788. AAMCDEBUGP(AAD_VERY_LOUD,
  1789. ("AbortIPEntry (MC): pIpEntry 0x%x: unlinked from MC list\n", pIpEntry));
  1790. }
  1791. #endif // IPMCAST
  1792. //
  1793. // Unlink this IP Entry from all Route Cache Entries
  1794. // that point to it.
  1795. //
  1796. pRCE = pIpEntry->pRCEList;
  1797. while (pRCE != (RouteCacheEntry *)NULL)
  1798. {
  1799. Found = AtmArpUnlinkRCE(pRCE, pIpEntry);
  1800. AA_ASSERT(Found);
  1801. rc = AA_DEREF_IE(pIpEntry, IE_REFTYPE_RCE); // RCE linkage ref
  1802. if (rc > 0)
  1803. {
  1804. pRCE = pIpEntry->pRCEList;
  1805. }
  1806. else
  1807. {
  1808. pRCE = (RouteCacheEntry *)NULL;
  1809. }
  1810. }
  1811. if (rc == 0)
  1812. {
  1813. // The IP Entry is gone.
  1814. break;
  1815. }
  1816. //
  1817. // Stop any timer running on the IP Entry.
  1818. //
  1819. TimerWasRunning = AtmArpStopTimer(&(pIpEntry->Timer), pInterface);
  1820. if (TimerWasRunning)
  1821. {
  1822. rc = AA_DEREF_IE(pIpEntry, IE_REFTYPE_TIMER); // Timer ref
  1823. if (rc == 0)
  1824. {
  1825. break;
  1826. }
  1827. }
  1828. //
  1829. // Unlink this IP Entry from the ARP Table, if needed.
  1830. //
  1831. Found = FALSE;
  1832. HashIndex = ATMARP_HASH(pIpEntry->IPAddress);
  1833. ppNextIpEntry = &(pInterface->pArpTable[HashIndex]);
  1834. while (*ppNextIpEntry != NULL_PATMARP_IP_ENTRY)
  1835. {
  1836. if (*ppNextIpEntry == pIpEntry)
  1837. {
  1838. //
  1839. // Make the predecessor point to the next
  1840. // in the list.
  1841. //
  1842. *ppNextIpEntry = pIpEntry->pNextEntry;
  1843. Found = TRUE;
  1844. pInterface->NumOfArpEntries--;
  1845. //
  1846. // Once it's off the arp table, we set the flag to IDLE.
  1847. //
  1848. AA_SET_FLAG(pIpEntry->Flags,
  1849. AA_IP_ENTRY_STATE_MASK,
  1850. AA_IP_ENTRY_IDLE);
  1851. break;
  1852. }
  1853. else
  1854. {
  1855. ppNextIpEntry = &((*ppNextIpEntry)->pNextEntry);
  1856. }
  1857. }
  1858. if (Found)
  1859. {
  1860. rc = AA_DEREF_IE(pIpEntry, IE_REFTYPE_TABLE); // ARP Table ref
  1861. if (rc == 0)
  1862. {
  1863. break;
  1864. }
  1865. }
  1866. //
  1867. // Do this last:
  1868. // ------------
  1869. // If this IP Entry is linked to an ATM Entry, unlink it.
  1870. // If this is a multicast ATM entry, shut down the ATM Entry, too.
  1871. //
  1872. pAtmEntry = pIpEntry->pAtmEntry;
  1873. if (pAtmEntry != NULL_PATMARP_ATM_ENTRY)
  1874. {
  1875. #ifdef IPMCAST
  1876. BOOLEAN IsMulticastAtmEntry;
  1877. pIpEntry->pAtmEntry = NULL;
  1878. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  1879. IsMulticastAtmEntry = AA_IS_FLAG_SET(pAtmEntry->Flags,
  1880. AA_ATM_ENTRY_TYPE_MASK,
  1881. AA_ATM_ENTRY_TYPE_NUCAST);
  1882. if (IsMulticastAtmEntry)
  1883. {
  1884. //
  1885. // We do this because we'll access the ATM
  1886. // Entry below, but only for the PMP case.
  1887. //
  1888. AA_REF_AE(pAtmEntry, AE_REFTYPE_TMP); // Temp ref: Abort IP Entry
  1889. }
  1890. #else
  1891. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  1892. #endif // IPMCAST
  1893. //
  1894. // Locate the position of this IP Entry in the ATM Entry's list.
  1895. //
  1896. ppNextIpEntry = &(pAtmEntry->pIpEntryList);
  1897. while (*ppNextIpEntry != NULL && *ppNextIpEntry != pIpEntry)
  1898. {
  1899. ppNextIpEntry = &((*ppNextIpEntry)->pNextToAtm);
  1900. }
  1901. if (*ppNextIpEntry == pIpEntry)
  1902. {
  1903. //
  1904. // Make the predecessor point to the next entry.
  1905. //
  1906. *ppNextIpEntry = pIpEntry->pNextToAtm;
  1907. rc = AA_DEREF_AE(pAtmEntry, AE_REFTYPE_IE); // IP Entry ref
  1908. if (rc != 0)
  1909. {
  1910. AA_RELEASE_AE_LOCK(pAtmEntry);
  1911. }
  1912. rc = AA_DEREF_IE(pIpEntry, IE_REFTYPE_AE); // ATM Entry linkage ref
  1913. if (rc != 0)
  1914. {
  1915. AA_ASSERT (FALSE); // we expect rc to be 0, but could be a tmp ref.
  1916. AA_RELEASE_IE_LOCK(pIpEntry);
  1917. }
  1918. }
  1919. else
  1920. {
  1921. //
  1922. // We didn't find this IP entry in the atm entry list!
  1923. // Presumably the linkage has been broken by some other
  1924. // path (probably AtmArpInvalidateAtmEntry) while we were
  1925. // in this function.
  1926. //
  1927. // We don't deref here because these two are now not linked.
  1928. //
  1929. //
  1930. AA_RELEASE_AE_LOCK(pAtmEntry);
  1931. AA_RELEASE_IE_LOCK(pIpEntry);
  1932. }
  1933. //
  1934. // IE Lock would have been released above.
  1935. //
  1936. AA_RELEASE_IF_TABLE_LOCK(pInterface);
  1937. IfTableLockReleased = TRUE;
  1938. #ifdef IPMCAST
  1939. //
  1940. // If this was a multicast entry, shut down the ATM Entry
  1941. //
  1942. if (IsMulticastAtmEntry)
  1943. {
  1944. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  1945. rc = AA_DEREF_AE(pAtmEntry, AE_REFTYPE_TMP); // Temp ref: Abort IP Entry
  1946. if (rc != 0)
  1947. {
  1948. AtmArpInvalidateAtmEntry(pAtmEntry, FALSE);
  1949. //
  1950. // AE Lock is released within the above.
  1951. //
  1952. }
  1953. }
  1954. #endif // IPMCAST
  1955. }
  1956. else
  1957. {
  1958. //
  1959. // No ATM entry linked to this IP entry.
  1960. //
  1961. AA_RELEASE_IE_LOCK(pIpEntry);
  1962. break;
  1963. }
  1964. break;
  1965. }
  1966. while (FALSE);
  1967. if (!IfTableLockReleased)
  1968. {
  1969. AA_RELEASE_IF_TABLE_LOCK(pInterface);
  1970. }
  1971. //
  1972. // Free all packets that were queued on the IP Entry.
  1973. //
  1974. AtmArpFreeSendPackets(
  1975. pInterface,
  1976. PacketList,
  1977. FALSE // No LLC/SNAP header on these
  1978. );
  1979. return;
  1980. }
  1981. VOID
  1982. AtmArpInvalidateAtmEntry(
  1983. IN PATMARP_ATM_ENTRY pAtmEntry,
  1984. IN BOOLEAN ShuttingDown
  1985. )
  1986. /*++
  1987. Routine Description:
  1988. Invalidate an ATM Entry by unlinking it from IP entries.
  1989. Typical situation:
  1990. A non-normal communication problem has been detected on a Vc going to
  1991. this ATM destination. The RFC says that we need to invalidate all IP
  1992. entries for this destination, and let them get re-resolved before sending
  1993. any traffic to them. We implement this by unlinking this ATM entry from
  1994. all IP entries it is linked to. Each such IP entry will get re-resolved
  1995. if+when we try to send a packet to it.
  1996. The only exceptions are IP Entries that have been statically mapped
  1997. to this ATM Entry: we don't unlink these, unless we are shutting down
  1998. now, as indicated by "ShuttingDown".
  1999. If we end up with no IP Entries pointing to this ATM Entry, we close all
  2000. SVCs linked to the ATM Entry. If ShuttingDown is TRUE, we close all PVCs
  2001. as well.
  2002. Arguments:
  2003. pAtmEntry - The ATM Entry needing invalidating.
  2004. ShuttingDown - TRUE iff the interface is being shut down.
  2005. Return Value:
  2006. None
  2007. --*/
  2008. {
  2009. PATMARP_IP_ENTRY pIpEntry;
  2010. PATMARP_IP_ENTRY pNextIpEntry;
  2011. ULONG rc; // Ref Count of ATM Entry
  2012. INT IPEntriesUnlinked;
  2013. PATMARP_IP_ENTRY pStaticIpEntryList; // List of static IP Entries
  2014. AA_STRUCT_ASSERT(pAtmEntry, aae);
  2015. AADEBUGP(AAD_INFO,
  2016. ("InvalidateAtmEntry: pAtmEntry 0x%x, Flags 0x%x, ShutDown %d, pIpEntryList 0x%x\n",
  2017. pAtmEntry,
  2018. pAtmEntry->Flags,
  2019. ShuttingDown,
  2020. pAtmEntry->pIpEntryList));
  2021. #ifndef PROTECT_ATM_ENTRY_IN_CLOSE_CALL
  2022. //
  2023. // Check if we are already closing this ATM Entry. If so,
  2024. // we don't do anything here.
  2025. //
  2026. if (AA_IS_FLAG_SET(
  2027. pAtmEntry->Flags,
  2028. AA_ATM_ENTRY_STATE_MASK,
  2029. AA_ATM_ENTRY_CLOSING))
  2030. {
  2031. AA_RELEASE_AE_LOCK(pAtmEntry);
  2032. return;
  2033. }
  2034. //
  2035. // Mark this ATM Entry so that we don't use it anymore.
  2036. //
  2037. AA_SET_FLAG(pAtmEntry->Flags,
  2038. AA_ATM_ENTRY_STATE_MASK,
  2039. AA_ATM_ENTRY_CLOSING);
  2040. #endif // PROTECT_ATM_ENTRY_IN_CLOSE_CALL
  2041. //
  2042. // Initialize.
  2043. //
  2044. pStaticIpEntryList = NULL_PATMARP_IP_ENTRY;
  2045. IPEntriesUnlinked = 0;
  2046. //
  2047. // Take the IP Entry list out of the ATM Entry.
  2048. //
  2049. pIpEntry = pAtmEntry->pIpEntryList;
  2050. pAtmEntry->pIpEntryList = NULL_PATMARP_IP_ENTRY;
  2051. #ifdef IPMCAST
  2052. //
  2053. // Delete the Migrate list, if any.
  2054. //
  2055. if (AA_IS_FLAG_SET(pAtmEntry->Flags,
  2056. AA_ATM_ENTRY_TYPE_MASK,
  2057. AA_ATM_ENTRY_TYPE_NUCAST))
  2058. {
  2059. PATMARP_IPMC_ATM_ENTRY pMcAtmEntry;
  2060. PATMARP_IPMC_ATM_ENTRY pNextMcAtmEntry;
  2061. for (pMcAtmEntry = pAtmEntry->pMcAtmInfo->pMcAtmMigrateList;
  2062. pMcAtmEntry != NULL_PATMARP_IPMC_ATM_ENTRY;
  2063. pMcAtmEntry = pNextMcAtmEntry)
  2064. {
  2065. pNextMcAtmEntry = pMcAtmEntry->pNextMcAtmEntry;
  2066. AA_ASSERT(!AA_IS_TIMER_ACTIVE(&pMcAtmEntry->Timer));
  2067. AA_CHECK_TIMER_IN_ACTIVE_LIST(&pMcAtmEntry->Timer, pAtmEntry->pInterface, pMcAtmEntry, "MC ATM Entry");
  2068. AA_FREE_MEM(pMcAtmEntry);
  2069. }
  2070. pAtmEntry->pMcAtmInfo->pMcAtmMigrateList = NULL_PATMARP_IPMC_ATM_ENTRY;
  2071. }
  2072. #endif // IPMCAST
  2073. //
  2074. // We let go of the ATM Entry lock here because we'll need
  2075. // to lock each IP Entry in the above list, and we need to make
  2076. // sure that we don't deadlock.
  2077. //
  2078. // However, we make sure that the ATM Entry doesn't go away
  2079. // by adding a reference to it.
  2080. //
  2081. AA_REF_AE(pAtmEntry, AE_REFTYPE_TMP); // Temp ref
  2082. AA_RELEASE_AE_LOCK(pAtmEntry);
  2083. //
  2084. // Now, unlink all IP entries that are "dynamic", and filter
  2085. // out a list of static mappings.
  2086. //
  2087. while (pIpEntry != NULL_PATMARP_IP_ENTRY)
  2088. {
  2089. AA_ACQUIRE_IE_LOCK(pIpEntry);
  2090. AA_ASSERT(AA_IE_IS_ALIVE(pIpEntry));
  2091. pNextIpEntry = pIpEntry->pNextToAtm;
  2092. if (ShuttingDown || (!AA_IS_FLAG_SET(pIpEntry->Flags,
  2093. AA_IP_ENTRY_TYPE_MASK,
  2094. AA_IP_ENTRY_IS_STATIC)))
  2095. {
  2096. AADEBUGP(AAD_INFO,
  2097. ("InvalidateATMEntry: Unlinking IP entry 0x%x, Flags 0x%x, ATM Entry 0x%x, IP Addr %d:%d:%d:%d; rc=%lu\n",
  2098. pIpEntry,
  2099. pIpEntry->Flags,
  2100. pIpEntry->pAtmEntry,
  2101. ((PUCHAR)&(pIpEntry->IPAddress))[0],
  2102. ((PUCHAR)&(pIpEntry->IPAddress))[1],
  2103. ((PUCHAR)&(pIpEntry->IPAddress))[2],
  2104. ((PUCHAR)&(pIpEntry->IPAddress))[3],
  2105. pIpEntry->RefCount
  2106. ));
  2107. //
  2108. // Remove the mapping.
  2109. //
  2110. AA_SET_FLAG(pIpEntry->Flags,
  2111. AA_IP_ENTRY_STATE_MASK,
  2112. AA_IP_ENTRY_IDLE2);
  2113. AA_SET_FLAG(pIpEntry->Flags,
  2114. AA_IP_ENTRY_MC_RESOLVE_MASK,
  2115. AA_IP_ENTRY_MC_IDLE);
  2116. pIpEntry->pAtmEntry = NULL_PATMARP_ATM_ENTRY;
  2117. pIpEntry->pNextToAtm = NULL_PATMARP_IP_ENTRY;
  2118. //
  2119. // Stop any active timer on the IP entry now that we have clobbered
  2120. // its state.
  2121. //
  2122. if (AtmArpStopTimer(&pIpEntry->Timer, pIpEntry->pInterface))
  2123. {
  2124. ULONG IpEntryRc;
  2125. IpEntryRc = AA_DEREF_IE(pIpEntry, IE_REFTYPE_TIMER);
  2126. AA_ASSERT(IpEntryRc != 0);
  2127. }
  2128. //
  2129. // Remove the ATM Entry linkage reference.
  2130. //
  2131. if (AA_DEREF_IE(pIpEntry, IE_REFTYPE_AE) != 0)
  2132. {
  2133. AA_RELEASE_IE_LOCK(pIpEntry);
  2134. }
  2135. //
  2136. // else the IP Entry is gone
  2137. //
  2138. IPEntriesUnlinked++;
  2139. }
  2140. else
  2141. {
  2142. //
  2143. // Static ARP entry, retain it.
  2144. //
  2145. pIpEntry->pNextToAtm = pStaticIpEntryList;
  2146. pStaticIpEntryList = pIpEntry;
  2147. AA_RELEASE_IE_LOCK(pIpEntry);
  2148. }
  2149. pIpEntry = pNextIpEntry;
  2150. }
  2151. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  2152. //
  2153. // Put back the static IP entries on the ATM Entry.
  2154. //
  2155. AA_ASSERT(pAtmEntry->pIpEntryList == NULL_PATMARP_IP_ENTRY);
  2156. pAtmEntry->pIpEntryList = pStaticIpEntryList;
  2157. //
  2158. // Now dereference the ATM Entry as many times as we unlinked
  2159. // IP Entries from it.
  2160. //
  2161. rc = pAtmEntry->RefCount;
  2162. while (IPEntriesUnlinked-- > 0)
  2163. {
  2164. rc = AA_DEREF_AE(pAtmEntry, AE_REFTYPE_IE); // IP Entry ref
  2165. }
  2166. AA_ASSERT(rc != 0);
  2167. //
  2168. // Take out the reference we added at the beginning of
  2169. // this routine.
  2170. //
  2171. rc = AA_DEREF_AE(pAtmEntry, AE_REFTYPE_TMP); // Temp ref
  2172. //
  2173. // Now, the only IP Entries pointing at this ATM Entry would be
  2174. // static entries. If there are no such IP entries, close all SVCs
  2175. // attached to the ATM Entry. But do all this only if the ATM Entry
  2176. // hasn't been dereferenced away already.
  2177. //
  2178. if (rc != 0)
  2179. {
  2180. //
  2181. // The ATM Entry still exists.
  2182. //
  2183. AADEBUGP(AAD_LOUD,
  2184. ("InvalidateAtmEntry: nonzero rc on exit.\n"
  2185. "\t pAE=0x%x; rc=%lu; pIpList=0x%x\n",
  2186. pAtmEntry,
  2187. pAtmEntry->RefCount,
  2188. pAtmEntry->pIpEntryList
  2189. ));
  2190. if (pAtmEntry->pIpEntryList == NULL_PATMARP_IP_ENTRY)
  2191. {
  2192. //
  2193. // No IP Entries pointing to this ATM Entry.
  2194. //
  2195. AtmArpCloseVCsOnAtmEntry(pAtmEntry, ShuttingDown);
  2196. //
  2197. // The ATM Entry lock is released within the above.
  2198. //
  2199. }
  2200. else
  2201. {
  2202. AADEBUGP(AAD_LOUD,
  2203. ("InvalidateAtmEnt: AtmEnt %x has nonempty IP list %x, reactivating\n",
  2204. pAtmEntry, pAtmEntry->pIpEntryList));
  2205. AA_SET_FLAG(
  2206. pAtmEntry->Flags,
  2207. AA_ATM_ENTRY_STATE_MASK,
  2208. AA_ATM_ENTRY_ACTIVE);
  2209. AA_RELEASE_AE_LOCK(pAtmEntry);
  2210. }
  2211. }
  2212. //
  2213. // else the ATM Entry is gone
  2214. //
  2215. return;
  2216. }
  2217. VOID
  2218. AtmArpCloseVCsOnAtmEntry(
  2219. IN PATMARP_ATM_ENTRY pAtmEntry LOCKIN NOLOCKOUT,
  2220. IN BOOLEAN ShuttingDown
  2221. )
  2222. /*++
  2223. Routine Description:
  2224. Go through the list of VCs chained to an ATM Entry, and close all
  2225. VCs that are SVCs. If the interface is being shut down, close all
  2226. PVCs as well.
  2227. NOTE: the caller is assumed to hold a lock to the ATM Entry,
  2228. which will be released here.
  2229. Arguments:
  2230. pAtmEntry - Pointer to ATM Entry on which we want to close SVCs.
  2231. ShuttingDown - TRUE iff the interface is being shut down.
  2232. Return Value:
  2233. None
  2234. --*/
  2235. {
  2236. PATMARP_VC pVc; // Used to walk the list of VCs on the ATM Entry
  2237. PATMARP_VC pCloseVcList; // List of VCs on the ATM Entry to be closed
  2238. PATMARP_VC *ppNextVc;
  2239. PATMARP_VC pNextVc;
  2240. ULONG rc; // Ref count on ATM Entry
  2241. do
  2242. {
  2243. //
  2244. // Reference the ATM Entry so that it cannot go away.
  2245. //
  2246. AA_REF_AE(pAtmEntry, AE_REFTYPE_TMP); // Temp ref: InvalidateAtmEntry
  2247. #ifdef PROTECT_ATM_ENTRY_IN_CLOSE_CALL
  2248. //
  2249. // Check if we are already closing this ATM Entry. If so,
  2250. // we don't do anything here.
  2251. //
  2252. if (AA_IS_FLAG_SET(
  2253. pAtmEntry->Flags,
  2254. AA_ATM_ENTRY_STATE_MASK,
  2255. AA_ATM_ENTRY_CLOSING))
  2256. {
  2257. break;
  2258. }
  2259. //
  2260. // Mark this ATM Entry so that we don't use it anymore.
  2261. //
  2262. AA_SET_FLAG(pAtmEntry->Flags,
  2263. AA_ATM_ENTRY_STATE_MASK,
  2264. AA_ATM_ENTRY_CLOSING);
  2265. #endif // PROTECT_ATM_ENTRY_IN_CLOSE_CALL
  2266. //
  2267. // Go through the list of VCs on this ATM Entry,
  2268. // close all SVCs, and if we are shutting down,
  2269. // all PVCs, too.
  2270. //
  2271. if (pAtmEntry->pVcList != NULL_PATMARP_VC)
  2272. {
  2273. pVc = pAtmEntry->pVcList;
  2274. AA_ACQUIRE_VC_LOCK_DPC(pVc);
  2275. AtmArpReferenceVc(pVc); // temp: CloseVCsOnAtmEntry
  2276. AA_RELEASE_VC_LOCK_DPC(pVc);
  2277. }
  2278. for (pVc = pAtmEntry->pVcList;
  2279. pVc != NULL_PATMARP_VC;
  2280. pVc = pNextVc)
  2281. {
  2282. pNextVc = pVc->pNextVc;
  2283. //
  2284. // Make sure we do not follow a stale link after
  2285. // we are done with the current VC.
  2286. //
  2287. if (pNextVc != NULL_PATMARP_VC)
  2288. {
  2289. AA_ACQUIRE_VC_LOCK_DPC(pNextVc);
  2290. AtmArpReferenceVc(pNextVc); // temp: CloseVCsOnAtmEntry
  2291. AA_RELEASE_VC_LOCK_DPC(pNextVc);
  2292. }
  2293. if (ShuttingDown || (AA_IS_FLAG_SET(pVc->Flags,
  2294. AA_VC_TYPE_MASK,
  2295. AA_VC_TYPE_SVC)))
  2296. {
  2297. AA_RELEASE_AE_LOCK(pAtmEntry);
  2298. AA_ACQUIRE_VC_LOCK(pVc);
  2299. if (AtmArpDereferenceVc(pVc) != 0)
  2300. {
  2301. AtmArpCloseCall(pVc);
  2302. //
  2303. // The VC Lock is released within the above.
  2304. //
  2305. }
  2306. }
  2307. else
  2308. {
  2309. AA_RELEASE_AE_LOCK(pAtmEntry);
  2310. AA_ACQUIRE_VC_LOCK(pVc);
  2311. if (AtmArpDereferenceVc(pVc) != 0)
  2312. {
  2313. AA_RELEASE_VC_LOCK(pVc);
  2314. }
  2315. }
  2316. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  2317. }
  2318. break;
  2319. }
  2320. while (FALSE);
  2321. //
  2322. // Remove the temp reference
  2323. //
  2324. rc = AA_DEREF_AE(pAtmEntry, AE_REFTYPE_TMP); // Temp ref: InvalidateAtmEntry
  2325. if (rc != 0)
  2326. {
  2327. AA_RELEASE_AE_LOCK(pAtmEntry);
  2328. }
  2329. //
  2330. // else the ATM Entry is gone.
  2331. //
  2332. return;
  2333. }
  2334. VOID
  2335. AtmArpResolveIpEntry(
  2336. IN PATMARP_IP_ENTRY pIpEntry LOCKIN NOLOCKOUT
  2337. )
  2338. /*++
  2339. Routine Description:
  2340. Trigger off address resolution of an IP entry, unless it's already
  2341. going on. Based on the IP address class, we either go to the ARP
  2342. server or to MARS.
  2343. NOTE: The caller is assumed to hold a lock to the IP Entry, and it
  2344. will be released here.
  2345. Arguments:
  2346. pIpEntry - IP Entry on which we want to start resolution.
  2347. Return Value:
  2348. None
  2349. --*/
  2350. {
  2351. PATMARP_INTERFACE pInterface;
  2352. IP_ADDRESS DstIPAddress;
  2353. IP_ADDRESS SrcIPAddress;
  2354. BOOLEAN WasRunning;
  2355. ULONG Flags; // From IP Entry
  2356. Flags = pIpEntry->Flags;
  2357. if (!AA_IS_FLAG_SET(
  2358. Flags,
  2359. AA_IP_ENTRY_STATE_MASK,
  2360. AA_IP_ENTRY_ARPING) &&
  2361. !AA_IS_FLAG_SET(
  2362. Flags,
  2363. AA_IP_ENTRY_STATE_MASK,
  2364. AA_IP_ENTRY_INARPING) &&
  2365. AA_IE_IS_ALIVE(pIpEntry))
  2366. {
  2367. pInterface = pIpEntry->pInterface;
  2368. //
  2369. // Get the source and destination IP addresses for
  2370. // the ARP Request.
  2371. //
  2372. DstIPAddress = pIpEntry->IPAddress;
  2373. SrcIPAddress = pInterface->LocalIPAddress.IPAddress;
  2374. //
  2375. // An aging timer might be running on this IP Entry.
  2376. // [We start one in the NakDelayTimeout routine].
  2377. // Stop it.
  2378. //
  2379. WasRunning = AtmArpStopTimer(&(pIpEntry->Timer), pInterface);
  2380. //
  2381. // Start an ARP Wait timer.
  2382. //
  2383. AtmArpStartTimer(
  2384. pInterface,
  2385. &(pIpEntry->Timer),
  2386. AtmArpAddressResolutionTimeout,
  2387. pInterface->AddressResolutionTimeout,
  2388. (PVOID)pIpEntry
  2389. );
  2390. if (!WasRunning)
  2391. {
  2392. AA_REF_IE(pIpEntry, IE_REFTYPE_TIMER); // timer ref
  2393. }
  2394. pIpEntry->RetriesLeft = pInterface->MaxResolutionAttempts - 1;
  2395. //
  2396. // Update the state on this IP Entry.
  2397. //
  2398. AA_SET_FLAG(
  2399. pIpEntry->Flags,
  2400. AA_IP_ENTRY_STATE_MASK,
  2401. AA_IP_ENTRY_ARPING);
  2402. AA_RELEASE_IE_LOCK(pIpEntry);
  2403. #ifdef IPMCAST
  2404. if (AA_IS_FLAG_SET(Flags,
  2405. AA_IP_ENTRY_ADDR_TYPE_MASK,
  2406. AA_IP_ENTRY_ADDR_TYPE_UCAST))
  2407. {
  2408. //
  2409. // Unicast address: send out an ARP Request
  2410. //
  2411. AtmArpSendARPRequest(
  2412. pInterface,
  2413. &SrcIPAddress,
  2414. &DstIPAddress
  2415. );
  2416. }
  2417. else
  2418. {
  2419. //
  2420. // Multicast/broadcast address: send a MARS Request
  2421. //
  2422. AtmArpMcSendRequest(
  2423. pInterface,
  2424. &DstIPAddress
  2425. );
  2426. }
  2427. #else
  2428. //
  2429. // Now send out the ARP Request
  2430. //
  2431. AtmArpSendARPRequest(
  2432. pInterface,
  2433. &SrcIPAddress,
  2434. &DstIPAddress
  2435. );
  2436. #endif // IPMCAST
  2437. }
  2438. else
  2439. {
  2440. //
  2441. // The IP Address is either not alived or being resolved.
  2442. // No more action needed
  2443. // here.
  2444. //
  2445. AA_RELEASE_IE_LOCK(pIpEntry);
  2446. }
  2447. return;
  2448. }
  2449. EXTERN
  2450. VOID
  2451. AtmArpCleanupArpTable(
  2452. IN PATMARP_INTERFACE pInterface
  2453. )
  2454. /*++
  2455. Routine Description:
  2456. Go through the ARP Table, deleting all multicast IP entries that
  2457. are stale (currently defined as having no link to an AtmEntry).
  2458. These IP entries stay around because mulicast entries don't have ageing timers.
  2459. Arguments:
  2460. pInterface
  2461. Return Value:
  2462. None
  2463. --*/
  2464. {
  2465. BOOLEAN fTableLockWasReleased;
  2466. AA_ACQUIRE_IF_TABLE_LOCK(pInterface);
  2467. do
  2468. {
  2469. PATMARP_IP_ENTRY pIpEntry;
  2470. fTableLockWasReleased = FALSE;
  2471. for (pIpEntry = pInterface->pMcSendList;
  2472. pIpEntry != NULL;
  2473. pIpEntry = pIpEntry->pNextMcEntry)
  2474. {
  2475. //
  2476. // NOTE: by design, we don't claim the ip entry lock when checking
  2477. // whether we should abort the entry or not.
  2478. //
  2479. if ( pIpEntry->pAtmEntry == NULL
  2480. && !AA_IS_FLAG_SET(
  2481. pIpEntry->Flags,
  2482. AA_IP_ENTRY_STATE_MASK,
  2483. AA_IP_ENTRY_ARPING))
  2484. {
  2485. //
  2486. // Get locks in the right order.
  2487. //
  2488. AA_ACQUIRE_IE_LOCK_DPC(pIpEntry);
  2489. AA_ASSERT(AA_IE_IS_ALIVE(pIpEntry));
  2490. AA_REF_IE(pIpEntry, IE_REFTYPE_TMP); // TmpRef
  2491. AA_RELEASE_IE_LOCK_DPC(pIpEntry);
  2492. AA_RELEASE_IF_TABLE_LOCK(pInterface);
  2493. AA_ACQUIRE_IE_LOCK(pIpEntry);
  2494. AA_ASSERT(AA_IE_IS_ALIVE(pIpEntry));
  2495. if (AA_DEREF_IE(pIpEntry, IE_REFTYPE_TMP)) // TmpRef
  2496. {
  2497. AADEBUGP(AAD_WARNING,
  2498. ("CleanupArpTable: Aborting stale IP %d:%d:%d:%d\n",
  2499. ((PUCHAR)&(pIpEntry->IPAddress))[0],
  2500. ((PUCHAR)&(pIpEntry->IPAddress))[1],
  2501. ((PUCHAR)&(pIpEntry->IPAddress))[2],
  2502. ((PUCHAR)&(pIpEntry->IPAddress))[3]
  2503. ));
  2504. AtmArpAbortIPEntry(pIpEntry);
  2505. //
  2506. // IE Lock is released within the above.
  2507. //
  2508. }
  2509. //
  2510. // Since we let go of the table lock, we must re-start our search
  2511. // through pMcSendList.
  2512. //
  2513. fTableLockWasReleased = TRUE;
  2514. AA_ACQUIRE_IF_TABLE_LOCK(pInterface);
  2515. break;
  2516. }
  2517. }
  2518. } while (fTableLockWasReleased);
  2519. AA_RELEASE_IF_TABLE_LOCK(pInterface);
  2520. }