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.

2123 lines
49 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. ipmcast.c
  5. Abstract:
  6. Revision History:
  7. Who When What
  8. -------- -------- ----------------------------------------------
  9. arvindm 08-27-96 Created
  10. Notes:
  11. --*/
  12. #include <precomp.h>
  13. #define _FILENUMBER 'CMPI'
  14. #ifdef IPMCAST
  15. UINT
  16. AtmArpMcAddAddress(
  17. IN PATMARP_INTERFACE pInterface LOCKIN NOLOCKOUT,
  18. IN IP_ADDRESS IPAddress,
  19. IN IP_MASK Mask
  20. )
  21. /*++
  22. Routine Description:
  23. The IP layer wants us to start receiving packets directed to this
  24. IP Multicast address. This translates to sending a MARS_JOIN message
  25. to MARS, if conditions are fine.
  26. NOTE: For now, we support a non-zero Mask value (see below) only
  27. for the special case of multicast promiscuous mode.
  28. NOTE: The caller is assumed to have acquired the IF lock, and it
  29. willl be released here.
  30. Arguments:
  31. pInterface - Pointer to ATMARP Interface on which to receive
  32. multicast packets.
  33. IPAddress - Identifies the multicast group to "Join"
  34. Mask - 0 if a single address is being specified, otherwise
  35. a mask that denotes a block of addresses being joined.
  36. Return Value:
  37. (UINT)TRUE if the address was added successfully, (UINT)FALSE otherwise.
  38. --*/
  39. {
  40. BOOLEAN ReturnValue;
  41. BOOLEAN LockReleased;
  42. PATMARP_IPMC_JOIN_ENTRY pJoinEntry;
  43. //
  44. // Initialize.
  45. //
  46. ReturnValue = (UINT)TRUE;
  47. LockReleased = TRUE;
  48. pJoinEntry = NULL_PATMARP_IPMC_JOIN_ENTRY;
  49. do
  50. {
  51. //
  52. // We don't support "block join" yet, i.e. we allow only single
  53. // IP addresses to be joined. Special exception: promiscuous mode
  54. // multicast, or "join everything", indicated by the special values
  55. // of IPAddress and Mask checked for below.
  56. //
  57. if (Mask != 0)
  58. {
  59. if (IPAddress != IP_CLASSD_MIN || Mask != IP_CLASSD_MASK)
  60. {
  61. ReturnValue = (UINT)FALSE;
  62. LockReleased = FALSE;
  63. break;
  64. }
  65. }
  66. //
  67. // Fail this if the interface is going down.
  68. //
  69. if (pInterface->ArpTableUp == FALSE)
  70. {
  71. ReturnValue = (UINT)FALSE;
  72. LockReleased = FALSE;
  73. break;
  74. }
  75. //
  76. // Check if this IP address range has been added before. If so,
  77. // all we need to do is to bump up its ref count.
  78. //
  79. for (pJoinEntry = pInterface->pJoinList;
  80. pJoinEntry != NULL_PATMARP_IPMC_JOIN_ENTRY;
  81. pJoinEntry = pJoinEntry->pNextJoinEntry)
  82. {
  83. if ( pJoinEntry->IPAddress == IPAddress
  84. && pJoinEntry->Mask == Mask)
  85. {
  86. break;
  87. }
  88. }
  89. if (pJoinEntry != NULL_PATMARP_IPMC_JOIN_ENTRY)
  90. {
  91. //
  92. // This address is already added. Just add a reference to it.
  93. //
  94. pJoinEntry->JoinRefCount++;
  95. ReturnValue = (UINT)TRUE;
  96. LockReleased = FALSE;
  97. break;
  98. }
  99. //
  100. // Allocate an entry for this IP address.
  101. //
  102. AA_ALLOC_MEM(pJoinEntry, ATMARP_IPMC_JOIN_ENTRY, sizeof(ATMARP_IPMC_JOIN_ENTRY));
  103. if (pJoinEntry == NULL_PATMARP_IPMC_JOIN_ENTRY)
  104. {
  105. ReturnValue = (UINT)FALSE;
  106. LockReleased = FALSE;
  107. break;
  108. }
  109. //
  110. // Fill in this new entry, and add it to the multicast address list.
  111. //
  112. AA_SET_MEM(pJoinEntry, 0, sizeof(ATMARP_IPMC_JOIN_ENTRY));
  113. #if DBG
  114. pJoinEntry->aamj_sig = aamj_signature;
  115. #endif // DBG
  116. pJoinEntry->IPAddress = IPAddress;
  117. pJoinEntry->Mask = Mask;
  118. pJoinEntry->pInterface = pInterface;
  119. pJoinEntry->JoinRefCount = 1;
  120. pJoinEntry->RefCount = 1;
  121. pJoinEntry->pNextJoinEntry = pInterface->pJoinList;
  122. pInterface->pJoinList = pJoinEntry;
  123. //
  124. // We proceed to send a Join only if we have completed registering with
  125. // the MARS. This is because we need to have a Cluster Member Id before
  126. // we can Join multicast groups. When registration completes, the
  127. // Join operation will be triggered off.
  128. //
  129. if (AAMC_IF_STATE(pInterface) == AAMC_IF_STATE_REGISTERED)
  130. {
  131. AA_SET_FLAG(pJoinEntry->Flags,
  132. AA_IPMC_JE_STATE_MASK,
  133. AA_IPMC_JE_STATE_JOINING);
  134. //
  135. // Start the "Wait For Join completion" timer.
  136. //
  137. AtmArpStartTimer(
  138. pInterface,
  139. &(pJoinEntry->Timer),
  140. AtmArpMcJoinOrLeaveTimeout,
  141. pInterface->JoinTimeout,
  142. (PVOID)pJoinEntry
  143. );
  144. AA_REF_JE(pJoinEntry); // McAddAddr: Wait for Join timer
  145. pJoinEntry->RetriesLeft = pInterface->MaxJoinOrLeaveAttempts - 1;
  146. //
  147. // Send off a MARS_JOIN for this IP address.
  148. //
  149. AtmArpMcSendJoinOrLeave(
  150. pInterface,
  151. AA_MARS_OP_TYPE_JOIN,
  152. &IPAddress,
  153. Mask
  154. );
  155. //
  156. // IF lock is released within the above.
  157. //
  158. }
  159. else
  160. {
  161. pJoinEntry->Flags = AA_IPMC_JE_STATE_PENDING;
  162. AtmArpMcStartRegistration(
  163. pInterface
  164. );
  165. //
  166. // IF lock is released within the above.
  167. //
  168. }
  169. break;
  170. }
  171. while (FALSE);
  172. if (!LockReleased)
  173. {
  174. AA_RELEASE_IF_LOCK(pInterface);
  175. }
  176. AAMCDEBUGP(AAD_LOUD,
  177. ("AtmArpMcAddAddress: pIf 0x%x, Addr 0x%x, Mask 0x%x, JoinEnt 0x%x, Ret %d\n",
  178. pInterface, IPAddress, Mask, pJoinEntry, ReturnValue));
  179. return (ReturnValue);
  180. }
  181. UINT
  182. AtmArpMcDelAddress(
  183. IN PATMARP_INTERFACE pInterface LOCKIN NOLOCKOUT,
  184. IN IP_ADDRESS IPAddress,
  185. IN IP_MASK Mask
  186. )
  187. /*++
  188. Routine Description:
  189. Delete membership of the given multicast IP address group, on the specified
  190. interface. If this is the last surviving reference to this multicast group,
  191. we send off a MARS_LEAVE message to MARS, indicating that we don't want to
  192. receive packets directed to this address anymore.
  193. NOTE: The "Mask" parameter could theoretically be used to identify a block
  194. of IP addresses. We support it for the specific case of stopping promiscuous
  195. multicast receive mode.
  196. NOTE: The caller is assumed to have acquired the IF Lock, which will
  197. be released here.
  198. Arguments:
  199. pInterface - Pointer to ATMARP Interface on which to remove
  200. multicast group membership.
  201. IPAddress - Identifies the multicast group to "Leave"
  202. Mask - 0 if a single address is being specified, otherwise
  203. a mask that denotes a block of addresses being "leave"d.
  204. Return Value:
  205. (UINT)TRUE if the given address was deleted successfully, (UINT)FALSE
  206. otherwise.
  207. --*/
  208. {
  209. PATMARP_IPMC_JOIN_ENTRY pJoinEntry;
  210. PATMARP_IPMC_JOIN_ENTRY *ppNextJoinEntry;
  211. UINT ReturnValue;
  212. BOOLEAN LockAcquired;
  213. BOOLEAN WasRunning;
  214. ULONG rc;
  215. //
  216. // Initialize.
  217. //
  218. ReturnValue = (UINT)TRUE;
  219. pJoinEntry = NULL_PATMARP_IPMC_JOIN_ENTRY;
  220. LockAcquired = TRUE;
  221. do
  222. {
  223. //
  224. // Get the entry corresponding to this IP address and mask.
  225. //
  226. ppNextJoinEntry = &(pInterface->pJoinList);
  227. while (*ppNextJoinEntry != NULL_PATMARP_IPMC_JOIN_ENTRY)
  228. {
  229. if ( (*ppNextJoinEntry)->IPAddress == IPAddress
  230. && (*ppNextJoinEntry)->Mask == Mask)
  231. {
  232. pJoinEntry = *ppNextJoinEntry;
  233. break;
  234. }
  235. ppNextJoinEntry = &((*ppNextJoinEntry)->pNextJoinEntry);
  236. }
  237. if (pJoinEntry == NULL_PATMARP_IPMC_JOIN_ENTRY)
  238. {
  239. //
  240. // No entry for the given IP address!
  241. //
  242. ReturnValue = (UINT)TRUE;
  243. break;
  244. }
  245. //
  246. // If we reached here, this call is successful.
  247. //
  248. ReturnValue = (UINT)TRUE;
  249. pJoinEntry->JoinRefCount--;
  250. if ((pJoinEntry->JoinRefCount == 0) &&
  251. (AA_IS_FLAG_SET(pJoinEntry->Flags,
  252. AA_IPMC_JE_STATE_MASK,
  253. AA_IPMC_JE_STATE_JOINED)))
  254. {
  255. //
  256. // We just removed the last "Join" reference to this multicast group.
  257. // If we are currently registered with MARS, send a MARS_LEAVE.
  258. //
  259. //
  260. // First, stop any timer running on this entry.
  261. //
  262. WasRunning = AtmArpStopTimer(
  263. &(pJoinEntry->Timer),
  264. pInterface
  265. );
  266. if (AAMC_IF_STATE(pInterface) == AAMC_IF_STATE_REGISTERED)
  267. {
  268. //
  269. // Start the "Wait for Leave completion" timer on this entry.
  270. //
  271. AtmArpStartTimer(
  272. pInterface,
  273. &(pJoinEntry->Timer),
  274. AtmArpMcJoinOrLeaveTimeout,
  275. pInterface->LeaveTimeout,
  276. (PVOID)pJoinEntry
  277. );
  278. if (!WasRunning)
  279. {
  280. AA_REF_JE(pJoinEntry); // Started Wait for Leave timer
  281. }
  282. AA_SET_FLAG(pJoinEntry->Flags,
  283. AA_IPMC_JE_STATE_MASK,
  284. AA_IPMC_JE_STATE_LEAVING);
  285. pJoinEntry->RetriesLeft = pInterface->MaxJoinOrLeaveAttempts - 1;
  286. //
  287. // Send off a MARS_LEAVE for this IP address.
  288. //
  289. AtmArpMcSendJoinOrLeave(
  290. pInterface,
  291. AA_MARS_OP_TYPE_LEAVE,
  292. &IPAddress,
  293. Mask
  294. );
  295. //
  296. // IF Lock is released within the above.
  297. //
  298. LockAcquired = FALSE;
  299. }
  300. else
  301. {
  302. //
  303. // We are not registered with MARS, meaning that
  304. // (re)-registration is in progress. Since all Joins
  305. // are invalidated and re-created at the end of registration,
  306. // we don't have to send a LEAVE explicitly for this address.
  307. //
  308. //
  309. // Remove this entry from the Join list, and free it.
  310. //
  311. *ppNextJoinEntry = pJoinEntry->pNextJoinEntry;
  312. AA_ASSERT(!AA_IS_TIMER_ACTIVE(&pJoinEntry->Timer));
  313. if (WasRunning)
  314. {
  315. rc = AA_DEREF_JE(pJoinEntry); // McDelAddr: Timer stopped
  316. }
  317. else
  318. {
  319. rc = pJoinEntry->RefCount;
  320. }
  321. if (rc != 0)
  322. {
  323. rc = AA_DEREF_JE(pJoinEntry); // McDelAddr: get rid of entry
  324. }
  325. else
  326. {
  327. AA_ASSERT(FALSE);
  328. }
  329. }
  330. }
  331. //
  332. // else this IP address has some references outstanding.
  333. // Leave it as is.
  334. //
  335. break;
  336. }
  337. while (FALSE);
  338. if (LockAcquired)
  339. {
  340. AA_RELEASE_IF_LOCK(pInterface);
  341. }
  342. return (ReturnValue);
  343. }
  344. VOID
  345. AtmArpMcHandleJoinOrLeaveCompletion(
  346. IN PATMARP_INTERFACE pInterface,
  347. IN IP_ADDRESS IPAddress,
  348. IN IP_MASK Mask,
  349. IN BOOLEAN IsJoin
  350. )
  351. /*++
  352. Routine Description:
  353. This is called when we receive a JOIN or LEAVE that acknowledges
  354. one that we sent earlier.
  355. Arguments:
  356. pInterface - Pointer to Interface
  357. IPAddress - The group being joined/left
  358. IsJoin - Is this a Join completion?
  359. Return Value:
  360. None
  361. --*/
  362. {
  363. PATMARP_IPMC_JOIN_ENTRY pJoinEntry;
  364. PATMARP_IPMC_JOIN_ENTRY *ppNextJoinEntry;
  365. ULONG NewFlags; // For Join Entry
  366. BOOLEAN SendJoinOrLeave;
  367. ULONG rc;
  368. //
  369. // Find the JOIN Entry for this address
  370. //
  371. AA_ACQUIRE_IF_LOCK(pInterface);
  372. SendJoinOrLeave = FALSE;
  373. pJoinEntry = NULL_PATMARP_IPMC_JOIN_ENTRY;
  374. ppNextJoinEntry = &(pInterface->pJoinList);
  375. while (*ppNextJoinEntry != NULL_PATMARP_IPMC_JOIN_ENTRY)
  376. {
  377. if ( (*ppNextJoinEntry)->IPAddress == IPAddress
  378. &&(*ppNextJoinEntry)->Mask == Mask)
  379. {
  380. pJoinEntry = *ppNextJoinEntry;
  381. break;
  382. }
  383. ppNextJoinEntry = &((*ppNextJoinEntry)->pNextJoinEntry);
  384. }
  385. if (pJoinEntry != NULL_PATMARP_IPMC_JOIN_ENTRY)
  386. {
  387. BOOLEAN WasRunning;
  388. WasRunning = AtmArpStopTimer(&(pJoinEntry->Timer), pInterface);
  389. if (WasRunning)
  390. {
  391. rc = AA_DEREF_JE(pJoinEntry); // Join Complete, stopped timer
  392. AA_ASSERT(rc != 0);
  393. }
  394. if (IsJoin)
  395. {
  396. AAMCDEBUGP(AAD_INFO,
  397. ("JOINed %d.%d.%d.%d, pJoinEntry 0x%x, Flags 0x%x, JoinRefCount %d\n",
  398. ((PUCHAR)&IPAddress)[0],
  399. ((PUCHAR)&IPAddress)[1],
  400. ((PUCHAR)&IPAddress)[2],
  401. ((PUCHAR)&IPAddress)[3],
  402. pJoinEntry, pJoinEntry->Flags, pJoinEntry->JoinRefCount
  403. ));
  404. AA_SET_FLAG(pJoinEntry->Flags,
  405. AA_IPMC_JE_STATE_MASK,
  406. AA_IPMC_JE_STATE_JOINED);
  407. //
  408. // Check if IP had deleted this address while we
  409. // were joining it.
  410. //
  411. if (pJoinEntry->JoinRefCount == 0)
  412. {
  413. //
  414. // Send a Leave.
  415. //
  416. SendJoinOrLeave = TRUE;
  417. AA_SET_FLAG(pJoinEntry->Flags,
  418. AA_IPMC_JE_STATE_MASK,
  419. AA_IPMC_JE_STATE_LEAVING);
  420. }
  421. }
  422. else
  423. {
  424. //
  425. // This signifies completion of a LEAVE process.
  426. //
  427. AAMCDEBUGP(AAD_INFO,
  428. ("LEFT %d.%d.%d.%d, pJoinEntry 0x%x, Flags 0x%x, RefCount %d\n",
  429. ((PUCHAR)&IPAddress)[0],
  430. ((PUCHAR)&IPAddress)[1],
  431. ((PUCHAR)&IPAddress)[2],
  432. ((PUCHAR)&IPAddress)[3],
  433. pJoinEntry, pJoinEntry->Flags, pJoinEntry->JoinRefCount
  434. ));
  435. //
  436. // IP might have re-joined this address while we were
  437. // waiting for completion of leave.
  438. //
  439. if (pJoinEntry->JoinRefCount != 0)
  440. {
  441. //
  442. // Send a Join.
  443. //
  444. SendJoinOrLeave = TRUE;
  445. AA_SET_FLAG(pJoinEntry->Flags,
  446. AA_IPMC_JE_STATE_MASK,
  447. AA_IPMC_JE_STATE_JOINING);
  448. }
  449. else
  450. {
  451. //
  452. // Unlink Join Entry from list.
  453. //
  454. *ppNextJoinEntry = pJoinEntry->pNextJoinEntry;
  455. //
  456. // And free it.
  457. //
  458. AA_ASSERT(!AA_IS_TIMER_ACTIVE(&pJoinEntry->Timer));
  459. rc = AA_DEREF_JE(pJoinEntry); // Leave Complete - get rid of entry
  460. AA_ASSERT(SendJoinOrLeave == FALSE);
  461. }
  462. }
  463. }
  464. if (SendJoinOrLeave)
  465. {
  466. USHORT Opcode;
  467. //
  468. // Start the "Wait for Leave completion" timer on this entry.
  469. //
  470. AtmArpStartTimer(
  471. pInterface,
  472. &(pJoinEntry->Timer),
  473. AtmArpMcJoinOrLeaveTimeout,
  474. pInterface->LeaveTimeout,
  475. (PVOID)pJoinEntry
  476. );
  477. AA_REF_JE(pJoinEntry); // Wait for Join/Leave completion
  478. pJoinEntry->RetriesLeft = pInterface->MaxJoinOrLeaveAttempts - 1;
  479. Opcode = (IsJoin? AA_MARS_OP_TYPE_LEAVE: AA_MARS_OP_TYPE_JOIN);
  480. AtmArpMcSendJoinOrLeave(
  481. pInterface,
  482. Opcode,
  483. &IPAddress,
  484. Mask
  485. );
  486. //
  487. // IF Lock is released within the above.
  488. //
  489. }
  490. else
  491. {
  492. AA_RELEASE_IF_LOCK(pInterface);
  493. }
  494. }
  495. VOID
  496. AtmArpMcStartRegistration(
  497. IN PATMARP_INTERFACE pInterface LOCKIN NOLOCKOUT
  498. )
  499. /*++
  500. Routine Description:
  501. Start registration with the MARS, if all pre-conditions are met:
  502. 0. AdminState for this Interface is UP
  503. 1. Registration isn't done or in progress
  504. 2. The ATM Interface is up
  505. 3. Atleast one MARS ATM address is known (configured).
  506. NOTE: The caller is assumed to have locked the Interface structure,
  507. and the lock will be released here.
  508. Arguments:
  509. pInterface - Interface on which MARS registration is to be done.
  510. Return Value:
  511. None
  512. --*/
  513. {
  514. BOOLEAN WasRunning;
  515. AAMCDEBUGP(AAD_LOUD,
  516. ("McStartReg: IF 0x%x, AdminState %d, AtmIfUp %d, Marslist size %d\n",
  517. pInterface,
  518. pInterface->AdminState,
  519. pInterface->AtmInterfaceUp,
  520. pInterface->MARSList.ListSize));
  521. if ((!pInterface->PVCOnly) &&
  522. (pInterface->AdminState == IF_STATUS_UP) &&
  523. (AAMC_IF_STATE(pInterface) == AAMC_IF_STATE_NOT_REGISTERED) &&
  524. (pInterface->AtmInterfaceUp) &&
  525. (pInterface->MARSList.ListSize > 0))
  526. {
  527. AAMCDEBUGP(AAD_INFO, ("Starting MARS registration on IF 0x%x\n", pInterface));
  528. AAMC_SET_IF_STATE(pInterface, AAMC_IF_STATE_REGISTERING);
  529. //
  530. // Stop any running timer.
  531. //
  532. WasRunning = AtmArpStopTimer(
  533. &(pInterface->McTimer),
  534. pInterface
  535. );
  536. //
  537. // Start a timer to police completion of MARS registration.
  538. //
  539. AtmArpStartTimer(
  540. pInterface,
  541. &(pInterface->McTimer),
  542. AtmArpMcMARSRegistrationTimeout,
  543. pInterface->MARSRegistrationTimeout,
  544. (PVOID)pInterface
  545. );
  546. if (!WasRunning)
  547. {
  548. AtmArpReferenceInterface(pInterface); // MARS Reg timer ref
  549. }
  550. pInterface->McRetriesLeft = pInterface->MaxRegistrationAttempts - 1;
  551. //
  552. // Send a MARS_JOIN
  553. //
  554. AtmArpMcSendJoinOrLeave(
  555. pInterface,
  556. AA_MARS_OP_TYPE_JOIN,
  557. NULL, // Not Joining any specific Multicast group (=> registration)
  558. 0 // Mask (don't care)
  559. );
  560. //
  561. // IF Lock is released within the above
  562. //
  563. }
  564. else
  565. {
  566. AA_RELEASE_IF_LOCK(pInterface);
  567. }
  568. }
  569. VOID
  570. AtmArpMcSendPendingJoins(
  571. IN PATMARP_INTERFACE pInterface LOCKIN NOLOCKOUT
  572. )
  573. /*++
  574. Routine Description:
  575. Send MARS_JOIN on behalf of all Joins pending initial registration.
  576. NOTE: The caller is assumed to have a lock for the Interface,
  577. which will be released here.
  578. Arguments:
  579. pInterface - Interface on which pending Joins are to be sent.
  580. Return Value:
  581. None
  582. --*/
  583. {
  584. typedef struct
  585. {
  586. IP_ADDRESS IPAddress;
  587. IP_MASK Mask;
  588. } AA_IP_MASK_PAIR;
  589. PATMARP_IPMC_JOIN_ENTRY pJoinEntry;
  590. PATMARP_IPMC_JOIN_ENTRY pNextJoinEntry;
  591. UINT NumEntries;
  592. AA_IP_MASK_PAIR *DestArray;
  593. //
  594. // Count the entries which need to be sent.
  595. //
  596. for (pJoinEntry = pInterface->pJoinList, NumEntries=0;
  597. pJoinEntry != NULL_PATMARP_IPMC_JOIN_ENTRY;
  598. pJoinEntry = pJoinEntry->pNextJoinEntry)
  599. {
  600. if (AA_IS_FLAG_SET(pJoinEntry->Flags,
  601. AA_IPMC_JE_STATE_MASK,
  602. AA_IPMC_JE_STATE_PENDING))
  603. {
  604. NumEntries++;
  605. }
  606. }
  607. if (NumEntries)
  608. {
  609. //
  610. // Allocate temporary space to hold their ip addresses and masks.
  611. //
  612. AA_ALLOC_MEM(
  613. DestArray,
  614. AA_IP_MASK_PAIR,
  615. NumEntries*sizeof(AA_IP_MASK_PAIR)
  616. );
  617. }
  618. else
  619. {
  620. DestArray = NULL;
  621. }
  622. if (DestArray!=NULL)
  623. {
  624. AA_IP_MASK_PAIR *pPair = DestArray;
  625. AA_IP_MASK_PAIR *pPairEnd = DestArray + NumEntries;
  626. //
  627. // Now go through the list again, setting the state of the entries
  628. // appropriately, and picking up the ipaddresses&masks.
  629. // Note that we continue to hold the interface lock, to the
  630. // join entry list can't grow or shrink, nor any join entry
  631. // change state. Neverthless, we check for these cases.
  632. //
  633. for (pJoinEntry = pInterface->pJoinList;
  634. pJoinEntry != NULL_PATMARP_IPMC_JOIN_ENTRY;
  635. pJoinEntry = pJoinEntry->pNextJoinEntry)
  636. {
  637. if (AA_IS_FLAG_SET(pJoinEntry->Flags,
  638. AA_IPMC_JE_STATE_MASK,
  639. AA_IPMC_JE_STATE_PENDING))
  640. {
  641. PIP_ADDRESS pIpAddress;
  642. if (pPair >= pPairEnd)
  643. {
  644. //
  645. // This means there are now more join entries in
  646. // this state then when we counted just above!
  647. // We deal with it by breaking out early, but really
  648. // this is an assert and if we hit it neet to determine
  649. // why the state of join entries are changing elsewhere
  650. // when we have the interface lock.
  651. //
  652. AA_ASSERT(FALSE);
  653. break;
  654. }
  655. pPair->IPAddress = pJoinEntry->IPAddress;
  656. pPair->Mask = pJoinEntry->Mask;
  657. pIpAddress = &(pJoinEntry->IPAddress);
  658. AA_SET_FLAG(pJoinEntry->Flags,
  659. AA_IPMC_JE_STATE_MASK,
  660. AA_IPMC_JE_STATE_JOINING);
  661. //
  662. // Send off a MARS_JOIN for this IP address.
  663. //
  664. AAMCDEBUGP(AAD_INFO,
  665. ("Sending Pended Join: pIf 0x%x, pJoinEntry 0x%x, Addr: %d.%d.%d.%d\n",
  666. pInterface,
  667. pJoinEntry,
  668. ((PUCHAR)pIpAddress)[0],
  669. ((PUCHAR)pIpAddress)[1],
  670. ((PUCHAR)pIpAddress)[2],
  671. ((PUCHAR)pIpAddress)[3]));
  672. //
  673. // Start the "Wait For Join completion" timer.
  674. //
  675. AtmArpStartTimer(
  676. pInterface,
  677. &(pJoinEntry->Timer),
  678. AtmArpMcJoinOrLeaveTimeout,
  679. pInterface->JoinTimeout,
  680. (PVOID)pJoinEntry
  681. );
  682. AA_REF_JE(pJoinEntry); // Wait for Join completion - pended join
  683. pJoinEntry->RetriesLeft = pInterface->MaxJoinOrLeaveAttempts - 1;
  684. pPair++;
  685. }
  686. }
  687. AA_ASSERT(pPair == pPairEnd);
  688. //
  689. // But just in case ....
  690. //
  691. if (pPair < pPairEnd)
  692. {
  693. //
  694. // Only send joins for as many as we've copied over.
  695. //
  696. pPairEnd = pPair;
  697. }
  698. //
  699. // Now actually send the JOIN entries. Note that the interface
  700. // lock is released/reacquired once per iteration.
  701. //
  702. for (pPair = DestArray;
  703. pPair < pPairEnd;
  704. pPair++)
  705. {
  706. AtmArpMcSendJoinOrLeave(
  707. pInterface,
  708. AA_MARS_OP_TYPE_JOIN,
  709. &(pPair->IPAddress),
  710. pPair->Mask
  711. );
  712. //
  713. // IF Lock is released within the above.
  714. //
  715. AA_ACQUIRE_IF_LOCK(pInterface);
  716. }
  717. AA_FREE_MEM(DestArray);
  718. DestArray = NULL;
  719. }
  720. AA_RELEASE_IF_LOCK(pInterface);
  721. }
  722. VOID
  723. AtmArpMcRevalidateAll(
  724. IN PATMARP_INTERFACE pInterface
  725. )
  726. /*++
  727. Routine Description:
  728. An event has happened that needs us to revalidate all group information.
  729. The RFC says that we should set the REVALIDATE flag on all groups at a
  730. random time between 1 and 10 seconds. We implement this by starting
  731. "random" timers on all groups.
  732. Arguments:
  733. pInterface - Interface on which revalidation is to be done
  734. Return Value:
  735. None
  736. --*/
  737. {
  738. PATMARP_IP_ENTRY pIpEntry;
  739. AAMCDEBUGP(AAD_INFO, ("McRevalidateAll on IF 0x%x\n", pInterface));
  740. AA_ACQUIRE_IF_TABLE_LOCK(pInterface);
  741. //
  742. // Go through the list of IP Entries representing multicast addresses
  743. // that we send to.
  744. //
  745. for (pIpEntry = pInterface->pMcSendList;
  746. pIpEntry != NULL_PATMARP_IP_ENTRY;
  747. pIpEntry = pIpEntry->pNextMcEntry)
  748. {
  749. AA_ASSERT(AA_IS_FLAG_SET(pIpEntry->Flags,
  750. AA_IP_ENTRY_ADDR_TYPE_MASK,
  751. AA_IP_ENTRY_ADDR_TYPE_NUCAST));
  752. AA_ACQUIRE_IE_LOCK(pIpEntry);
  753. AA_ASSERT(AA_IE_IS_ALIVE(pIpEntry));
  754. if (AA_IS_FLAG_SET(pIpEntry->Flags,
  755. AA_IP_ENTRY_MC_RESOLVE_MASK,
  756. AA_IP_ENTRY_MC_RESOLVED))
  757. {
  758. ULONG RandomDelay;
  759. BOOLEAN WasRunning;
  760. WasRunning = AtmArpStopTimer(&(pIpEntry->Timer), pInterface);
  761. RandomDelay = AA_GET_RANDOM(
  762. pInterface->MinRevalidationDelay,
  763. pInterface->MaxRevalidationDelay);
  764. AAMCDEBUGP(AAD_LOUD,
  765. ("McRevalidateAll: pIpEntry 0x%x/0x%x, Addr: %d.%d.%d.%d, pAtmEntry 0x%x\n",
  766. pIpEntry, pIpEntry->Flags,
  767. ((PUCHAR)&(pIpEntry->IPAddress))[0],
  768. ((PUCHAR)&(pIpEntry->IPAddress))[1],
  769. ((PUCHAR)&(pIpEntry->IPAddress))[2],
  770. ((PUCHAR)&(pIpEntry->IPAddress))[3],
  771. pIpEntry->pAtmEntry));
  772. AtmArpStartTimer(
  773. pInterface,
  774. &(pIpEntry->Timer),
  775. AtmArpMcRevalidationDelayTimeout,
  776. RandomDelay,
  777. (PVOID)pIpEntry
  778. );
  779. if (!WasRunning)
  780. {
  781. AA_REF_IE(pIpEntry, IE_REFTYPE_TIMER); // Timer ref
  782. }
  783. }
  784. AA_RELEASE_IE_LOCK(pIpEntry);
  785. }
  786. AA_RELEASE_IF_TABLE_LOCK(pInterface);
  787. }
  788. VOID
  789. AtmArpMcHandleMARSFailure(
  790. IN PATMARP_INTERFACE pInterface,
  791. IN BOOLEAN IsRegnFailure
  792. )
  793. /*++
  794. Routine Description:
  795. Handle a MARS failure, as per Section 5.4.1 etc in RFC 2022.
  796. On seeing the first failure, we assume that there is a transient
  797. problem with the MARS, so we try to re-register. If we fail to do
  798. so, we pick up the next MARS in our configured list. If no such
  799. MARS exists, then we wait for a while before retrying registration.
  800. Arguments:
  801. pInterface - Interface on which MARS failure has been detected.
  802. IsRegnFailure - Is this a failure in registering?
  803. Return Value:
  804. None
  805. --*/
  806. {
  807. BOOLEAN WasRunning;
  808. ULONG rc;
  809. PATMARP_IPMC_JOIN_ENTRY pJoinEntry;
  810. PATMARP_IPMC_JOIN_ENTRY * ppJoinEntry;
  811. AAMCDEBUGP(AAD_INFO, ("HandleMARSFailure: pIf 0x%x, Flags 0x%x, RegnFailure=%d\n",
  812. pInterface, pInterface->Flags, IsRegnFailure));
  813. AA_ACQUIRE_IF_LOCK(pInterface);
  814. //
  815. // Stop the MC timer running on this Interface.
  816. //
  817. WasRunning = AtmArpStopTimer(&(pInterface->McTimer), pInterface);
  818. if (WasRunning)
  819. {
  820. rc = AtmArpDereferenceInterface(pInterface); // MC Timer ref
  821. AA_ASSERT(rc != 0);
  822. }
  823. if (AA_IS_FLAG_SET(pInterface->Flags,
  824. AAMC_IF_MARS_FAILURE_MASK,
  825. AAMC_IF_MARS_FAILURE_NONE))
  826. {
  827. //
  828. // First failure. Do some housekeeping, and re-register with
  829. // the MARS.
  830. //
  831. AA_SET_FLAG(pInterface->Flags,
  832. AAMC_IF_MARS_FAILURE_MASK,
  833. AAMC_IF_MARS_FAILURE_FIRST_RESP);
  834. //
  835. // Clean up all our JOIN Entries.
  836. //
  837. ppJoinEntry = &(pInterface->pJoinList);
  838. while (*ppJoinEntry != NULL_PATMARP_IPMC_JOIN_ENTRY)
  839. {
  840. pJoinEntry = *ppJoinEntry;
  841. WasRunning = AtmArpStopTimer(&(pJoinEntry->Timer), pInterface);
  842. if (WasRunning)
  843. {
  844. rc = AA_DEREF_JE(pJoinEntry); // MARS failure; stopped timer
  845. AA_ASSERT(rc != 0);
  846. }
  847. if (AA_IS_FLAG_SET(pJoinEntry->Flags,
  848. AA_IPMC_JE_STATE_MASK,
  849. AA_IPMC_JE_STATE_LEAVING))
  850. {
  851. //
  852. // Delete this because it is leaving.
  853. //
  854. *ppJoinEntry = pJoinEntry->pNextJoinEntry;
  855. AA_ASSERT(!AA_IS_TIMER_ACTIVE(&pJoinEntry->Timer));
  856. AA_DEREF_JE(pJoinEntry); // MARS Failure; get rid of leaving entry
  857. }
  858. else
  859. {
  860. //
  861. // Mark this as "pending" so that we will re-join
  862. // this group as soon as we complete re-registration.
  863. //
  864. AA_SET_FLAG(pJoinEntry->Flags,
  865. AA_IPMC_JE_STATE_MASK,
  866. AA_IPMC_JE_STATE_PENDING);
  867. ppJoinEntry = &(pJoinEntry->pNextJoinEntry);
  868. }
  869. }
  870. //
  871. // Prime the IF state so that registration can happen.
  872. //
  873. AAMC_SET_IF_STATE(pInterface, AAMC_IF_STATE_NOT_REGISTERED);
  874. AtmArpMcStartRegistration(pInterface);
  875. //
  876. // IF Lock is released within the above.
  877. //
  878. }
  879. else if (pInterface->AdminState == IF_STATUS_UP)
  880. {
  881. //
  882. // Check if this is a failure to re-register.
  883. //
  884. if (AA_IS_FLAG_SET(pInterface->Flags,
  885. AAMC_IF_MARS_FAILURE_MASK,
  886. AAMC_IF_MARS_FAILURE_FIRST_RESP) ||
  887. IsRegnFailure)
  888. {
  889. //
  890. // Absolutely no hope for this MARS. If we have more entries in
  891. // the MARS list, move to the next one. In any case, delay for
  892. // atleast 1 minute before re-registering.
  893. //
  894. if (pInterface->pCurrentMARS->pNext != (PATMARP_SERVER_ENTRY)NULL)
  895. {
  896. pInterface->pCurrentMARS = pInterface->pCurrentMARS->pNext;
  897. }
  898. else
  899. {
  900. pInterface->pCurrentMARS = pInterface->MARSList.pList;
  901. }
  902. }
  903. AA_SET_FLAG(pInterface->Flags,
  904. AAMC_IF_MARS_FAILURE_MASK,
  905. AAMC_IF_MARS_FAILURE_SECOND_RESP);
  906. AAMC_SET_IF_STATE(pInterface, AAMC_IF_STATE_DELAY_B4_REGISTERING);
  907. AtmArpStartTimer(
  908. pInterface,
  909. &(pInterface->McTimer),
  910. AtmArpMcMARSReconnectTimeout,
  911. pInterface->MARSConnectInterval,
  912. (PVOID)pInterface
  913. );
  914. AtmArpReferenceInterface(pInterface); // MC Timer ref
  915. AA_RELEASE_IF_LOCK(pInterface);
  916. }
  917. else
  918. {
  919. //
  920. // AdminStatus is not UP -- don't try to re-register.
  921. //
  922. AA_RELEASE_IF_LOCK(pInterface);
  923. }
  924. }
  925. VOID
  926. AtmArpMcSendToMARS(
  927. IN PATMARP_INTERFACE pInterface,
  928. IN PNDIS_PACKET pNdisPacket
  929. )
  930. /*++
  931. Routine Description:
  932. Send the given packet to MARS on the specified interface.
  933. NOTE: The caller is assumed to have acquired the Interface lock, which
  934. will be released here.
  935. Arguments:
  936. pInterface - Interface on which the MARS message is to be sent.
  937. pNdisPacket - Points to packet to be sent. This is assumed to be
  938. allocated by ourselves.
  939. Return Value:
  940. None
  941. --*/
  942. {
  943. PATMARP_ATM_ENTRY pAtmEntry;
  944. PATMARP_VC pVc;
  945. PATMARP_FLOW_SPEC pFlowSpec;
  946. NDIS_STATUS Status;
  947. ULONG rc;
  948. AA_ASSERT(pInterface->pCurrentMARS != NULL_PATMARP_SERVER_ENTRY);
  949. pAtmEntry = pInterface->pCurrentMARS->pAtmEntry;
  950. AA_ASSERT(pAtmEntry != NULL_PATMARP_ATM_ENTRY);
  951. AAMCDEBUGP(AAD_EXTRA_LOUD,
  952. ("SendToMars: pIf 0x%x, NdisPkt 0x%x, MARS ATM Entry 0x%x\n",
  953. pInterface, pNdisPacket, pAtmEntry));
  954. AA_RELEASE_IF_LOCK(pInterface);
  955. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  956. //
  957. // Get at the best effort VC going to this address
  958. //
  959. pVc = pAtmEntry->pBestEffortVc;
  960. if (pVc != NULL_PATMARP_VC)
  961. {
  962. //
  963. // Nail down the VC.
  964. //
  965. AA_ACQUIRE_VC_LOCK_DPC(pVc);
  966. AtmArpReferenceVc(pVc); // temp ref
  967. AA_RELEASE_VC_LOCK_DPC(pVc);
  968. AA_RELEASE_AE_LOCK(pAtmEntry); // Not needed anymore
  969. //
  970. // We found a VC to MARS. Make sure it is still around, and send the
  971. // packet on it.
  972. //
  973. AA_ACQUIRE_VC_LOCK(pVc);
  974. rc = AtmArpDereferenceVc(pVc); // temp ref
  975. if (rc != 0)
  976. {
  977. AtmArpSendPacketOnVc(pVc, pNdisPacket);
  978. //
  979. // The VC lock is released in SendPacketOnVc
  980. //
  981. }
  982. else
  983. {
  984. //
  985. // The VC has been deref'ed away! Set up "pVc" for the check
  986. // coming up.
  987. //
  988. pVc = NULL_PATMARP_VC;
  989. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  990. }
  991. }
  992. if (pVc == NULL_PATMARP_VC)
  993. {
  994. //
  995. // We don't have an appropriate VC to the MARS, so create
  996. // one, and queue this packet for transmission as soon as
  997. // the call is made.
  998. //
  999. // AtmArpMakeCall needs the caller to hold the ATM Entry lock.
  1000. //
  1001. AA_GET_CONTROL_PACKET_SPECS(pInterface, &pFlowSpec);
  1002. Status = AtmArpMakeCall(
  1003. pInterface,
  1004. pAtmEntry,
  1005. pFlowSpec,
  1006. pNdisPacket
  1007. );
  1008. //
  1009. // The AE lock is released within the above.
  1010. //
  1011. }
  1012. }
  1013. VOID
  1014. AtmArpMcSendJoinOrLeave(
  1015. IN PATMARP_INTERFACE pInterface,
  1016. IN USHORT OpCode,
  1017. IN PIP_ADDRESS pIpAddress OPTIONAL,
  1018. IN IP_ADDRESS Mask
  1019. )
  1020. /*++
  1021. Routine Description:
  1022. Send a MARS_JOIN or MARS_LEAVE to the MARS on the specified interface.
  1023. If no IP address is given, then this message is being sent to (de)-register
  1024. ourselves with the MARS. Otherwise, we are Joining/Leaving the multicast
  1025. group(s) indicated by the IP address and mask.
  1026. NOTE: The caller is assumed to have acquired the Interface lock, which
  1027. will be released here.
  1028. Arguments:
  1029. pInterface - Interface on which the MARS message is to be sent.
  1030. OpCode - JOIN or LEAVE
  1031. pIpAddress - Optional pointer to first IP address in block
  1032. of Class D IP addresses being Joined/Left. NULL if
  1033. the JOIN/LEAVE message is being sent in order to
  1034. (de)register.
  1035. Mask - Defines the block [*pIpAddress to (*pIpAddress | Mask)]
  1036. of IP addresses being Joined/Left, if pIpAddress isn't
  1037. NULL.
  1038. Return Value:
  1039. None
  1040. --*/
  1041. {
  1042. PNDIS_PACKET pNdisPacket;
  1043. PNDIS_BUFFER pNdisBuffer;
  1044. ULONG BufferLength;
  1045. PAA_MARS_JOIN_LEAVE_HEADER pPkt;
  1046. PUCHAR pNextToFill; // Next field to fill in packet
  1047. IP_ADDRESS MaxIPAddress; // being joined
  1048. BufferLength = sizeof(AA_MARS_JOIN_LEAVE_HEADER) +
  1049. pInterface->LocalAtmAddress.NumberOfDigits;
  1050. AA_RELEASE_IF_LOCK(pInterface);
  1051. #if DBG
  1052. if (pIpAddress != (PIP_ADDRESS)NULL)
  1053. {
  1054. AAMCDEBUGP(AAD_VERY_LOUD,
  1055. ("SendJoinOrLeave: pIf 0x%x, Op %d, IP Address: %d.%d.%d.%d\n",
  1056. pInterface, OpCode,
  1057. ((PUCHAR)pIpAddress)[0],
  1058. ((PUCHAR)pIpAddress)[1],
  1059. ((PUCHAR)pIpAddress)[2],
  1060. ((PUCHAR)pIpAddress)[3]));
  1061. }
  1062. else
  1063. {
  1064. AAMCDEBUGP(AAD_VERY_LOUD,
  1065. ("SendJoinOrLeave: pIf 0x%x, Op %d, No IP Address\n",
  1066. pInterface, OpCode));
  1067. }
  1068. #endif // DBG
  1069. if (pIpAddress != (PIP_ADDRESS)NULL)
  1070. {
  1071. BufferLength += (2 * AA_IPV4_ADDRESS_LENGTH);
  1072. }
  1073. //
  1074. // Allocate packet
  1075. //
  1076. pNdisPacket = AtmArpAllocatePacket(pInterface);
  1077. if (pNdisPacket != (PNDIS_PACKET)NULL)
  1078. {
  1079. //
  1080. // Allocate buffer
  1081. //
  1082. pNdisBuffer = AtmArpAllocateProtoBuffer(
  1083. pInterface,
  1084. BufferLength,
  1085. (PUCHAR *)&pPkt
  1086. );
  1087. if (pNdisBuffer != (PNDIS_BUFFER)NULL)
  1088. {
  1089. NdisChainBufferAtFront(pNdisPacket, pNdisBuffer);
  1090. AA_SET_MEM((PUCHAR)pPkt, 0, BufferLength);
  1091. //
  1092. // Fill in fixed fields first.
  1093. //
  1094. AA_COPY_MEM((PUCHAR)pPkt,
  1095. (PUCHAR)&AtmArpMcMARSFixedHeader,
  1096. sizeof(AtmArpMcMARSFixedHeader));
  1097. pPkt->op = NET_SHORT(OpCode);
  1098. pPkt->shtl = AA_PKT_ATM_ADDRESS_TO_TYPE_LEN(&(pInterface->LocalAtmAddress));
  1099. if (pIpAddress != (PIP_ADDRESS)NULL)
  1100. {
  1101. pPkt->tpln = AA_IPV4_ADDRESS_LENGTH;
  1102. }
  1103. //
  1104. // The only addresses we fill in are Source ATM Number and
  1105. // Target multicast group address.
  1106. //
  1107. pNextToFill = (PUCHAR)pPkt + sizeof(AA_MARS_JOIN_LEAVE_HEADER);
  1108. //
  1109. // Source ATM Number:
  1110. //
  1111. AA_COPY_MEM(pNextToFill,
  1112. (pInterface->LocalAtmAddress.Address),
  1113. pInterface->LocalAtmAddress.NumberOfDigits);
  1114. pNextToFill += pInterface->LocalAtmAddress.NumberOfDigits;
  1115. //
  1116. // Target Multicast Group Address:
  1117. //
  1118. if (pIpAddress != (PIP_ADDRESS)NULL)
  1119. {
  1120. //
  1121. // Joining a layer 3 group
  1122. //
  1123. pPkt->pnum = HOST_TO_NET_SHORT(1);
  1124. pPkt->flags |= AA_MARS_JL_FLAG_LAYER3_GROUP;
  1125. //
  1126. // Fill in one <Min, Max> pair: "Min" value first:
  1127. //
  1128. AA_COPY_MEM(pNextToFill,
  1129. pIpAddress,
  1130. AA_IPV4_ADDRESS_LENGTH);
  1131. pNextToFill += AA_IPV4_ADDRESS_LENGTH;
  1132. //
  1133. // Compute the "Max" value, and fill it in.
  1134. //
  1135. MaxIPAddress = *pIpAddress | Mask;
  1136. AA_COPY_MEM(pNextToFill,
  1137. &(MaxIPAddress),
  1138. AA_IPV4_ADDRESS_LENGTH);
  1139. }
  1140. else
  1141. {
  1142. //
  1143. // Registering as a Cluster Member
  1144. //
  1145. pPkt->flags |= AA_MARS_JL_FLAG_REGISTER;
  1146. }
  1147. AA_ACQUIRE_IF_LOCK(pInterface);
  1148. AtmArpMcSendToMARS(
  1149. pInterface,
  1150. pNdisPacket
  1151. );
  1152. //
  1153. // IF Lock is released within the above.
  1154. //
  1155. }
  1156. else
  1157. {
  1158. AtmArpFreePacket(pInterface, pNdisPacket);
  1159. }
  1160. }
  1161. }
  1162. VOID
  1163. AtmArpMcSendRequest(
  1164. IN PATMARP_INTERFACE pInterface,
  1165. IN PIP_ADDRESS pIpAddress
  1166. )
  1167. /*++
  1168. Routine Description:
  1169. Send a MARS Request to resolve a multicast group address, on the specified
  1170. interface.
  1171. Arguments:
  1172. pInterface - Interface on which the MARS message is to be sent.
  1173. pIpAddress - Pointer to Address to be resolved.
  1174. Return Value:
  1175. None
  1176. --*/
  1177. {
  1178. PNDIS_PACKET pNdisPacket;
  1179. PNDIS_BUFFER pNdisBuffer;
  1180. ULONG BufferLength;
  1181. PAA_MARS_REQ_NAK_HEADER pPkt;
  1182. AAMCDEBUGP(AAD_LOUD,
  1183. ("McSendRequest: pIf 0x%x, IP Address: %d.%d.%d.%d\n",
  1184. pInterface,
  1185. ((PUCHAR)pIpAddress)[0],
  1186. ((PUCHAR)pIpAddress)[1],
  1187. ((PUCHAR)pIpAddress)[2],
  1188. ((PUCHAR)pIpAddress)[3]));
  1189. BufferLength = sizeof(AA_MARS_REQ_NAK_HEADER) +
  1190. pInterface->LocalAtmAddress.NumberOfDigits +
  1191. AA_IPV4_ADDRESS_LENGTH;
  1192. //
  1193. // Allocate packet
  1194. //
  1195. pNdisPacket = AtmArpAllocatePacket(pInterface);
  1196. if (pNdisPacket != (PNDIS_PACKET)NULL)
  1197. {
  1198. //
  1199. // Allocate buffer
  1200. //
  1201. pNdisBuffer = AtmArpAllocateProtoBuffer(
  1202. pInterface,
  1203. BufferLength,
  1204. (PUCHAR *)&pPkt
  1205. );
  1206. if (pNdisBuffer != (PNDIS_BUFFER)NULL)
  1207. {
  1208. NdisChainBufferAtFront(pNdisPacket, pNdisBuffer);
  1209. AA_SET_MEM((PUCHAR)pPkt, 0, BufferLength);
  1210. //
  1211. // Fill in fixed fields first.
  1212. //
  1213. AA_COPY_MEM((PUCHAR)pPkt,
  1214. (PUCHAR)&AtmArpMcMARSFixedHeader,
  1215. sizeof(AtmArpMcMARSFixedHeader));
  1216. pPkt->op = NET_SHORT(AA_MARS_OP_TYPE_REQUEST);
  1217. pPkt->shtl = AA_PKT_ATM_ADDRESS_TO_TYPE_LEN(&(pInterface->LocalAtmAddress));
  1218. pPkt->tpln = AA_IPV4_ADDRESS_LENGTH;
  1219. //
  1220. // The only addresses we fill in are Source ATM Number and
  1221. // Target multicast group address.
  1222. //
  1223. //
  1224. // Source ATM Number:
  1225. //
  1226. AA_COPY_MEM((PUCHAR)pPkt + sizeof(AA_MARS_REQ_NAK_HEADER),
  1227. (pInterface->LocalAtmAddress.Address),
  1228. pInterface->LocalAtmAddress.NumberOfDigits);
  1229. //
  1230. // Target Multicast Group Address:
  1231. //
  1232. AA_COPY_MEM((PUCHAR)pPkt + sizeof(AA_MARS_REQ_NAK_HEADER) +
  1233. pInterface->LocalAtmAddress.NumberOfDigits,
  1234. pIpAddress,
  1235. AA_IPV4_ADDRESS_LENGTH);
  1236. AA_ACQUIRE_IF_LOCK(pInterface);
  1237. AtmArpMcSendToMARS(
  1238. pInterface,
  1239. pNdisPacket
  1240. );
  1241. //
  1242. // IF Lock is released within the above.
  1243. //
  1244. }
  1245. else
  1246. {
  1247. AtmArpFreePacket(pInterface, pNdisPacket);
  1248. }
  1249. }
  1250. }
  1251. PATMARP_IPMC_ATM_ENTRY
  1252. AtmArpMcLookupAtmMember(
  1253. IN PATMARP_ATM_ENTRY pAtmEntry,
  1254. IN PATMARP_IPMC_ATM_ENTRY * ppMcAtmList,
  1255. IN PUCHAR pAtmNumber,
  1256. IN ULONG AtmNumberLength,
  1257. IN ATM_ADDRESSTYPE AtmNumberType,
  1258. IN PUCHAR pAtmSubaddress,
  1259. IN ULONG AtmSubaddressLength,
  1260. IN BOOLEAN CreateNew
  1261. )
  1262. /*++
  1263. Routine Description:
  1264. Check if the specified ATM endstation is a member of the list of
  1265. ATM addresses associated with a Multicast entry. If so, return
  1266. a pointer to the entry for this endstation. If not, create a new
  1267. entry conditionally and return a pointer to this.
  1268. NOTE: the ATM Entry is assumed to be locked by the caller.
  1269. Arguments:
  1270. pAtmEntry - ATM Entry to which the member will be added
  1271. ppMcAtmList - Points to start of list to search in.
  1272. pAtmNumber - Pointer to ATM address for this endstation
  1273. AtmNumberLength - Length of above
  1274. AtmNumberType - Type of above
  1275. pAtmSubaddress - Pointer to ATM Subaddress for this endstation
  1276. AtmSubaddressLength - Length of above
  1277. CreateNew - Should we create a new entry if not found?
  1278. Return Value:
  1279. Pointer to the (possibly new) ATM MC Entry for the specified leaf.
  1280. --*/
  1281. {
  1282. PATMARP_IPMC_ATM_ENTRY pMcAtmEntry;
  1283. BOOLEAN Found;
  1284. Found = FALSE;
  1285. for (pMcAtmEntry = *ppMcAtmList;
  1286. pMcAtmEntry != NULL_PATMARP_IPMC_ATM_ENTRY;
  1287. pMcAtmEntry = pMcAtmEntry->pNextMcAtmEntry)
  1288. {
  1289. //
  1290. // Compare ATM Numbers
  1291. //
  1292. if ((pMcAtmEntry->ATMAddress.NumberOfDigits == AtmNumberLength) &&
  1293. (pMcAtmEntry->ATMAddress.AddressType == AtmNumberType) &&
  1294. (AA_MEM_CMP(pMcAtmEntry->ATMAddress.Address, pAtmNumber, AtmNumberLength) == 0))
  1295. {
  1296. //
  1297. // Compare subaddresses
  1298. //
  1299. if ((pMcAtmEntry->ATMSubaddress.NumberOfDigits == AtmSubaddressLength) &&
  1300. (AA_MEM_CMP(pMcAtmEntry->ATMSubaddress.Address,
  1301. pAtmSubaddress,
  1302. AtmSubaddressLength) == 0))
  1303. {
  1304. Found = TRUE;
  1305. break;
  1306. }
  1307. }
  1308. }
  1309. if ((!Found) && CreateNew)
  1310. {
  1311. AA_ALLOC_MEM(pMcAtmEntry, ATMARP_IPMC_ATM_ENTRY, sizeof(ATMARP_IPMC_ATM_ENTRY));
  1312. if (pMcAtmEntry != NULL_PATMARP_IPMC_ATM_ENTRY)
  1313. {
  1314. AA_SET_MEM(pMcAtmEntry, 0, sizeof(ATMARP_IPMC_ATM_ENTRY));
  1315. //
  1316. // Fill in all that we know.
  1317. //
  1318. #if DBG
  1319. pMcAtmEntry->ame_sig = ame_signature;
  1320. #endif
  1321. pMcAtmEntry->pAtmEntry = pAtmEntry;
  1322. //
  1323. // The ATM Address
  1324. //
  1325. pMcAtmEntry->ATMAddress.NumberOfDigits = AtmNumberLength;
  1326. pMcAtmEntry->ATMAddress.AddressType = AtmNumberType;
  1327. AA_COPY_MEM(pMcAtmEntry->ATMAddress.Address, pAtmNumber, AtmNumberLength);
  1328. //
  1329. // ATM Subaddress
  1330. //
  1331. pMcAtmEntry->ATMSubaddress.NumberOfDigits = AtmSubaddressLength;
  1332. pMcAtmEntry->ATMSubaddress.AddressType = ATM_NSAP;
  1333. AA_COPY_MEM(pMcAtmEntry->ATMSubaddress.Address, pAtmSubaddress, AtmSubaddressLength);
  1334. //
  1335. // Link it to the list
  1336. //
  1337. pMcAtmEntry->pNextMcAtmEntry = *ppMcAtmList;
  1338. *ppMcAtmList = pMcAtmEntry;
  1339. pAtmEntry->pMcAtmInfo->NumOfEntries++;
  1340. //
  1341. // Bump up ref count on this ATM Entry
  1342. //
  1343. AA_REF_AE(pAtmEntry, AE_REFTYPE_MCAE); // New McAtmEntry added
  1344. }
  1345. }
  1346. AAMCDEBUGP(AAD_VERY_LOUD,
  1347. ("McLookupAtmMember: pAtmEntry 0x%x, %s pMcAtmEntry 0x%x\n",
  1348. pAtmEntry, (!Found)? "New": "Old", pMcAtmEntry));
  1349. #if DBG
  1350. if (pMcAtmEntry && (pAtmEntry->pIpEntryList))
  1351. {
  1352. AAMCDEBUGPMAP(AAD_INFO, ((!Found)? "Added " : "Found "),
  1353. &pAtmEntry->pIpEntryList->IPAddress,
  1354. &pMcAtmEntry->ATMAddress);
  1355. }
  1356. #endif // DBG
  1357. return (pMcAtmEntry);
  1358. }
  1359. VOID
  1360. AtmArpMcUnlinkAtmMember(
  1361. IN PATMARP_ATM_ENTRY pAtmEntry,
  1362. IN PATMARP_IPMC_ATM_ENTRY pMcAtmEntry
  1363. )
  1364. /*++
  1365. Routine Description:
  1366. Delete an ATM destination from the list of members of a multicast group.
  1367. We stop the timer (if running) associated with this Multicast entry and delink the entry
  1368. from the list of destinations, and free the structure.
  1369. NOTE: the caller is assumed to hold a lock to the ATM Entry.
  1370. Arguments:
  1371. pAtmEntry - ATM Entry from which to delete the member
  1372. pMcAtmEntry - The entry to be deleted
  1373. Return Value:
  1374. None
  1375. --*/
  1376. {
  1377. PATMARP_IPMC_ATM_ENTRY * ppMcAtmEntry;
  1378. ULONG rc;
  1379. AA_ASSERT(pAtmEntry->pMcAtmInfo != NULL_PATMARP_IPMC_ATM_INFO);
  1380. AA_ASSERT(AA_IS_FLAG_SET(pMcAtmEntry->Flags,
  1381. AA_IPMC_AE_CONN_STATE_MASK,
  1382. AA_IPMC_AE_CONN_DISCONNECTED));
  1383. AAMCDEBUGP(AAD_LOUD, ("UnlinkAtmMember: pAtmEntry 0x%x, pMcAtmEntry 0x%x\n",
  1384. pAtmEntry, pMcAtmEntry));
  1385. //
  1386. // Stop any timer running here.
  1387. //
  1388. if (AA_IS_TIMER_ACTIVE(&(pMcAtmEntry->Timer)))
  1389. {
  1390. (VOID)AtmArpStopTimer(&(pMcAtmEntry->Timer), pAtmEntry->pInterface);
  1391. }
  1392. for (ppMcAtmEntry = &(pAtmEntry->pMcAtmInfo->pMcAtmEntryList);
  1393. *ppMcAtmEntry != NULL_PATMARP_IPMC_ATM_ENTRY;
  1394. ppMcAtmEntry = &((*ppMcAtmEntry)->pNextMcAtmEntry))
  1395. {
  1396. if (*ppMcAtmEntry == pMcAtmEntry)
  1397. {
  1398. //
  1399. // Delink now.
  1400. //
  1401. *ppMcAtmEntry = pMcAtmEntry->pNextMcAtmEntry;
  1402. break;
  1403. }
  1404. AA_ASSERT(*ppMcAtmEntry != NULL_PATMARP_IPMC_ATM_ENTRY);
  1405. }
  1406. AA_ASSERT(!AA_IS_TIMER_ACTIVE(&pMcAtmEntry->Timer));
  1407. AA_CHECK_TIMER_IN_ACTIVE_LIST(&pMcAtmEntry->Timer, pAtmEntry->pInterface, pMcAtmEntry, "MC ATM Entry");
  1408. AA_FREE_MEM(pMcAtmEntry);
  1409. pAtmEntry->pMcAtmInfo->NumOfEntries--;
  1410. rc = AA_DEREF_AE(pAtmEntry, AE_REFTYPE_MCAE); // Unlink MC ATM Entry
  1411. AA_ASSERT(rc!=0);// We always expect caller will retain a reference to pAtmEntry.
  1412. }
  1413. VOID
  1414. AtmArpMcUpdateConnection(
  1415. IN PATMARP_ATM_ENTRY pAtmEntry LOCKIN NOLOCKOUT
  1416. )
  1417. /*++
  1418. Routine Description:
  1419. Update our outgoing Point to Multipoint connection for the multicast
  1420. group represented by the given IP Entry.
  1421. If no call exists, and there is atleast one valid entry in the list
  1422. of remote ATM addresses for this group, then we place an outgoing call.
  1423. If an outgoing call exists, then we go through the list of remote
  1424. ATM addresses. Each address that isn't participating in the call,
  1425. and is Valid gets added as a leaf to the call. Each address that has
  1426. been invalidated gets deleted.
  1427. NOTE: The caller is assumed to have acquired the ATM_ENTRY lock;
  1428. it will be released here.
  1429. Arguments:
  1430. pAtmEntry - ATM Entry representing multicast group on which
  1431. to update the PMP connection.
  1432. Return Value:
  1433. None
  1434. --*/
  1435. {
  1436. PATMARP_IPMC_ATM_INFO pMcAtmInfo;
  1437. PATMARP_IPMC_ATM_ENTRY pMcAtmEntry;
  1438. PATMARP_IPMC_ATM_ENTRY pNextMcAtmEntry;
  1439. ULONG rc;
  1440. PATMARP_IP_ENTRY pIpEntry;
  1441. PATMARP_INTERFACE pInterface;
  1442. PATMARP_FLOW_INFO pFlowInfo;
  1443. PATMARP_FLOW_SPEC pFlowSpec;
  1444. PATMARP_FILTER_SPEC pFilterSpec;
  1445. PNDIS_PACKET pNdisPacket;
  1446. BOOLEAN Closing = FALSE;
  1447. AAMCDEBUGP(AAD_LOUD,
  1448. ("McUpdateConn: pAtmEntry 0x%x/0x%x, pMcAtmInfo 0x%x/0x%x\n",
  1449. pAtmEntry, pAtmEntry->Flags,
  1450. pAtmEntry->pMcAtmInfo, pAtmEntry->pMcAtmInfo->Flags));
  1451. pMcAtmInfo = pAtmEntry->pMcAtmInfo;
  1452. AA_ASSERT(pMcAtmInfo != NULL_PATMARP_IPMC_ATM_INFO);
  1453. AA_ASSERT(pMcAtmInfo->pMcAtmEntryList != NULL_PATMARP_IPMC_ATM_ENTRY);
  1454. AA_ASSERT(AA_IS_FLAG_SET(pAtmEntry->Flags,
  1455. AA_ATM_ENTRY_TYPE_MASK,
  1456. AA_ATM_ENTRY_TYPE_NUCAST));
  1457. //
  1458. // Add a temp reference to the ATM Entry so that it can't go
  1459. // away for the duration of this routine.
  1460. //
  1461. AA_REF_AE(pAtmEntry, AE_REFTYPE_TMP); // temp ref
  1462. do
  1463. {
  1464. if (pAtmEntry->pVcList && AA_IS_FLAG_SET(pAtmEntry->pVcList->Flags,
  1465. AA_VC_CLOSE_STATE_MASK,
  1466. AA_VC_CLOSE_STATE_CLOSING))
  1467. {
  1468. //
  1469. // Bail out.
  1470. //
  1471. pMcAtmInfo->Flags &= ~AA_IPMC_AI_WANT_UPDATE;
  1472. Closing = TRUE;
  1473. break;
  1474. }
  1475. //
  1476. // Mark this entry as needing a connection update.
  1477. //
  1478. pMcAtmInfo->Flags |= AA_IPMC_AI_WANT_UPDATE;
  1479. //
  1480. // If a connection update is in progress, don't do
  1481. // anything more. The thread that's doing the update
  1482. // will see that another update is needed, and do it.
  1483. //
  1484. if (pMcAtmInfo->Flags & AA_IPMC_AI_BEING_UPDATED)
  1485. {
  1486. break;
  1487. }
  1488. //
  1489. // Mark this entry so that we don't have more than one
  1490. // thread proceeding beyond here.
  1491. //
  1492. pMcAtmInfo->Flags |= AA_IPMC_AI_BEING_UPDATED;
  1493. while (pMcAtmInfo->Flags & AA_IPMC_AI_WANT_UPDATE)
  1494. {
  1495. pMcAtmInfo->Flags &= ~AA_IPMC_AI_WANT_UPDATE;
  1496. if (AA_IS_FLAG_SET(
  1497. pMcAtmInfo->Flags,
  1498. AA_IPMC_AI_CONN_STATE_MASK,
  1499. AA_IPMC_AI_CONN_NONE))
  1500. {
  1501. PATMARP_IPMC_ATM_ENTRY * ppMcAtmEntry;
  1502. //
  1503. // No connection exists; create one.
  1504. //
  1505. //
  1506. // First, find an MC ATM Entry that is valid and disconnected.
  1507. // We are mainly concerned with avoiding entries that are running
  1508. // a party-retry delay timer.
  1509. //
  1510. for (ppMcAtmEntry = &pAtmEntry->pMcAtmInfo->pMcAtmEntryList;
  1511. *ppMcAtmEntry != NULL_PATMARP_IPMC_ATM_ENTRY;
  1512. ppMcAtmEntry = &((*ppMcAtmEntry)->pNextMcAtmEntry))
  1513. {
  1514. pMcAtmEntry = *ppMcAtmEntry;
  1515. if (AA_IS_FLAG_SET(
  1516. pMcAtmEntry->Flags,
  1517. AA_IPMC_AE_GEN_STATE_MASK,
  1518. AA_IPMC_AE_VALID) &&
  1519. AA_IS_FLAG_SET(
  1520. pMcAtmEntry->Flags,
  1521. AA_IPMC_AE_CONN_STATE_MASK,
  1522. AA_IPMC_AE_CONN_DISCONNECTED))
  1523. {
  1524. break;
  1525. }
  1526. }
  1527. //
  1528. // Bail out if we don't find one.
  1529. //
  1530. if (*ppMcAtmEntry == NULL_PATMARP_IPMC_ATM_ENTRY)
  1531. {
  1532. AAMCDEBUGP(AAD_INFO,
  1533. ("McUpdateConn: pAtmEntry %x, pMcAtmInfo %x, no valid MC ATM Entry to make call on!\n",
  1534. pAtmEntry, pMcAtmInfo));
  1535. break;
  1536. }
  1537. //
  1538. // We found one. Remove it from its current position and
  1539. // move it to the top of the list. This is for the benefit
  1540. // of AtmArpMakeCall, which picks up the first MC ATM Entry
  1541. // as the party context for the call.
  1542. //
  1543. //
  1544. // Unlink from current position.
  1545. //
  1546. *ppMcAtmEntry = pMcAtmEntry->pNextMcAtmEntry;
  1547. //
  1548. // Insert at top of list.
  1549. //
  1550. pMcAtmEntry->pNextMcAtmEntry = pAtmEntry->pMcAtmInfo->pMcAtmEntryList;
  1551. pAtmEntry->pMcAtmInfo->pMcAtmEntryList = pMcAtmEntry;
  1552. AAMCDEBUGP(AAD_VERY_LOUD,
  1553. ("McUpdateConn: No conn exists: pIpEnt 0x%x, pMcAtmInfo 0x%x\n",
  1554. pAtmEntry->pIpEntryList, pMcAtmInfo));
  1555. AA_ASSERT(pAtmEntry->pVcList == NULL_PATMARP_VC);
  1556. AA_SET_FLAG(
  1557. pMcAtmInfo->Flags,
  1558. AA_IPMC_AI_CONN_STATE_MASK,
  1559. AA_IPMC_AI_CONN_WACK_MAKE_CALL);
  1560. AA_SET_FLAG(
  1561. pMcAtmEntry->Flags,
  1562. AA_IPMC_AE_CONN_STATE_MASK,
  1563. AA_IPMC_AE_CONN_WACK_ADD_PARTY);
  1564. //
  1565. // Get the flow spec for this call from one of the packets
  1566. // queued on the IP entry.
  1567. //
  1568. pInterface = pAtmEntry->pInterface;
  1569. pIpEntry = pAtmEntry->pIpEntryList;
  1570. if (pIpEntry != NULL_PATMARP_IP_ENTRY)
  1571. {
  1572. pNdisPacket = pIpEntry->PacketList;
  1573. if (pNdisPacket != NULL)
  1574. {
  1575. AA_GET_PACKET_SPECS(pInterface,
  1576. pNdisPacket,
  1577. &pFlowInfo,
  1578. &pFlowSpec,
  1579. &pFilterSpec);
  1580. }
  1581. else
  1582. {
  1583. pFlowSpec = &(pInterface->DefaultFlowSpec);
  1584. }
  1585. }
  1586. else
  1587. {
  1588. pFlowSpec = &(pInterface->DefaultFlowSpec);
  1589. }
  1590. AtmArpMakeCall(
  1591. pInterface,
  1592. pAtmEntry,
  1593. pFlowSpec,
  1594. (PNDIS_PACKET)NULL
  1595. );
  1596. //
  1597. // the ATM Entry lock is released within the above.
  1598. //
  1599. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  1600. break;
  1601. }
  1602. else if (AA_IS_FLAG_SET(
  1603. pMcAtmInfo->Flags,
  1604. AA_IPMC_AI_CONN_STATE_MASK,
  1605. AA_IPMC_AI_CONN_WACK_MAKE_CALL))
  1606. {
  1607. //
  1608. // Don't do anything till the first connection
  1609. // is established.
  1610. //
  1611. break;
  1612. }
  1613. else if (AA_IS_FLAG_SET(
  1614. pMcAtmInfo->Flags,
  1615. AA_IPMC_AI_CONN_STATE_MASK,
  1616. AA_IPMC_AI_CONN_ACTIVE))
  1617. {
  1618. //
  1619. // The PMP connection exists. Go through the list
  1620. // of ATM MC Entries, and:
  1621. // 1 - Add valid ones which aren't leaves yet
  1622. // 2 - Delete invalid ones
  1623. //
  1624. // #1: add validated leaves
  1625. for (pMcAtmEntry = pAtmEntry->pMcAtmInfo->pMcAtmEntryList;
  1626. pMcAtmEntry != NULL_PATMARP_IPMC_ATM_ENTRY;
  1627. pMcAtmEntry = pNextMcAtmEntry)
  1628. {
  1629. pNextMcAtmEntry = pMcAtmEntry->pNextMcAtmEntry;
  1630. if (AA_IS_FLAG_SET(
  1631. pMcAtmEntry->Flags,
  1632. AA_IPMC_AE_GEN_STATE_MASK,
  1633. AA_IPMC_AE_VALID) &&
  1634. AA_IS_FLAG_SET(
  1635. pMcAtmEntry->Flags,
  1636. AA_IPMC_AE_CONN_STATE_MASK,
  1637. AA_IPMC_AE_CONN_DISCONNECTED))
  1638. {
  1639. AAMCDEBUGP(AAD_VERY_LOUD, ("McUpdateConn: pAtmEnt 0x%x, Adding Pty pMcAtmEnt 0x%x\n",
  1640. pAtmEntry, pMcAtmEntry));
  1641. AtmArpAddParty(
  1642. pAtmEntry,
  1643. pMcAtmEntry
  1644. );
  1645. //
  1646. // ATM Entry lock is released within the above.
  1647. //
  1648. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  1649. pMcAtmInfo->Flags |= AA_IPMC_AI_WANT_UPDATE;
  1650. break;
  1651. }
  1652. } // for
  1653. // #2: delete invalid leaves
  1654. for (pMcAtmEntry = pAtmEntry->pMcAtmInfo->pMcAtmEntryList;
  1655. pMcAtmEntry != NULL_PATMARP_IPMC_ATM_ENTRY;
  1656. pMcAtmEntry = pNextMcAtmEntry)
  1657. {
  1658. pNextMcAtmEntry = pMcAtmEntry->pNextMcAtmEntry;
  1659. if (AA_IS_FLAG_SET(
  1660. pMcAtmEntry->Flags,
  1661. AA_IPMC_AE_GEN_STATE_MASK,
  1662. AA_IPMC_AE_INVALID))
  1663. {
  1664. AAMCDEBUGP(AAD_VERY_LOUD, ("McUpdateConn: pAtmEnt 0x%x, Terminating 0x%x\n",
  1665. pAtmEntry, pMcAtmEntry));
  1666. AAMCDEBUGPMAP(AAD_INFO,
  1667. "Deleting ", &pAtmEntry->pIpEntryList->IPAddress,
  1668. &pMcAtmEntry->ATMAddress);
  1669. AtmArpMcTerminateMember(
  1670. pAtmEntry,
  1671. pMcAtmEntry
  1672. );
  1673. //
  1674. // ATM Entry lock is released within the above.
  1675. //
  1676. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  1677. pMcAtmInfo->Flags |= AA_IPMC_AI_WANT_UPDATE;
  1678. break;
  1679. }
  1680. } // for
  1681. } // if Connection is active
  1682. //
  1683. // else we may be waiting for a while after seeing
  1684. // a transient connection failure on the first MakeCall.
  1685. //
  1686. } // while more connection updates needed
  1687. AA_SET_FLAG(pMcAtmInfo->Flags,
  1688. AA_IPMC_AI_CONN_UPDATE_MASK,
  1689. AA_IPMC_AI_NO_UPDATE);
  1690. break;
  1691. }
  1692. while (FALSE);
  1693. //
  1694. // Remove the temp reference on the ATM Entry:
  1695. //
  1696. rc = AA_DEREF_AE(pAtmEntry, AE_REFTYPE_TMP); // temp ref
  1697. if (rc != 0)
  1698. {
  1699. BOOLEAN ClearToSend;
  1700. PNDIS_PACKET pPacketList;
  1701. ClearToSend = ((pMcAtmInfo->TransientLeaves == 0) &&
  1702. !Closing &&
  1703. (AA_IS_FLAG_SET(pMcAtmInfo->Flags,
  1704. AA_IPMC_AI_CONN_STATE_MASK,
  1705. AA_IPMC_AI_CONN_ACTIVE)));
  1706. pIpEntry = pAtmEntry->pIpEntryList;
  1707. pInterface = pAtmEntry->pInterface;
  1708. AA_RELEASE_AE_LOCK(pAtmEntry);
  1709. if (ClearToSend && pIpEntry)
  1710. {
  1711. AA_ACQUIRE_IE_LOCK(pIpEntry);
  1712. AA_ASSERT(AA_IE_IS_ALIVE(pIpEntry));
  1713. pPacketList = pIpEntry->PacketList;
  1714. pIpEntry->PacketList = (PNDIS_PACKET)NULL;
  1715. AA_RELEASE_IE_LOCK(pIpEntry);
  1716. if (pPacketList != (PNDIS_PACKET)NULL)
  1717. {
  1718. AAMCDEBUGP(AAD_INFO, ("UpdateConn: pAtmEntry 0x%x, sending pktlist 0x%x\n",
  1719. pAtmEntry, pPacketList));
  1720. AtmArpSendPacketListOnAtmEntry(
  1721. pInterface,
  1722. pAtmEntry,
  1723. pPacketList,
  1724. TRUE // IsBroadcast
  1725. );
  1726. }
  1727. }
  1728. }
  1729. //
  1730. // else the ATM Entry is gone.
  1731. //
  1732. }
  1733. #endif // IPMCAST