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

4325 lines
94 KiB

  1. /*++
  2. Copyright (c) 1992-1996 Microsoft Corporation
  3. Module Name:
  4. mars.c
  5. Abstract:
  6. This file contains the code to implement the functionality of
  7. Multicast Address Resolution Server (MARS), and a minimal
  8. MultiCast Server (MCS).
  9. Reference: RFC 2022
  10. Author:
  11. Jameel Hyder (jameelh@microsoft.com) January 1997
  12. Environment:
  13. Kernel mode
  14. Revision History:
  15. --*/
  16. #include <precomp.h>
  17. #define _FILENUM_ FILENUM_MARS
  18. #define MARS_CO_SEND_PACKETS(_Vc, _PktArray, _PktCount) \
  19. { \
  20. ULONG _Count; \
  21. NDIS_HANDLE _NdisVcHandle = (_Vc)->NdisVcHandle; \
  22. \
  23. if (_NdisVcHandle != NULL) \
  24. { \
  25. NdisCoSendPackets(_NdisVcHandle, _PktArray, _PktCount); \
  26. } \
  27. else \
  28. { \
  29. for (_Count = 0; _Count < _PktCount; _Count++) \
  30. { \
  31. ArpSCoSendComplete(NDIS_STATUS_FAILURE, _Vc, _PktArray[_Count]); \
  32. } \
  33. } \
  34. }
  35. VOID
  36. MarsReqThread(
  37. IN PVOID Context
  38. )
  39. /*++
  40. Routine Description:
  41. Handle all MARS requests here.
  42. Arguments:
  43. None
  44. Return Value:
  45. None
  46. --*/
  47. {
  48. PMARS_HEADER Header;
  49. PLIST_ENTRY List;
  50. PNDIS_PACKET Pkt;
  51. PPROTOCOL_RESD Resd;
  52. PARP_VC Vc;
  53. UINT PktLen;
  54. PINTF pIntF;
  55. ARPS_PAGED_CODE( );
  56. MARSDBGPRINT(DBG_LEVEL_INFO,
  57. ("MarsReqThread: Came to life\n"));
  58. do
  59. {
  60. List = KeRemoveQueue(&MarsReqQueue, KernelMode, NULL);
  61. if (List == &ArpSEntryOfDeath)
  62. {
  63. //
  64. // Asked to terminate, do so.
  65. //
  66. break;
  67. }
  68. Resd = CONTAINING_RECORD(List, PROTOCOL_RESD, ReqList);
  69. if (Resd->Flags & RESD_FLAG_KILL_CCVC)
  70. {
  71. pIntF = (PINTF)Resd->Vc;
  72. MARSDBGPRINT(DBG_LEVEL_NOTICE,
  73. ("MARS Thread: will kill CCVC on pIntF %x\n", pIntF));
  74. FREE_MEM(Resd);
  75. MarsAbortAllMembers(pIntF);
  76. continue;
  77. }
  78. Pkt = CONTAINING_RECORD(Resd, NDIS_PACKET, ProtocolReserved);
  79. Vc = Resd->Vc;
  80. pIntF = Vc->IntF;
  81. pIntF->MarsStats.TotalRecvPkts++;
  82. if (pIntF->Flags & INTF_STOPPING)
  83. {
  84. MARSDBGPRINT(DBG_LEVEL_WARN,
  85. ("MARS Thread: pIntF %x is stopping, dropping pkt %x\n", pIntF, Pkt));
  86. pIntF->MarsStats.DiscardedRecvPkts++;
  87. ArpSDereferenceVc(Vc, FALSE, TRUE);
  88. Resd->Vc = NULL;
  89. ExInterlockedPushEntrySList(&ArpSPktList,
  90. &Resd->FreeList,
  91. &ArpSPktListLock);
  92. continue;
  93. }
  94. NdisQueryBuffer(Pkt->Private.Head, &Header, &PktLen);
  95. MARSDBGPRINT(DBG_LEVEL_LOUD,
  96. ("MARS Thread: Resd %x, Pkt %x, PktLen %x, Header %x, Op %x, Vc %x, IntF %x\n",
  97. Resd, Pkt, PktLen, Header, Header->Opcode, Vc, pIntF));
  98. ARPS_ASSERT (PktLen <= PKT_SPACE);
  99. switch(Header->Opcode)
  100. {
  101. case OP_MARS_REQUEST:
  102. MarsHandleRequest(pIntF, Vc, Header, Pkt);
  103. break;
  104. case OP_MARS_JOIN:
  105. MarsHandleJoin(pIntF, Vc, Header, Pkt);
  106. break;
  107. case OP_MARS_LEAVE:
  108. MarsHandleLeave(pIntF, Vc, Header, Pkt);
  109. break;
  110. default:
  111. MARSDBGPRINT(DBG_LEVEL_FATAL,
  112. ("MarsReqThread: Opcode %x unknown\n", Header->Opcode));
  113. pIntF->MarsStats.DiscardedRecvPkts++;
  114. ArpSDereferenceVc(Vc, FALSE, TRUE);
  115. Resd->Vc = NULL;
  116. ExInterlockedPushEntrySList(&ArpSPktList,
  117. &Resd->FreeList,
  118. &ArpSPktListLock);
  119. break;
  120. }
  121. } while (TRUE);
  122. KeSetEvent(&ArpSReqThreadEvent, 0, FALSE);
  123. MARSDBGPRINT(DBG_LEVEL_WARN,
  124. ("MarsReqThread: Terminating\n"));
  125. }
  126. VOID
  127. MarsHandleRequest(
  128. IN PINTF pIntF,
  129. IN PARP_VC Vc,
  130. IN PMARS_HEADER Header,
  131. IN PNDIS_PACKET Packet
  132. )
  133. /*++
  134. Routine Description:
  135. Handle MARS_REQUEST. If the sender is a valid registered Cluster member,
  136. lookup the desired target group address in the MARS cache. If found, send
  137. a sequence of one or more MARS MULTIs. Include the addresses of members
  138. who are monitoring the entire class-D address space.
  139. Arguments:
  140. pIntF - The interface on which the MARS_REQUEST arrived
  141. Vc - The VC on which the packet arrived
  142. Header - Points to the request packet
  143. Packet - Packet where the incoming information is copied
  144. Return Value:
  145. None
  146. --*/
  147. {
  148. HW_ADDR SrcAddr;
  149. HW_ADDR ** pPromisHWAddrArray;
  150. HW_ADDR ** ppPromisHWAddr;
  151. ATM_ADDRESS SrcSubAddr;
  152. IPADDR GrpAddr;
  153. PCLUSTER_MEMBER pMember;
  154. PGROUP_MEMBER pGroup;
  155. PMARS_ENTRY pMarsEntry;
  156. NDIS_STATUS Status;
  157. PMARS_REQUEST RHdr;
  158. PUCHAR p;
  159. PPROTOCOL_RESD Resd, MultiResd;
  160. ULONG SeqY;
  161. ULONG Length;
  162. ULONG CopyLength;
  163. ULONG PacketLength;
  164. PNDIS_PACKET MultiPacket;
  165. PNDIS_PACKET HeadMultiList;
  166. PNDIS_PACKET * pTailMultiList;
  167. ULONG AddrCountThisPacket;
  168. ULONG AddrPerPacket;
  169. INT AddrRem;
  170. INT NumUniquePromisEntries;
  171. PMARS_MULTI MHdr;
  172. KIRQL OldIrql;
  173. BOOLEAN LockAcquired;
  174. BOOLEAN SendNak;
  175. BOOLEAN Discarded=TRUE;
  176. RHdr = (PMARS_REQUEST)Header;
  177. Resd = RESD_FROM_PKT(Packet);
  178. LockAcquired = FALSE;
  179. SendNak = FALSE;
  180. do
  181. {
  182. pIntF->MarsStats.TotalRequests++;
  183. //
  184. // Check if we have enough to even parse this.
  185. //
  186. if (Resd->PktLen < sizeof(MARS_REQUEST))
  187. {
  188. MARSDBGPRINT(DBG_LEVEL_ERROR,
  189. ("MarsHandleRequest: Packet Length too small: %x\n", Resd->PktLen));
  190. break;
  191. }
  192. Length = sizeof(MARS_REQUEST) + RHdr->SrcProtoAddrLen +
  193. TL_LEN(RHdr->SrcAddressTL) +
  194. TL_LEN(RHdr->SrcSubAddrTL) +
  195. RHdr->TgtGroupAddrLen;
  196. //
  197. // Validate length of packet - it should have what it purports to have
  198. //
  199. if (Length > Resd->PktLen)
  200. {
  201. MARSDBGPRINT(DBG_LEVEL_ERROR,
  202. ("MarsHandleRequest: Invalid packet length %x < %x\n",
  203. Resd->PktLen, Length));
  204. break;
  205. }
  206. //
  207. // Expect NULL target ATM address/subaddress
  208. //
  209. if ((RHdr->TgtAddressTL != 0) ||
  210. (RHdr->TgtSubAddrTL != 0))
  211. {
  212. MARSDBGPRINT(DBG_LEVEL_ERROR,
  213. ("MarsHandleRequest: Non-null target HW address %x or %x\n",
  214. RHdr->TgtAddressTL,
  215. RHdr->TgtSubAddrTL));
  216. break;
  217. }
  218. //
  219. // Go to the variable length part, consisting of:
  220. // Source ATM Number (mandatory)
  221. // Source ATM Subaddress (optional)
  222. // Source protocol address (optional)
  223. // Target group address (mandatory)
  224. //
  225. p = (PUCHAR)(RHdr + 1);
  226. SrcAddr.Address.NumberOfDigits = TL_LEN(Header->SrcAddressTL);
  227. if (SrcAddr.Address.NumberOfDigits > 0)
  228. {
  229. SrcAddr.Address.AddressType = TL_TYPE(Header->SrcAddressTL);
  230. COPY_MEM(SrcAddr.Address.Address, p, SrcAddr.Address.NumberOfDigits);
  231. p += SrcAddr.Address.NumberOfDigits;
  232. }
  233. SrcAddr.SubAddress = NULL;
  234. if (TL_LEN(Header->SrcSubAddrTL) > 0)
  235. {
  236. SrcAddr.SubAddress = &SrcSubAddr;
  237. SrcSubAddr.NumberOfDigits = TL_LEN(Header->SrcSubAddrTL);
  238. SrcSubAddr.AddressType = TL_TYPE(Header->SrcSubAddrTL);
  239. COPY_MEM(&SrcSubAddr.Address, p, SrcSubAddr.NumberOfDigits);
  240. p += SrcSubAddr.NumberOfDigits;
  241. }
  242. //
  243. // NOTE:
  244. //
  245. // We only support full length Source ATM Number,
  246. // and zero-length Source ATM Subaddress.
  247. //
  248. if ((SrcAddr.Address.NumberOfDigits != ATM_ADDRESS_LENGTH) ||
  249. (SrcAddr.SubAddress != NULL))
  250. {
  251. MARSDBGPRINT(DBG_LEVEL_ERROR,
  252. ("MarsHandleReq: unsupported ATM Number len %x or non-zero subaddr\n",
  253. SrcAddr.Address.NumberOfDigits));
  254. break;
  255. }
  256. if ((RHdr->SrcProtoAddrLen != 0) &&
  257. (RHdr->SrcProtoAddrLen != IP_ADDR_LEN))
  258. {
  259. MARSDBGPRINT(DBG_LEVEL_ERROR,
  260. ("MarsHandleReq: bad src proto addr len %x\n", RHdr->SrcProtoAddrLen));
  261. break;
  262. }
  263. p += RHdr->SrcProtoAddrLen;
  264. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  265. LockAcquired = TRUE;
  266. //
  267. // We honor this REQUEST only if it has come from a legitimate
  268. // Cluster Member.
  269. //
  270. pMember = MarsLookupClusterMember(pIntF, &SrcAddr);
  271. if ((pMember == NULL_PCLUSTER_MEMBER) ||
  272. (MARS_GET_CM_CONN_STATE(pMember) != CM_CONN_ACTIVE))
  273. {
  274. MARSDBGPRINT(DBG_LEVEL_ERROR,
  275. ("MarsHandleReq: from unconnected cluster member: "));
  276. MARSDUMPATMADDR(DBG_LEVEL_ERROR, &SrcAddr.Address, "");
  277. break;
  278. }
  279. Discarded = FALSE; // For stats.
  280. //
  281. // Target Group address being resolved.
  282. //
  283. MARSDBGPRINT(DBG_LEVEL_LOUD,
  284. ("MarsHandleReq: Request from pMember %x for Addr ", pMember));
  285. MARSDUMPIPADDR(DBG_LEVEL_LOUD, *(UNALIGNED IPADDR *)p, "\n");
  286. GETULONG2ULONG(&GrpAddr, p);
  287. //
  288. // Fill in our Seq number just in case we decide to send a NAK
  289. // using this packet
  290. //
  291. PUTULONG2ULONG(&(RHdr->SequenceNumber), pIntF->CSN);
  292. //
  293. // Check if we are the MCS serving the desired group address.
  294. //
  295. if (MarsIsAddressMcsServed(pIntF, GrpAddr))
  296. {
  297. PATM_ADDRESS pAtmAddr = &(pIntF->ConfiguredAddress);
  298. MARSDBGPRINT(DBG_LEVEL_INFO,
  299. ("MarsHandleReq: sending MULTI with MCS for "));
  300. MARSDUMPIPADDR(DBG_LEVEL_INFO, *(UNALIGNED IPADDR *)p, "\n");
  301. //
  302. // Prepare a MARS MULTI with our address and return it.
  303. //
  304. PacketLength = Length + pAtmAddr->NumberOfDigits +
  305. sizeof(MARS_TLV_MULTI_IS_MCS) +
  306. sizeof(MARS_TLV_NULL);
  307. MultiPacket = MarsAllocControlPacket(pIntF, PacketLength, (PUCHAR *)&MHdr);
  308. if (MultiPacket != (PNDIS_PACKET)NULL)
  309. {
  310. ULONG ExtOff;
  311. COPY_MEM(MHdr, RHdr, Length);
  312. MHdr->Opcode = OP_MARS_MULTI;
  313. MHdr->TgtAddressTL = TL(pAtmAddr->AddressType, pAtmAddr->NumberOfDigits);
  314. PUTULONG2ULONG(&(MHdr->SequenceNumber), pIntF->CSN);
  315. PUTSHORT2SHORT(&(MHdr->NumTgtGroupAddr), 1);
  316. SeqY = LAST_MULTI_FLAG | 1;
  317. PUTSHORT2SHORT(&(MHdr->FlagSeq), SeqY);
  318. p = (PUCHAR)MHdr + Length;
  319. COPY_MEM(p, pAtmAddr->Address, pAtmAddr->NumberOfDigits);
  320. p += pAtmAddr->NumberOfDigits;
  321. //
  322. // Calculate and fill in the extensions offset. This is the
  323. // offset, calculated from the HwType (afn) field, where
  324. // we put in the "MULTI is MCS" TLV.
  325. //
  326. ExtOff = (ULONG) (p - (PUCHAR)MHdr - sizeof(LLC_SNAP_HDR));
  327. PUTSHORT2SHORT(&MHdr->ExtensionOffset, ExtOff);
  328. //
  329. // Fill in the MULTI is MCS TLV
  330. //
  331. COPY_MEM(p, &MultiIsMcsTLV, sizeof(MultiIsMcsTLV));
  332. p += sizeof(MultiIsMcsTLV);
  333. //
  334. // Fill in a NULL (terminating) TLV
  335. //
  336. COPY_MEM(p, &NullTLV, sizeof(NullTLV));
  337. pIntF->MarsStats.MCSAcks++;
  338. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  339. LockAcquired = FALSE;
  340. MARS_CO_SEND_PACKETS(Vc, &MultiPacket, 1);
  341. }
  342. break;
  343. }
  344. pMarsEntry = MarsLookupMarsEntry(pIntF, GrpAddr, FALSE);
  345. if (pMarsEntry!=NULL && pMarsEntry->NumMembers==0)
  346. {
  347. pMarsEntry=NULL; // just to simplify tests later on.
  348. }
  349. //
  350. // Pick up the h/w address of all members that are members
  351. // of the entire class-D address space (promiscuous members),
  352. // but which are not monitoring
  353. // the specific group address requested here. Pointers to these h/w addresses
  354. // are saved in ALLOC_NP_MEM allocated array pPromisHWAddrArray.
  355. // NumUniquePromisEntries is the count of these addresses.
  356. //
  357. {
  358. PMARS_ENTRY pPromisMarsEntry;
  359. INT TotPromisEntries;
  360. PGROUP_MEMBER pPromisGroup;
  361. NumUniquePromisEntries = 0;
  362. //
  363. // Get total count of promiscuous members.
  364. //
  365. TotPromisEntries = 0;
  366. pPromisMarsEntry = MarsLookupMarsEntry(pIntF, IPADDR_FULL_RANGE, FALSE);
  367. if (pPromisMarsEntry != NULL_PMARS_ENTRY)
  368. {
  369. TotPromisEntries = pPromisMarsEntry->NumMembers;
  370. }
  371. //
  372. // Allocate space to hold the hw addresses of all of them.
  373. //
  374. pPromisHWAddrArray = NULL;
  375. if (TotPromisEntries != 0)
  376. {
  377. pPromisHWAddrArray = (HW_ADDR **) ALLOC_NP_MEM(
  378. TotPromisEntries*sizeof(HW_ADDR *),
  379. POOL_TAG_MARS
  380. );
  381. if (pPromisHWAddrArray == NULL)
  382. {
  383. //
  384. // On alloc failure, simply ignore promiscuous members.
  385. //
  386. TotPromisEntries = 0;
  387. }
  388. }
  389. //
  390. // Now only pick up the hw addresses of those members who
  391. // are not also members of the specific group requested.
  392. //
  393. if (TotPromisEntries!=0)
  394. {
  395. PGROUP_MEMBER pGroupStart = NULL;
  396. if (pMarsEntry!=NULL)
  397. {
  398. pGroupStart = pMarsEntry->pMembers;
  399. }
  400. for(
  401. pPromisGroup = pPromisMarsEntry->pMembers;
  402. TotPromisEntries!=0 && pPromisGroup!=NULL;
  403. TotPromisEntries--, pPromisGroup = pPromisGroup->Next)
  404. {
  405. for (pGroup = pGroupStart;
  406. pGroup!=NULL;
  407. pGroup = pGroup->Next)
  408. {
  409. if (pPromisGroup->pClusterMember == pGroup->pClusterMember)
  410. {
  411. break;
  412. }
  413. }
  414. if (pGroup == NULL)
  415. {
  416. //
  417. // pPromisGroup->pClusterMember is a promiscuous member
  418. // who is not also a member of the specific group
  419. // GrpAddr, so we save a pointer to its hw address
  420. // in our array.
  421. //
  422. pPromisHWAddrArray[NumUniquePromisEntries++] =
  423. &(pPromisGroup->pClusterMember->HwAddr);
  424. }
  425. }
  426. }
  427. if (NumUniquePromisEntries == 0 && TotPromisEntries != 0)
  428. {
  429. FREE_MEM(pPromisHWAddrArray);
  430. pPromisHWAddrArray = NULL;
  431. TotPromisEntries = 0;
  432. }
  433. }
  434. //
  435. // Total addresses equals number of members of the specific group (if any)
  436. // plus NumUniquePromisEntries
  437. //
  438. AddrRem = NumUniquePromisEntries;
  439. if (pMarsEntry != NULL_PMARS_ENTRY)
  440. {
  441. AddrRem += pMarsEntry->NumMembers;
  442. }
  443. if (AddrRem == 0)
  444. {
  445. RHdr->Opcode = OP_MARS_NAK;
  446. SendNak = TRUE;
  447. pIntF->MarsStats.Naks++;
  448. break;
  449. }
  450. // We've computed the total number of hw address we're going to
  451. // send: AddrRem. This consistes of the addresses of all the
  452. // members of the specific group GrpAddr, as well as any
  453. // members of the entire class D space which are not members of
  454. // the specific group.
  455. //
  456. // We'll now create MARS_MULTI send pkts for
  457. // all these hw addresses, starting with the
  458. // the addresses of the specific group, and then tacking on
  459. // the class-D members.
  460. //
  461. //
  462. // Each MARS_MULTI will begin with a copy of the MARS_REQUEST.
  463. //
  464. CopyLength = Length;
  465. AddrPerPacket = (Vc->MaxSendSize - CopyLength)/ATM_ADDRESS_LENGTH;
  466. HeadMultiList = NULL;
  467. pTailMultiList = &HeadMultiList;
  468. SeqY = 1;
  469. if (pMarsEntry != NULL)
  470. {
  471. pGroup = pMarsEntry->pMembers;
  472. }
  473. else
  474. {
  475. pGroup = NULL;
  476. }
  477. ppPromisHWAddr = pPromisHWAddrArray;
  478. for (; AddrRem != 0; SeqY++)
  479. {
  480. AddrCountThisPacket = MIN(AddrRem, (INT)AddrPerPacket);
  481. AddrRem -= AddrCountThisPacket;
  482. PacketLength = CopyLength + (AddrCountThisPacket * ATM_ADDRESS_LENGTH);
  483. MultiPacket = MarsAllocControlPacket(pIntF, PacketLength, (PUCHAR *)&MHdr);
  484. if (MultiPacket != (PNDIS_PACKET)NULL)
  485. {
  486. COPY_MEM(MHdr, RHdr, Length);
  487. MHdr->Opcode = OP_MARS_MULTI;
  488. MHdr->TgtAddressTL = ATM_ADDRESS_LENGTH;
  489. MHdr->TgtSubAddrTL = 0;
  490. PUTULONG2ULONG(&(MHdr->SequenceNumber), pIntF->CSN);
  491. PUTSHORT2SHORT(&(MHdr->NumTgtGroupAddr), AddrCountThisPacket);
  492. #if 0
  493. p = (PUCHAR)(MHdr + 1);
  494. #else
  495. p = (PUCHAR)MHdr + CopyLength;
  496. #endif
  497. while (AddrCountThisPacket-- != 0)
  498. {
  499. HW_ADDR *pHWAddr;
  500. if (pGroup != NULL)
  501. {
  502. pHWAddr = &(pGroup->pClusterMember->HwAddr);
  503. pGroup = pGroup->Next;
  504. }
  505. else
  506. {
  507. ARPS_ASSERT( ppPromisHWAddr
  508. < (pPromisHWAddrArray + NumUniquePromisEntries));
  509. pHWAddr = *(ppPromisHWAddr++);
  510. }
  511. COPY_MEM( p,
  512. pHWAddr->Address.Address,
  513. pHWAddr->Address.NumberOfDigits);
  514. p += pHWAddr->Address.NumberOfDigits;
  515. }
  516. if (AddrRem == 0)
  517. {
  518. SeqY |= LAST_MULTI_FLAG;
  519. }
  520. PUTSHORT2SHORT(&(MHdr->FlagSeq), SeqY);
  521. //
  522. // Link to tail of list of MULTIs.
  523. //
  524. *pTailMultiList = MultiPacket;
  525. MultiResd = RESD_FROM_PKT(MultiPacket);
  526. pTailMultiList = (PNDIS_PACKET *)&(MultiResd->ReqList.Flink);
  527. MultiResd->ReqList.Flink = NULL;
  528. }
  529. else
  530. {
  531. //
  532. // Failed to allocate MULTI: free all packets allocated so far
  533. //
  534. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  535. LockAcquired = FALSE;
  536. while (HeadMultiList != NULL)
  537. {
  538. MultiPacket = HeadMultiList;
  539. MultiResd = RESD_FROM_PKT(MultiPacket);
  540. HeadMultiList = (PNDIS_PACKET)MultiResd->ReqList.Flink;
  541. MarsFreePacket(MultiPacket);
  542. }
  543. break;
  544. }
  545. }
  546. //
  547. // Unless there was an allocation failure (HeadMultiList == NULL),
  548. // we had better have gone through all the hw addresses...
  549. //
  550. ARPS_ASSERT(
  551. HeadMultiList == NULL
  552. || (pGroup == NULL
  553. && (ppPromisHWAddr == (pPromisHWAddrArray+NumUniquePromisEntries))));
  554. //
  555. // We're done with the temporary array of pointers to unique
  556. // promiscuous hw members.
  557. //
  558. if (pPromisHWAddrArray != NULL)
  559. {
  560. FREE_MEM(pPromisHWAddrArray);
  561. }
  562. if (HeadMultiList != NULL)
  563. {
  564. pIntF->MarsStats.VCMeshAcks++;
  565. }
  566. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  567. LockAcquired = FALSE;
  568. if (HeadMultiList != NULL)
  569. {
  570. //
  571. // Send all MULTIs.
  572. //
  573. do
  574. {
  575. MultiPacket = HeadMultiList;
  576. MultiResd = RESD_FROM_PKT(MultiPacket);
  577. HeadMultiList = (PNDIS_PACKET)MultiResd->ReqList.Flink;
  578. MARS_CO_SEND_PACKETS(Vc, &MultiPacket, 1);
  579. }
  580. while (HeadMultiList != NULL);
  581. }
  582. break;
  583. }
  584. while (FALSE);
  585. //
  586. // Update stats (we may not have the IF lock, but we don't care)...
  587. //
  588. if (Discarded)
  589. {
  590. pIntF->MarsStats.DiscardedRecvPkts++;
  591. }
  592. if (LockAcquired)
  593. {
  594. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  595. }
  596. //
  597. // Free the MARS_REQUEST copy if we didn't reuse it.
  598. //
  599. if (SendNak)
  600. {
  601. //
  602. // Send MARS_NAK back
  603. //
  604. NDIS_SET_PACKET_STATUS(Packet, NDIS_STATUS_SUCCESS);
  605. MARS_CO_SEND_PACKETS(Vc, &Packet, 1);
  606. }
  607. else
  608. {
  609. ArpSDereferenceVc(Vc, FALSE, TRUE);
  610. Resd->Vc = NULL;
  611. ExInterlockedPushEntrySList(&ArpSPktList,
  612. &Resd->FreeList,
  613. &ArpSPktListLock);
  614. }
  615. }
  616. VOID
  617. MarsHandleJoin(
  618. IN PINTF pIntF,
  619. IN PARP_VC Vc,
  620. IN PMARS_HEADER Header,
  621. IN PNDIS_PACKET Packet
  622. )
  623. /*++
  624. Routine Description:
  625. Handle MARS_JOIN.
  626. This is issued as part of register (Flags register bit is set and no group addresses
  627. are specified) or to join a group address range.
  628. Arguments:
  629. pIntF - The interface on which the MARS_JOIN arrived
  630. Vc - The VC on which the packet arrived
  631. Header - Points to the request packet
  632. Packet - Packet where the incoming information is copied
  633. Return Value:
  634. None
  635. --*/
  636. {
  637. NDIS_STATUS Status;
  638. PMARS_JOIN_LEAVE JHdr;
  639. PPROTOCOL_RESD Resd;
  640. HW_ADDR SrcAddr;
  641. ATM_ADDRESS SrcSubAddr;
  642. MCAST_ADDR_PAIR GrpAddrRange;
  643. UINT Length;
  644. USHORT Flags, AddrPairs, CMI;
  645. PUCHAR p;
  646. BOOLEAN bSendReply = FALSE, NewMember = FALSE;
  647. PCLUSTER_MEMBER pMember;
  648. PNDIS_PACKET ClusterPacket; // Reply packet to be sent on ClusterControlVc
  649. KIRQL OldIrql;
  650. BOOLEAN LockAcquired;
  651. BOOLEAN Discarded=TRUE, JoinFailed=FALSE, RegistrationFailed=FALSE;
  652. JHdr = (PMARS_JOIN_LEAVE)Header;
  653. Resd = RESD_FROM_PKT(Packet);
  654. ClusterPacket = (PNDIS_PACKET)NULL;
  655. LockAcquired = FALSE;
  656. do
  657. {
  658. //
  659. // Check if we have enough to even parse this.
  660. //
  661. if (Resd->PktLen < sizeof(MARS_JOIN_LEAVE))
  662. {
  663. MARSDBGPRINT(DBG_LEVEL_ERROR,
  664. ("MarsHandleJoin: Packet Length too small: %x\n", Resd->PktLen));
  665. break;
  666. }
  667. GETSHORT2SHORT(&Flags, &JHdr->Flags);
  668. GETSHORT2SHORT(&AddrPairs, &JHdr->NumGrpAddrPairs);
  669. GETSHORT2SHORT(&CMI, &JHdr->ClusterMemberId);
  670. MARSDBGPRINT(DBG_LEVEL_LOUD,
  671. ("MarsHandleJoin: Pkt %x, Flags %x, AddrPairs %x, CMI %x\n",
  672. Packet, Flags, AddrPairs, CMI));
  673. if (Flags & JL_FLAGS_REGISTER)
  674. {
  675. RegistrationFailed = TRUE; // For stats. Assume failure.
  676. pIntF->MarsStats.RegistrationRequests++;
  677. }
  678. else
  679. {
  680. JoinFailed = TRUE; // For stats. Assume failure.
  681. pIntF->MarsStats.TotalJoins++;
  682. }
  683. Length = sizeof(MARS_JOIN_LEAVE) + JHdr->SrcProtoAddrLen +
  684. TL_LEN(Header->SrcAddressTL) +
  685. 2*AddrPairs*(JHdr->GrpProtoAddrLen);
  686. //
  687. // Validate length of packet - it should have what it purports to have
  688. //
  689. if (Length > Resd->PktLen)
  690. {
  691. MARSDBGPRINT(DBG_LEVEL_ERROR,
  692. ("MarsHandleJoin: Invalid packet length %x < %x\n",
  693. Resd->PktLen, Length));
  694. break;
  695. }
  696. if (Flags & JL_FLAGS_COPY)
  697. {
  698. MARSDBGPRINT(DBG_LEVEL_WARN,
  699. ("MarsHandleJoin: dropping pkt %x with COPY set\n", Packet));
  700. break;
  701. }
  702. if (((Flags & JL_FLAGS_REGISTER) == 0) && (JHdr->GrpProtoAddrLen != IP_ADDR_LEN))
  703. {
  704. MARSDBGPRINT(DBG_LEVEL_ERROR,
  705. ("MarsHandleJoin: Invalid Grp address length %x\n",
  706. JHdr->GrpProtoAddrLen));
  707. break;
  708. }
  709. if (((AddrPairs == 0) && ((Flags & JL_FLAGS_REGISTER) == 0)) ||
  710. ((Flags & JL_FLAGS_REGISTER) && (AddrPairs != 0)))
  711. {
  712. MARSDBGPRINT(DBG_LEVEL_ERROR,
  713. ("MarsHandleJoin: Invalid flags/addr pair combination - %x.%x\n",
  714. Flags, AddrPairs));
  715. break;
  716. }
  717. p = (PUCHAR)(JHdr + 1);
  718. SrcAddr.Address.NumberOfDigits = TL_LEN(Header->SrcAddressTL);
  719. if (SrcAddr.Address.NumberOfDigits > 0)
  720. {
  721. SrcAddr.Address.AddressType = TL_TYPE(Header->SrcAddressTL);
  722. COPY_MEM(SrcAddr.Address.Address, p, SrcAddr.Address.NumberOfDigits);
  723. p += SrcAddr.Address.NumberOfDigits;
  724. }
  725. SrcAddr.SubAddress = NULL;
  726. if (TL_LEN(Header->SrcSubAddrTL) > 0)
  727. {
  728. SrcAddr.SubAddress = &SrcSubAddr;
  729. SrcSubAddr.NumberOfDigits = TL_LEN(Header->SrcSubAddrTL);
  730. SrcSubAddr.AddressType = TL_TYPE(Header->SrcSubAddrTL);
  731. COPY_MEM(&SrcSubAddr.Address, p, SrcSubAddr.NumberOfDigits);
  732. p += SrcSubAddr.NumberOfDigits;
  733. }
  734. //
  735. // We only support full length Source ATM Number,
  736. // and zero-length Source ATM Subaddress.
  737. //
  738. // This is because it is not easy to prepare MARS_MULTI
  739. // messages when you have an arbitrary mix of ATM Number and
  740. // ATM Subaddress lengths in the member list for a group.
  741. //
  742. if ((SrcAddr.Address.NumberOfDigits != ATM_ADDRESS_LENGTH) ||
  743. (SrcAddr.SubAddress != NULL))
  744. {
  745. MARSDBGPRINT(DBG_LEVEL_ERROR,
  746. ("MarsHandleJoin: unsupported ATM Number len %x or non-zero subaddr\n",
  747. SrcAddr.Address.NumberOfDigits));
  748. break;
  749. }
  750. //
  751. // We do not care about the Src Ip Addr
  752. //
  753. p += JHdr->SrcProtoAddrLen;
  754. //
  755. // Atmost one Address Pair can be present in a JOIN
  756. //
  757. if (AddrPairs > 1)
  758. {
  759. MARSDBGPRINT(DBG_LEVEL_ERROR,
  760. ("MarsHandleJoin: Too many address pairs: %x\n", AddrPairs));
  761. break;
  762. }
  763. //
  764. // Get the group addr pair, if present
  765. //
  766. if (AddrPairs != 0)
  767. {
  768. MARSDBGPRINT(DBG_LEVEL_LOUD,
  769. ("MarsHandleJoin: Group Min: "));
  770. MARSDUMPIPADDR(DBG_LEVEL_LOUD, *(UNALIGNED IPADDR *)p, ", Group Max ");
  771. GETULONG2ULONG(&GrpAddrRange.MinAddr, p);
  772. p += IP_ADDR_LEN;
  773. MARSDUMPIPADDR(DBG_LEVEL_LOUD, *(UNALIGNED IPADDR *)p, "\n");
  774. GETULONG2ULONG(&GrpAddrRange.MaxAddr, p);
  775. p += IP_ADDR_LEN;
  776. //
  777. // We only support two kinds of JOIN: single group JOIN, or
  778. // JOIN for the entire Class D space. If this is any other
  779. // kind, dump it.
  780. //
  781. if ((GrpAddrRange.MinAddr != GrpAddrRange.MaxAddr) &&
  782. ((GrpAddrRange.MinAddr != MIN_CLASSD_IPADDR_VALUE) ||
  783. (GrpAddrRange.MaxAddr != MAX_CLASSD_IPADDR_VALUE)))
  784. {
  785. MARSDBGPRINT(DBG_LEVEL_ERROR,
  786. ("MarsHandleJoin: invalid pair %x - %x\n",
  787. GrpAddrRange.MinAddr, GrpAddrRange.MaxAddr));
  788. break;
  789. }
  790. }
  791. //
  792. // Set the COPY bit right here in case we send this packet
  793. // back. Also fill in the MARS Seq Number.
  794. //
  795. Flags |= JL_FLAGS_COPY;
  796. PUTSHORT2SHORT(&JHdr->Flags, Flags);
  797. PUTULONG2ULONG(&(JHdr->MarsSequenceNumber), pIntF->CSN);
  798. Discarded = FALSE; // for stats.
  799. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  800. LockAcquired = TRUE;
  801. //
  802. // Search for this (potential) cluster member in our database.
  803. //
  804. pMember = MarsLookupClusterMember(pIntF, &SrcAddr);
  805. if (Flags & JL_FLAGS_REGISTER)
  806. {
  807. //
  808. // A cluster member attempting to register.
  809. //
  810. //
  811. // No groups expected in Registration Join.
  812. //
  813. if (AddrPairs != 0)
  814. {
  815. break; // discard
  816. }
  817. //
  818. // Create a new entry if we need to.
  819. //
  820. if (pMember == NULL_PCLUSTER_MEMBER)
  821. {
  822. //
  823. // If the ClusterControlVc is closing, discard this: we
  824. // are in no shape to handle this now.
  825. //
  826. if ((pIntF->ClusterControlVc != NULL_PMARS_VC) &&
  827. MARS_GET_VC_CONN_STATE(pIntF->ClusterControlVc) == MVC_CONN_CLOSING)
  828. {
  829. break;
  830. }
  831. pMember = MarsCreateClusterMember(pIntF, &SrcAddr);
  832. if (pMember != NULL_PCLUSTER_MEMBER)
  833. {
  834. NewMember = TRUE;
  835. }
  836. }
  837. if (pMember != NULL_PCLUSTER_MEMBER)
  838. {
  839. //
  840. // Successfully registered this Cluster member. Reflect the
  841. // JOIN message back to it with COPY bit set and PUNCHED bit
  842. // reset.
  843. //
  844. Flags &= ~JL_FLAGS_PUNCHED;
  845. PUTSHORT2SHORT(&JHdr->Flags, Flags);
  846. PUTSHORT2SHORT(&JHdr->ClusterMemberId, pMember->CMI);
  847. PUTULONG2ULONG(&JHdr->MarsSequenceNumber, pIntF->CSN);
  848. bSendReply = TRUE;
  849. RegistrationFailed = FALSE;
  850. }
  851. }
  852. else
  853. {
  854. //
  855. // A cluster member Joining one or more multicast groups.
  856. // Allow this only if the cluster member has been
  857. // successfully added to ClusterControlVc AND it is in a position to add groups to it.
  858. //
  859. if ((pMember != NULL_PCLUSTER_MEMBER) &&
  860. (MARS_GET_CM_CONN_STATE(pMember) == CM_CONN_ACTIVE) &&
  861. (MARS_GET_CM_GROUP_STATE(pMember) == CM_GROUP_ACTIVE))
  862. {
  863. if (AddrPairs != 0)
  864. {
  865. if (MarsAddClusterMemberToGroups(
  866. pIntF,
  867. pMember,
  868. &GrpAddrRange,
  869. Packet,
  870. JHdr,
  871. Length,
  872. &ClusterPacket
  873. ))
  874. {
  875. JoinFailed = FALSE; // For stats.
  876. bSendReply = TRUE;
  877. }
  878. else if (ClusterPacket!=NULL)
  879. {
  880. JoinFailed = FALSE; // For stats.
  881. }
  882. }
  883. //
  884. // else discard: no groups specified.
  885. //
  886. }
  887. //
  888. // else discard: unknown member or member not added to ClusterControlVc
  889. //
  890. }
  891. } while (FALSE);
  892. //
  893. // Update stats (we may not have the IF lock, but we don't care)...
  894. //
  895. if (RegistrationFailed)
  896. {
  897. pIntF->MarsStats.FailedRegistrations++; // this includes failures due to bad pkts.
  898. }
  899. if (JoinFailed)
  900. {
  901. pIntF->MarsStats.FailedJoins++; // this include failures due to bad pkts.
  902. }
  903. if (Discarded)
  904. {
  905. pIntF->MarsStats.DiscardedRecvPkts++;
  906. }
  907. if (LockAcquired)
  908. {
  909. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  910. }
  911. //
  912. // Follow up actions:
  913. //
  914. // - We may send a reply on the VC this packet came on
  915. // - We may initiate AddParty to add a new member to ClusterControlVc
  916. // - We may send a reply packet on ClusterControlVc
  917. //
  918. if (bSendReply)
  919. {
  920. //
  921. // Send this back on the VC we received the JOIN from
  922. //
  923. NDIS_SET_PACKET_STATUS(Packet, NDIS_STATUS_SUCCESS);
  924. MARS_CO_SEND_PACKETS(Vc, &Packet, 1);
  925. }
  926. else
  927. {
  928. if (ClusterPacket != Packet)
  929. {
  930. ArpSDereferenceVc(Vc, FALSE, TRUE);
  931. Resd->Vc = NULL;
  932. ExInterlockedPushEntrySList(&ArpSPktList,
  933. &Resd->FreeList,
  934. &ArpSPktListLock);
  935. }
  936. //
  937. // else we're sending Packet on CC VC
  938. //
  939. }
  940. if (NewMember)
  941. {
  942. MarsAddMemberToClusterControlVc(pIntF, pMember);
  943. }
  944. if (ClusterPacket != (PNDIS_PACKET)NULL)
  945. {
  946. //
  947. // Send this packet on ClusterControlVc.
  948. //
  949. MarsSendOnClusterControlVc(pIntF, ClusterPacket);
  950. }
  951. }
  952. VOID
  953. MarsHandleLeave(
  954. IN PINTF pIntF,
  955. IN PARP_VC Vc,
  956. IN PMARS_HEADER Header,
  957. IN PNDIS_PACKET Packet
  958. )
  959. /*++
  960. Routine Description:
  961. Handle MARS_LEAVE.
  962. Arguments:
  963. pIntF - The interface on which the MARS_LEAVE arrived
  964. Vc - The VC on which the packet arrived
  965. Header - Points to the request packet
  966. Packet - Packet where the incoming information is copied
  967. Return Value:
  968. None
  969. --*/
  970. {
  971. NDIS_STATUS Status;
  972. PMARS_JOIN_LEAVE LHdr;
  973. PPROTOCOL_RESD Resd;
  974. HW_ADDR SrcAddr;
  975. ATM_ADDRESS SrcSubAddr;
  976. MCAST_ADDR_PAIR GrpAddrRange;
  977. UINT Length;
  978. USHORT Flags, AddrPairs, CMI;
  979. PUCHAR p;
  980. BOOLEAN bSendReply = FALSE, Deregistered = FALSE;
  981. PCLUSTER_MEMBER pMember;
  982. PNDIS_PACKET ClusterPacket; // Reply packet to be sent on ClusterControlVc
  983. KIRQL OldIrql;
  984. BOOLEAN LockAcquired;
  985. BOOLEAN Discarded=TRUE, LeaveFailed=FALSE;
  986. LHdr = (PMARS_JOIN_LEAVE)Header;
  987. Resd = RESD_FROM_PKT(Packet);
  988. ClusterPacket = (PNDIS_PACKET)NULL;
  989. LockAcquired = FALSE;
  990. do
  991. {
  992. //
  993. // Check if we have enough to even parse this.
  994. //
  995. if (Resd->PktLen < sizeof(MARS_JOIN_LEAVE))
  996. {
  997. MARSDBGPRINT(DBG_LEVEL_ERROR,
  998. ("MarsHandleLeave: Packet Length too small: %x\n", Resd->PktLen));
  999. break;
  1000. }
  1001. GETSHORT2SHORT(&Flags, &LHdr->Flags);
  1002. GETSHORT2SHORT(&AddrPairs, &LHdr->NumGrpAddrPairs);
  1003. GETSHORT2SHORT(&CMI, &LHdr->ClusterMemberId);
  1004. MARSDBGPRINT(DBG_LEVEL_LOUD,
  1005. ("MarsHandleLeave: Pkt %x, Flags %x, AddrPairs %x, CMI %x\n",
  1006. Packet, Flags, AddrPairs, CMI));
  1007. Length = sizeof(MARS_JOIN_LEAVE) + LHdr->SrcProtoAddrLen +
  1008. TL_LEN(Header->SrcAddressTL) +
  1009. 2*AddrPairs*(LHdr->GrpProtoAddrLen);
  1010. if (Flags & JL_FLAGS_REGISTER)
  1011. {
  1012. // We don't track de-registrations.
  1013. }
  1014. else
  1015. {
  1016. LeaveFailed = TRUE; // For stats. Assume failure.
  1017. pIntF->MarsStats.TotalLeaves++;
  1018. }
  1019. //
  1020. // Validate length of packet - it should have what it purports to have
  1021. //
  1022. if (Length > Resd->PktLen)
  1023. {
  1024. MARSDBGPRINT(DBG_LEVEL_ERROR,
  1025. ("MarsHandleLeave: Invalid packet length %x < %x\n",
  1026. Resd->PktLen, Length));
  1027. break;
  1028. }
  1029. if (Flags & JL_FLAGS_COPY)
  1030. {
  1031. MARSDBGPRINT(DBG_LEVEL_INFO,
  1032. ("MarsHandleLeave: dropping pkt %x with COPY set\n", Packet));
  1033. break;
  1034. }
  1035. if (((Flags & JL_FLAGS_REGISTER) == 0) && (LHdr->GrpProtoAddrLen != IP_ADDR_LEN))
  1036. {
  1037. MARSDBGPRINT(DBG_LEVEL_ERROR,
  1038. ("MarsHandleLeave: Invalid Grp address length %x\n",
  1039. LHdr->GrpProtoAddrLen));
  1040. break;
  1041. }
  1042. if (((AddrPairs == 0) && ((Flags & JL_FLAGS_REGISTER) == 0)) ||
  1043. ((Flags & JL_FLAGS_REGISTER) && (AddrPairs != 0)))
  1044. {
  1045. MARSDBGPRINT(DBG_LEVEL_ERROR,
  1046. ("MarsHandleLeave: Invalid flags/addr pair combination - %x.%x\n",
  1047. Flags, AddrPairs));
  1048. break;
  1049. }
  1050. p = (PUCHAR)(LHdr + 1);
  1051. SrcAddr.Address.NumberOfDigits = TL_LEN(Header->SrcAddressTL);
  1052. if (SrcAddr.Address.NumberOfDigits > 0)
  1053. {
  1054. SrcAddr.Address.AddressType = TL_TYPE(Header->SrcAddressTL);
  1055. COPY_MEM(SrcAddr.Address.Address, p, SrcAddr.Address.NumberOfDigits);
  1056. p += SrcAddr.Address.NumberOfDigits;
  1057. }
  1058. SrcAddr.SubAddress = NULL;
  1059. if (TL_LEN(Header->SrcSubAddrTL) > 0)
  1060. {
  1061. SrcAddr.SubAddress = &SrcSubAddr;
  1062. SrcSubAddr.NumberOfDigits = TL_LEN(Header->SrcSubAddrTL);
  1063. SrcSubAddr.AddressType = TL_TYPE(Header->SrcSubAddrTL);
  1064. COPY_MEM(&SrcSubAddr.Address, p, SrcSubAddr.NumberOfDigits);
  1065. p += SrcSubAddr.NumberOfDigits;
  1066. }
  1067. //
  1068. // We do not care about the Src Ip Addr
  1069. //
  1070. p += LHdr->SrcProtoAddrLen;
  1071. //
  1072. // Atmost one Address Pair can be present in a LEAVE
  1073. //
  1074. if (AddrPairs > 1)
  1075. {
  1076. break;
  1077. }
  1078. //
  1079. // Get the group addr pair, if present
  1080. //
  1081. if (AddrPairs != 0)
  1082. {
  1083. MARSDBGPRINT(DBG_LEVEL_LOUD,
  1084. ("HandleLeave: Group Min: "));
  1085. MARSDUMPIPADDR(DBG_LEVEL_LOUD, *(UNALIGNED IPADDR *)p, ", Group Max ");
  1086. GETULONG2ULONG(&GrpAddrRange.MinAddr, p);
  1087. p += IP_ADDR_LEN;
  1088. MARSDUMPIPADDR(DBG_LEVEL_LOUD, *(UNALIGNED IPADDR *)p, "\n");
  1089. GETULONG2ULONG(&GrpAddrRange.MaxAddr, p);
  1090. p += IP_ADDR_LEN;
  1091. //
  1092. // We only support two kinds of non-deregistration LEAVE:
  1093. // single group LEAVE, or LEAVE for the entire Class D space.
  1094. // If this is any other kind, dump it.
  1095. //
  1096. if ((GrpAddrRange.MinAddr != GrpAddrRange.MaxAddr) &&
  1097. ((GrpAddrRange.MinAddr != MIN_CLASSD_IPADDR_VALUE) ||
  1098. (GrpAddrRange.MaxAddr != MAX_CLASSD_IPADDR_VALUE)))
  1099. {
  1100. break;
  1101. }
  1102. }
  1103. //
  1104. // Set the COPY bit right here in case we send this packet
  1105. // back. Also fill in the MARS Seq Number.
  1106. //
  1107. Flags |= JL_FLAGS_COPY;
  1108. PUTSHORT2SHORT(&LHdr->Flags, Flags);
  1109. PUTULONG2ULONG(&(LHdr->MarsSequenceNumber), pIntF->CSN);
  1110. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  1111. LockAcquired = TRUE;
  1112. Discarded = FALSE; // For stats.
  1113. //
  1114. // Search for this (potential) cluster member in our database.
  1115. //
  1116. pMember = MarsLookupClusterMember(pIntF, &SrcAddr);
  1117. if (Flags & JL_FLAGS_REGISTER)
  1118. {
  1119. //
  1120. // A cluster member attempting to de-register.
  1121. //
  1122. if (AddrPairs == 0)
  1123. {
  1124. if (pMember != NULL_PCLUSTER_MEMBER)
  1125. {
  1126. //
  1127. // Unlink all Group structures from the Cluster member,
  1128. // AND disable further groups from being added.
  1129. //
  1130. MarsUnlinkAllGroupsOnClusterMember(pIntF, pMember);
  1131. Deregistered = TRUE;
  1132. //
  1133. // Successfully de-registered this Cluster member. Reflect the
  1134. // LEAVE message back to it with COPY bit set and PUNCHED bit
  1135. // reset.
  1136. //
  1137. Flags &= ~JL_FLAGS_PUNCHED;
  1138. PUTSHORT2SHORT(&LHdr->Flags, Flags);
  1139. PUTULONG2ULONG(&LHdr->MarsSequenceNumber, pIntF->CSN);
  1140. bSendReply = TRUE;
  1141. }
  1142. }
  1143. //
  1144. // else discard: no groups expected in DeRegistration Leave
  1145. //
  1146. }
  1147. else
  1148. {
  1149. //
  1150. // A cluster member Leaving one or more multicast groups.
  1151. //
  1152. if (AddrPairs != 0)
  1153. {
  1154. if (MarsDelClusterMemberFromGroups(
  1155. pIntF,
  1156. pMember,
  1157. &GrpAddrRange,
  1158. Packet,
  1159. LHdr,
  1160. Length,
  1161. &ClusterPacket
  1162. ))
  1163. {
  1164. bSendReply = TRUE;
  1165. LeaveFailed = FALSE;
  1166. }
  1167. }
  1168. //
  1169. // else discard: no groups specified.
  1170. //
  1171. }
  1172. } while (FALSE);
  1173. //
  1174. // Update stats (we may not have the IF lock, but we don't care)...
  1175. //
  1176. if (LeaveFailed)
  1177. {
  1178. pIntF->MarsStats.FailedLeaves++; // this includes failures due to bad pkts.
  1179. }
  1180. if (Discarded)
  1181. {
  1182. pIntF->MarsStats.DiscardedRecvPkts++;
  1183. }
  1184. if (LockAcquired)
  1185. {
  1186. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  1187. }
  1188. //
  1189. // Follow up actions:
  1190. //
  1191. // - We may send a reply on the VC this packet came on
  1192. // - We may initiate DropParty to delete a member from ClusterControlVc
  1193. // - We may send a reply packet on ClusterControlVc
  1194. //
  1195. if (bSendReply)
  1196. {
  1197. //
  1198. // Send this back on the VC we received the JOIN from
  1199. //
  1200. NDIS_SET_PACKET_STATUS(Packet, NDIS_STATUS_SUCCESS);
  1201. MARS_CO_SEND_PACKETS(Vc, &Packet, 1);
  1202. }
  1203. else
  1204. {
  1205. if (ClusterPacket != Packet)
  1206. {
  1207. ArpSDereferenceVc(Vc, FALSE, TRUE);
  1208. Resd->Vc = NULL;
  1209. ExInterlockedPushEntrySList(&ArpSPktList,
  1210. &Resd->FreeList,
  1211. &ArpSPktListLock);
  1212. }
  1213. //
  1214. // else we're sending this packet on CC VC
  1215. //
  1216. }
  1217. if (Deregistered)
  1218. {
  1219. BOOLEAN fLocked =
  1220. MarsDelMemberFromClusterControlVc(pIntF, pMember, FALSE, 0);
  1221. ASSERT(!fLocked);
  1222. }
  1223. if (ClusterPacket != NULL)
  1224. {
  1225. //
  1226. // Send this packet on ClusterControlVc.
  1227. //
  1228. MarsSendOnClusterControlVc(pIntF, ClusterPacket);
  1229. }
  1230. }
  1231. PCLUSTER_MEMBER
  1232. MarsLookupClusterMember(
  1233. IN PINTF pIntF,
  1234. IN PHW_ADDR pHwAddr
  1235. )
  1236. /*++
  1237. Routine Description:
  1238. Given the Hardware address of a cluster member, search our list
  1239. of cluster members for an entry that matches this.
  1240. It is assumed that the caller has acquired the IntF lock.
  1241. Arguments:
  1242. pIntF - Ptr to Interface to search in
  1243. pHwAddr - Ptr to ATM address and subaddress
  1244. Return Value:
  1245. Pointer to Cluster member structure if found, else NULL.
  1246. --*/
  1247. {
  1248. PCLUSTER_MEMBER pMember;
  1249. for (pMember = pIntF->ClusterMembers;
  1250. pMember != NULL;
  1251. pMember = pMember->Next)
  1252. {
  1253. if (COMP_HW_ADDR(pHwAddr, &pMember->HwAddr))
  1254. {
  1255. break;
  1256. }
  1257. }
  1258. return (pMember);
  1259. }
  1260. PCLUSTER_MEMBER
  1261. MarsCreateClusterMember(
  1262. IN PINTF pIntF,
  1263. IN PHW_ADDR pHwAddr
  1264. )
  1265. /*++
  1266. Routine Description:
  1267. Allocate and initialize a Cluster Member structure, and link it
  1268. to the list of members on the specified Interface.
  1269. It is assumed that the caller has acquired the IntF spin lock.
  1270. Arguments:
  1271. pIntF - Ptr to Interface on which this member has joined
  1272. pHwAddr - ATM address and subaddress for this new member
  1273. Return Value:
  1274. Pointer to Cluster member structure if successful, else NULL.
  1275. --*/
  1276. {
  1277. PCLUSTER_MEMBER pMember;
  1278. ENTRY_TYPE EntryType;
  1279. ULONG Length;
  1280. Length = sizeof(CLUSTER_MEMBER) +
  1281. ((pHwAddr->SubAddress != NULL) ? sizeof(ATM_ADDRESS) : 0);
  1282. pMember = ALLOC_NP_MEM(Length, POOL_TAG_MARS);
  1283. if (pMember == NULL)
  1284. {
  1285. LOG_ERROR(NDIS_STATUS_RESOURCES);
  1286. }
  1287. else
  1288. {
  1289. if (++(pIntF->MarsStats.CurrentClusterMembers) > pIntF->MarsStats.MaxClusterMembers)
  1290. {
  1291. pIntF->MarsStats.MaxClusterMembers = pIntF->MarsStats.CurrentClusterMembers;
  1292. }
  1293. ZERO_MEM(pMember, Length);
  1294. COPY_ATM_ADDR(&pMember->HwAddr.Address, &pHwAddr->Address);
  1295. if (pHwAddr->SubAddress != NULL)
  1296. {
  1297. pMember->HwAddr.SubAddress = (PATM_ADDRESS)(pMember + 1);
  1298. COPY_ATM_ADDR(pMember->HwAddr.SubAddress, pHwAddr->SubAddress);
  1299. }
  1300. pMember->pIntF = pIntF;
  1301. //
  1302. // Link it to the list of Cluster Members on this Interface.
  1303. //
  1304. #if 0
  1305. {
  1306. PCLUSTER_MEMBER * pPrev;
  1307. for (pPrev= &(pIntF->ClusterMembers);
  1308. *pPrev != NULL;
  1309. pPrev = &(PCLUSTER_MEMBER)((*pPrev)->Next) )
  1310. {
  1311. // Nothing
  1312. }
  1313. pMember->Next = NULL;
  1314. pMember->Prev = pPrev;
  1315. *pPrev = (PCLUSTER_MEMBER)pMember;
  1316. }
  1317. #else
  1318. pMember->Next = pIntF->ClusterMembers;
  1319. pMember->Prev = &(pIntF->ClusterMembers);
  1320. if (pIntF->ClusterMembers != NULL_PCLUSTER_MEMBER)
  1321. {
  1322. pIntF->ClusterMembers->Prev = &(pMember->Next);
  1323. }
  1324. pIntF->ClusterMembers = pMember;
  1325. #endif
  1326. pIntF->NumClusterMembers++;
  1327. //
  1328. // Assign it a CMI
  1329. //
  1330. pMember->CMI = pIntF->CMI++;
  1331. }
  1332. MARSDBGPRINT(DBG_LEVEL_INFO,
  1333. ("New Cluster Member 0x%x, pIntF %x, CMI %x, Prev %x, Next %x, ATM Addr:",
  1334. pMember, pIntF, pMember->CMI, pMember->Prev, pMember->Next));
  1335. MARSDUMPATMADDR(DBG_LEVEL_INFO, &pHwAddr->Address, "");
  1336. return (pMember);
  1337. }
  1338. VOID
  1339. MarsDeleteClusterMember(
  1340. IN PINTF pIntF,
  1341. IN PCLUSTER_MEMBER pMember
  1342. )
  1343. /*++
  1344. Routine Description:
  1345. Remove Cluster member from the list of Cluster members, and free it.
  1346. Arguments:
  1347. pIntF - Ptr to Interface
  1348. pMember - Cluster member to be freed
  1349. Return Value:
  1350. None
  1351. --*/
  1352. {
  1353. ARPS_ASSERT(pMember->pGroupList == NULL_PGROUP_MEMBER);
  1354. MARSDBGPRINT(DBG_LEVEL_INFO,
  1355. ("MarsDeleteClusterMember: pIntF %x, pMember %x, Next %x, Prev %x\n",
  1356. pIntF, pMember, pMember->Next, pMember->Prev));
  1357. pIntF->MarsStats.CurrentClusterMembers--;
  1358. //
  1359. // De-link this Cluster Member from the list on IntF.
  1360. //
  1361. *(pMember->Prev) = pMember->Next;
  1362. if (pMember->Next != NULL)
  1363. {
  1364. ((PENTRY_HDR)pMember->Next)->Prev = pMember->Prev;
  1365. }
  1366. pIntF->NumClusterMembers--;
  1367. FREE_MEM(pMember);
  1368. }
  1369. PMARS_ENTRY
  1370. MarsLookupMarsEntry(
  1371. IN PINTF pIntF,
  1372. IN IPADDR GrpAddr,
  1373. IN BOOLEAN bCreateNew
  1374. )
  1375. /*++
  1376. Routine Description:
  1377. Look up the MARS_ENTRY for the given Group Address on the specified
  1378. Interface. Optionally create a new one if not found.
  1379. The caller is assumed to hold the IntF lock.
  1380. Arguments:
  1381. pIntF - Ptr to Interface
  1382. GrpAddr - The address to look for
  1383. bCreateNew - Should we create a new entry if one isn't present?
  1384. Return Value:
  1385. Pointer to MARS entry if found/created, else NULL.
  1386. --*/
  1387. {
  1388. PMARS_ENTRY * ppMarsEntry;
  1389. PMARS_ENTRY pMarsEntry = NULL_PMARS_ENTRY;
  1390. UINT Hash = MARS_HASH(GrpAddr);
  1391. MARSDBGPRINT(DBG_LEVEL_LOUD,
  1392. ("MarsLookupMarsEntry: for IP Addr: "));
  1393. MARSDUMPIPADDR(DBG_LEVEL_LOUD, GrpAddr, "...");
  1394. for (ppMarsEntry = &pIntF->MarsCache[Hash];
  1395. *ppMarsEntry != NULL;
  1396. ppMarsEntry = (PMARS_ENTRY *)(&(*ppMarsEntry)->Next))
  1397. {
  1398. if ((*ppMarsEntry)->IPAddress == GrpAddr)
  1399. {
  1400. pMarsEntry = *ppMarsEntry;
  1401. break;
  1402. }
  1403. if ((*ppMarsEntry)->IPAddress > GrpAddr)
  1404. {
  1405. //
  1406. // No chance of finding this.
  1407. //
  1408. break;
  1409. }
  1410. }
  1411. MARSDBGPRINT(DBG_LEVEL_LOUD+DBG_NO_HDR,
  1412. ("%sFound\n", ((pMarsEntry != NULL_PMARS_ENTRY)? "" : "Not ")));
  1413. if ((pMarsEntry == NULL_PMARS_ENTRY) && bCreateNew)
  1414. {
  1415. pMarsEntry = (PMARS_ENTRY)ArpSAllocBlock(pIntF, MARS_BLOCK_ENTRY);
  1416. if (pMarsEntry == NULL_PMARS_ENTRY)
  1417. {
  1418. LOG_ERROR(NDIS_STATUS_RESOURCES);
  1419. }
  1420. else
  1421. {
  1422. //
  1423. // Fill in the new entry.
  1424. //
  1425. pMarsEntry->IPAddress = GrpAddr;
  1426. pMarsEntry->pIntF = pIntF;
  1427. //
  1428. // ppMarsEntry points to the Next field of the predecessor of this new entry
  1429. //
  1430. pMarsEntry->Next = *ppMarsEntry;
  1431. pMarsEntry->Prev = ppMarsEntry;
  1432. if (*ppMarsEntry != NULL_PMARS_ENTRY)
  1433. {
  1434. (*ppMarsEntry)->Prev = &(pMarsEntry->Next);
  1435. }
  1436. *ppMarsEntry = pMarsEntry;
  1437. MARSDBGPRINT(DBG_LEVEL_INFO,
  1438. ("MarsLookupMarsEntry: new entry %x for IP Addr:", pMarsEntry));
  1439. MARSDUMPIPADDR(DBG_LEVEL_INFO, GrpAddr, "\n");
  1440. if (++(pIntF->MarsStats.CurrentGroups) > pIntF->MarsStats.MaxGroups)
  1441. {
  1442. pIntF->MarsStats.MaxGroups = pIntF->MarsStats.CurrentGroups;
  1443. }
  1444. }
  1445. }
  1446. return (pMarsEntry);
  1447. }
  1448. BOOLEAN
  1449. MarsIsAddressMcsServed(
  1450. IN PINTF pIntF,
  1451. IN IPADDR IPAddress
  1452. )
  1453. /*++
  1454. Routine Description:
  1455. Check if the given IP Address is one that is served by MCS.
  1456. Arguments:
  1457. pIntF - Ptr to Interface
  1458. IPAddress - Address to check
  1459. Return Value:
  1460. TRUE if we are the MCS serving IPAddress, else FALSE.
  1461. --*/
  1462. {
  1463. PMCS_ENTRY pMcsEntry;
  1464. for (pMcsEntry = pIntF->pMcsList;
  1465. pMcsEntry != NULL_PMCS_ENTRY;
  1466. pMcsEntry = (PMCS_ENTRY)pMcsEntry->Next)
  1467. {
  1468. if ((IPAddress >= pMcsEntry->GrpAddrPair.MinAddr) &&
  1469. (IPAddress <= pMcsEntry->GrpAddrPair.MaxAddr))
  1470. {
  1471. return TRUE;
  1472. }
  1473. }
  1474. return FALSE;
  1475. }
  1476. VOID
  1477. MarsPunchHoles(
  1478. IN PMCAST_ADDR_PAIR pGrpAddrRange,
  1479. IN PGROUP_MEMBER pGroupList,
  1480. IN PINTF pIntF,
  1481. IN IPADDR UNALIGNED * pOutBuf OPTIONAL,
  1482. OUT PUSHORT pMinMaxCount,
  1483. OUT BOOLEAN * pAnyHolesPunched
  1484. )
  1485. /*++
  1486. Routine Description:
  1487. Punch holes in the given IP Address range, according to RFC 2022.
  1488. These holes correspond to:
  1489. 1. IP Addresses that are MCS-supported
  1490. 2. IP Addresses that are present in the given Group Member list
  1491. Optionally, fill in an output buffer (reflected JOIN/LEAVE) with the
  1492. resulting <min, max> list.
  1493. This routine gets called twice when processing any JOIN or LEAVE message,
  1494. once to get the MinMaxCount and AnyHolesPunched info, and then again,
  1495. after space has been allocated for MinMaxCount pairs, to fill in
  1496. a retransmitted JOIN or LEAVE.
  1497. Arguments:
  1498. pGrpAddrRange - The range to punch holes in
  1499. pGroupList - #2 in Routine Description above
  1500. pIntF - Ptr to Interface
  1501. pOutBuf - If not NULL, place to write <min, max> pairs to.
  1502. pMinMaxCount - The number of discrete, non-contiguous IP address ranges
  1503. remaining after hole-punching.
  1504. pAnyHolesPunched- Where we return TRUE iff we punched atleast one hole.
  1505. Return Value:
  1506. None. See OUT parameters above.
  1507. --*/
  1508. {
  1509. PGROUP_MEMBER pGroup;
  1510. PMCS_ENTRY pMcsEntry;
  1511. IPADDR StartOfThisRange;
  1512. IPADDR IPAddress;
  1513. UNALIGNED IPADDR * pIPAddress;
  1514. BOOLEAN InHole; // are we in a hole now?
  1515. BOOLEAN HolePunched; // any holes punched so far?
  1516. BOOLEAN InGroupList;
  1517. BOOLEAN InMcsList;
  1518. *pMinMaxCount = 0;
  1519. StartOfThisRange = pGrpAddrRange->MinAddr;
  1520. pGroup = pGroupList;
  1521. pMcsEntry = pIntF->pMcsList;
  1522. InHole = FALSE;
  1523. HolePunched = FALSE;
  1524. pIPAddress = (UNALIGNED IPADDR *)pOutBuf;
  1525. for (IPAddress = pGrpAddrRange->MinAddr;
  1526. IPAddress <= pGrpAddrRange->MaxAddr;
  1527. IPAddress++)
  1528. {
  1529. //
  1530. // Check if IPAddress is covered by the Group Member list.
  1531. //
  1532. while ((pGroup != NULL) &&
  1533. (pGroup->pMarsEntry->IPAddress < IPAddress))
  1534. {
  1535. pGroup = (PGROUP_MEMBER)pGroup->pNextGroup;
  1536. }
  1537. if ((pGroup != NULL) &&
  1538. (pGroup->pMarsEntry->IPAddress == IPAddress))
  1539. {
  1540. InGroupList = TRUE;
  1541. }
  1542. else
  1543. {
  1544. InGroupList = FALSE;
  1545. }
  1546. //
  1547. // Check if IPAddress is served by MCS.
  1548. //
  1549. while ((pMcsEntry != NULL) &&
  1550. (pMcsEntry->GrpAddrPair.MaxAddr < IPAddress))
  1551. {
  1552. pMcsEntry = (PMCS_ENTRY)pMcsEntry->Next;
  1553. }
  1554. if ((pMcsEntry != NULL) &&
  1555. ((pMcsEntry->GrpAddrPair.MinAddr <= IPAddress) &&
  1556. (pMcsEntry->GrpAddrPair.MaxAddr >= IPAddress)))
  1557. {
  1558. InMcsList = TRUE;
  1559. }
  1560. else
  1561. {
  1562. InMcsList = FALSE;
  1563. }
  1564. if (InHole)
  1565. {
  1566. if (!InGroupList && !InMcsList)
  1567. {
  1568. //
  1569. // Out of the hole with this IPAddress
  1570. //
  1571. InHole = FALSE;
  1572. StartOfThisRange = IPAddress;
  1573. }
  1574. else
  1575. {
  1576. //
  1577. // A hole right next to the one we were previously in..
  1578. // Jump to the end of this hole...
  1579. // (If we're not in an mcs-served range then we're already
  1580. // at the end of the single-address hole and so don't do anything).
  1581. //
  1582. if (InMcsList)
  1583. {
  1584. IPAddress = pMcsEntry->GrpAddrPair.MaxAddr;
  1585. if (IPAddress > pGrpAddrRange->MaxAddr)
  1586. {
  1587. IPAddress = pGrpAddrRange->MaxAddr;
  1588. }
  1589. }
  1590. }
  1591. }
  1592. else
  1593. {
  1594. if (InGroupList || InMcsList)
  1595. {
  1596. //
  1597. // Entering a hole that includes IPAddress
  1598. //
  1599. InHole = TRUE;
  1600. HolePunched = TRUE;
  1601. if (IPAddress > StartOfThisRange)
  1602. {
  1603. (*pMinMaxCount)++;
  1604. if (pIPAddress)
  1605. {
  1606. //
  1607. // Write out a pair: <StartOfThisRange to IPAddress-1>
  1608. //
  1609. PUTULONG2ULONG(pIPAddress, StartOfThisRange);
  1610. pIPAddress++;
  1611. IPAddress--;
  1612. PUTULONG2ULONG(pIPAddress, IPAddress);
  1613. pIPAddress++;
  1614. IPAddress++;
  1615. }
  1616. }
  1617. //
  1618. // Jump to the end of this hole...
  1619. // (If we're not in an mcs-served range then we're already
  1620. // at the end of the single-address hole and so don't do anything).
  1621. //
  1622. if (InMcsList)
  1623. {
  1624. IPAddress = pMcsEntry->GrpAddrPair.MaxAddr;
  1625. if (IPAddress > pGrpAddrRange->MaxAddr)
  1626. {
  1627. IPAddress = pGrpAddrRange->MaxAddr;
  1628. }
  1629. }
  1630. }
  1631. else
  1632. {
  1633. //
  1634. // We're not in a hole -- skip to just before the next hole...
  1635. //
  1636. //
  1637. // Since we're not in a hole, the following 2 assertions hold.
  1638. //
  1639. ARPS_ASSERT(pGroup==NULL || pGroup->pMarsEntry->IPAddress > IPAddress);
  1640. ARPS_ASSERT(pMcsEntry==NULL || pMcsEntry->GrpAddrPair.MinAddr > IPAddress);
  1641. //
  1642. // We now pick the skip to just before the next hole which is either
  1643. // a group address or a mcs-served range, whichever comes first.
  1644. // Note that either entry could be NULL.
  1645. //
  1646. if (pGroup != NULL)
  1647. {
  1648. IPAddress = pGroup->pMarsEntry->IPAddress-1;
  1649. }
  1650. if ( (pMcsEntry != NULL)
  1651. && ( (pGroup == NULL)
  1652. || (pMcsEntry->GrpAddrPair.MinAddr <= IPAddress)))
  1653. {
  1654. IPAddress = pMcsEntry->GrpAddrPair.MinAddr-1;
  1655. }
  1656. //
  1657. // Truncate back to the end of the GrpAddrRange
  1658. //
  1659. if (IPAddress > pGrpAddrRange->MaxAddr)
  1660. {
  1661. IPAddress = pGrpAddrRange->MaxAddr;
  1662. }
  1663. }
  1664. }
  1665. //
  1666. // Corner case: Handle IPAddress 255.255.255.255
  1667. // (because adding 1 to it causes rollover)
  1668. //
  1669. if (IPAddress == IP_BROADCAST_ADDR_VALUE)
  1670. {
  1671. break;
  1672. }
  1673. }
  1674. if (!InHole)
  1675. {
  1676. (*pMinMaxCount)++;
  1677. if (pIPAddress)
  1678. {
  1679. //
  1680. // Write out a pair: <StartOfThisRange to IPAddress-1>
  1681. //
  1682. PUTULONG2ULONG(pIPAddress, StartOfThisRange);
  1683. pIPAddress++;
  1684. IPAddress--;
  1685. PUTULONG2ULONG(pIPAddress, IPAddress);
  1686. pIPAddress++;
  1687. }
  1688. }
  1689. *pAnyHolesPunched = HolePunched;
  1690. return;
  1691. }
  1692. BOOLEAN
  1693. MarsAddClusterMemberToGroups(
  1694. IN PINTF pIntF,
  1695. IN PCLUSTER_MEMBER pMember,
  1696. IN PMCAST_ADDR_PAIR pGrpAddrRange,
  1697. IN PNDIS_PACKET Packet,
  1698. IN PMARS_JOIN_LEAVE JHdr,
  1699. IN UINT Length,
  1700. OUT PNDIS_PACKET * ppClusterPacket
  1701. )
  1702. /*++
  1703. Routine Description:
  1704. This is called when processing a non-registration JOIN.
  1705. Add a Cluster member to the multicast groups in the given range
  1706. (could be just one). Create all necessary data structures and
  1707. linkages for this.
  1708. It is assumed that the caller has acquired the IntF spin lock.
  1709. Arguments:
  1710. pIntF - Ptr to Interface on which this member has joined
  1711. pMember - Ptr to Cluster member
  1712. pGrpAddrRange - Min, Max IP addresses being Joined
  1713. Packet - Ptr to NDIS packet containing the JOIN
  1714. JHdr - Ptr to incoming JOIN
  1715. Length - of incoming JOIN
  1716. ppClusterPacket - Optionally, a packet to be sent out on ClusterControlVc.
  1717. Return Value:
  1718. TRUE if the member was added successfully to the indicated groups,
  1719. FALSE otherwise. If we returned TRUE, we also set *pClusterPacket optionally
  1720. to a packet to be sent out on ClusterControlVc.
  1721. --*/
  1722. {
  1723. PGROUP_MEMBER pGroup;
  1724. PGROUP_MEMBER * ppGroup;
  1725. PMARS_ENTRY pMarsEntry;
  1726. PMARS_JOIN_LEAVE pCopyHdr;
  1727. IPADDR IPAddress;
  1728. USHORT MinMaxCount;
  1729. BOOLEAN ReflectJoin;
  1730. BOOLEAN HolePunched;
  1731. BOOLEAN RetransmitOnCCVC;
  1732. USHORT Flags;
  1733. UNALIGNED IPADDR * pIPAddress;
  1734. ULONG JoinCopyLength;
  1735. *ppClusterPacket = (PNDIS_PACKET)NULL;
  1736. ReflectJoin = FALSE;
  1737. RetransmitOnCCVC = FALSE;
  1738. GETSHORT2SHORT(&Flags, &JHdr->Flags);
  1739. MARSDBGPRINT(DBG_LEVEL_LOUD,
  1740. ("MarsAddClusterMemberToGroups: pMember %x, Min ", pMember));
  1741. MARSDUMPIPADDR(DBG_LEVEL_LOUD, pGrpAddrRange->MinAddr, ", Max ");
  1742. MARSDUMPIPADDR(DBG_LEVEL_LOUD, pGrpAddrRange->MaxAddr, "\n");
  1743. MARSDUMPMAP(DBG_LEVEL_NOTICE,
  1744. "MARS: Join ", pGrpAddrRange->MinAddr, &pMember->HwAddr.Address);
  1745. do
  1746. {
  1747. //
  1748. // Possible cases:
  1749. //
  1750. // 1. Joining a single group
  1751. // 2. Joining the entire Class D space.
  1752. //
  1753. if ((pGrpAddrRange->MinAddr == MIN_CLASSD_IPADDR_VALUE) &&
  1754. (pGrpAddrRange->MaxAddr == MAX_CLASSD_IPADDR_VALUE))
  1755. {
  1756. IPAddress = IPADDR_FULL_RANGE; // key for entry representing entire range
  1757. }
  1758. else
  1759. {
  1760. IPAddress = pGrpAddrRange->MinAddr;
  1761. }
  1762. //
  1763. // Check if this is a duplicate join of the entire class-D range.
  1764. // The special value, IPADDR_FULL_RANGE is smaller than any valid
  1765. // IP address, so if present it's always the first in
  1766. // pMember->pGroupList
  1767. //
  1768. if ( IPAddress == IPADDR_FULL_RANGE
  1769. && pMember->pGroupList != NULL
  1770. && pMember->pGroupList->pMarsEntry->IPAddress == IPAddress)
  1771. {
  1772. //
  1773. // Yes it is a duplicate join of the entire class-D address space.
  1774. //
  1775. MinMaxCount = 0;
  1776. }
  1777. else
  1778. {
  1779. MarsPunchHoles(
  1780. pGrpAddrRange,
  1781. pMember->pGroupList,
  1782. pIntF,
  1783. NULL,
  1784. &MinMaxCount,
  1785. &HolePunched
  1786. );
  1787. }
  1788. //
  1789. // Check whether the JOIN is a complete duplicate.
  1790. //
  1791. if (MinMaxCount == 0)
  1792. {
  1793. //
  1794. // Duplicate JOIN. Retransmit JOIN back on the VC
  1795. // on which it was received.
  1796. //
  1797. ReflectJoin = TRUE;
  1798. pIntF->MarsStats.DuplicateJoins++;
  1799. //
  1800. // Set PUNCHED to 0 in the received JOIN.
  1801. //
  1802. Flags &= ~JL_FLAGS_PUNCHED;
  1803. PUTSHORT2SHORT(&JHdr->Flags, Flags);
  1804. break;
  1805. }
  1806. // First access the MARS entry representing the
  1807. // Multicast group being joined.
  1808. //
  1809. pMarsEntry = MarsLookupMarsEntry(pIntF, IPAddress, TRUE);
  1810. if (pMarsEntry == NULL_PMARS_ENTRY)
  1811. {
  1812. break;
  1813. }
  1814. pGroup = ALLOC_NP_MEM(sizeof(GROUP_MEMBER), POOL_TAG_MARS);
  1815. if (pGroup == NULL_PGROUP_MEMBER)
  1816. {
  1817. break;
  1818. }
  1819. //
  1820. // stats...
  1821. //
  1822. pIntF->MarsStats.SuccessfulVCMeshJoins++;
  1823. if (IPAddress == IPADDR_FULL_RANGE)
  1824. {
  1825. if (++(pIntF->MarsStats.CurrentPromiscuous) > pIntF->MarsStats.MaxPromiscuous)
  1826. {
  1827. pIntF->MarsStats.MaxPromiscuous = pIntF->MarsStats.CurrentPromiscuous;
  1828. }
  1829. }
  1830. //
  1831. // Fill in the basics for this GROUP_MEMBER.
  1832. //
  1833. pGroup->pMarsEntry = pMarsEntry;
  1834. pGroup->pClusterMember = pMember;
  1835. //
  1836. // Link this GROUP_MEMBER to the MARS Entry.
  1837. //
  1838. pGroup->Prev = &(pMarsEntry->pMembers);
  1839. pGroup->Next = pMarsEntry->pMembers;
  1840. if (pMarsEntry->pMembers != NULL_PGROUP_MEMBER)
  1841. {
  1842. ((PENTRY_HDR)(pGroup->Next))->Prev = &(pGroup->Next);
  1843. }
  1844. pMarsEntry->pMembers = pGroup;
  1845. pMarsEntry->NumMembers++;
  1846. //
  1847. // Stats...
  1848. //
  1849. if ((UINT)pMarsEntry->NumMembers > pIntF->MarsStats.MaxAddressesPerGroup)
  1850. {
  1851. pIntF->MarsStats.MaxAddressesPerGroup = pMarsEntry->NumMembers;
  1852. }
  1853. //
  1854. // Link this GROUP_MEMBER to the CLUSTER_MEMBER. The list
  1855. // is sorted in ascending order of IPAddress.
  1856. // NOTE: This function must not be called if pMember's GROUP_STATE is not ACTIVE.
  1857. //
  1858. ASSERT((MARS_GET_CM_GROUP_STATE(pMember) == CM_GROUP_ACTIVE));
  1859. for (ppGroup = &(pMember->pGroupList);
  1860. *ppGroup != NULL_PGROUP_MEMBER;
  1861. ppGroup = &(*ppGroup)->pNextGroup)
  1862. {
  1863. if ((*ppGroup)->pMarsEntry->IPAddress > IPAddress)
  1864. {
  1865. break;
  1866. }
  1867. }
  1868. pGroup->pNextGroup = *ppGroup;
  1869. *ppGroup = pGroup;
  1870. pMember->NumGroups++;
  1871. //
  1872. // If a single group was being joined, retransmit the JOIN
  1873. // on ClusterControlVc.
  1874. //
  1875. if (pGrpAddrRange->MinAddr == pGrpAddrRange->MaxAddr)
  1876. {
  1877. //
  1878. // Set PUNCHED to 0 in the received JOIN.
  1879. //
  1880. Flags &= ~JL_FLAGS_PUNCHED;
  1881. PUTSHORT2SHORT(&JHdr->Flags, Flags);
  1882. RetransmitOnCCVC = TRUE;
  1883. break;
  1884. }
  1885. //
  1886. // A range of groups were joined. Check whether any holes
  1887. // were punched, i.e., are there any addresses in this
  1888. // range that the member had already joined, or any addresses
  1889. // that are MCS-served.
  1890. //
  1891. if (!HolePunched)
  1892. {
  1893. //
  1894. // All new Join, and no addresses were MCS-served.
  1895. // Retransmit the original JOIN on ClusterControlVc.
  1896. //
  1897. RetransmitOnCCVC = TRUE;
  1898. break;
  1899. }
  1900. //
  1901. // A copy of the JOIN, with the hole-punched list, is to be
  1902. // sent on ClusterControlVc.
  1903. //
  1904. // The copy will contain (MinMaxCount - 1) _additional_ address
  1905. // pairs.
  1906. //
  1907. JoinCopyLength = Length + ((2 * sizeof(IPADDR))*(MinMaxCount - 1));
  1908. *ppClusterPacket = MarsAllocControlPacket(
  1909. pIntF,
  1910. JoinCopyLength,
  1911. (PUCHAR *)&pCopyHdr
  1912. );
  1913. if (*ppClusterPacket == (PNDIS_PACKET)NULL)
  1914. {
  1915. break;
  1916. }
  1917. COPY_MEM((PUCHAR)pCopyHdr, (PUCHAR)JHdr, Length);
  1918. pIPAddress = (UNALIGNED IPADDR *)((PUCHAR)pCopyHdr + Length - (2 * sizeof(IPADDR)));
  1919. MarsPunchHoles(
  1920. pGrpAddrRange,
  1921. pMember->pGroupList,
  1922. pIntF,
  1923. pIPAddress,
  1924. &MinMaxCount,
  1925. &HolePunched
  1926. );
  1927. //
  1928. // Update the JOIN _copy_ that will go on ClusterControlVc.
  1929. //
  1930. PUTSHORT2SHORT(&pCopyHdr->NumGrpAddrPairs, MinMaxCount);
  1931. Flags |= JL_FLAGS_PUNCHED;
  1932. PUTSHORT2SHORT(&pCopyHdr->Flags, Flags);
  1933. //
  1934. // Retransmit the received JOIN on the VC it arrived on, with
  1935. // Hole-punched reset.
  1936. //
  1937. Flags &= ~JL_FLAGS_PUNCHED;
  1938. PUTSHORT2SHORT(&JHdr->Flags, Flags);
  1939. ReflectJoin = TRUE;
  1940. break;
  1941. }
  1942. while (FALSE);
  1943. if (RetransmitOnCCVC)
  1944. {
  1945. ARPS_ASSERT(!ReflectJoin);
  1946. #if 0
  1947. *ppClusterPacket = MarsAllocPacketHdrCopy(Packet);
  1948. #else
  1949. *ppClusterPacket = Packet;
  1950. #endif
  1951. }
  1952. MARSDBGPRINT(DBG_LEVEL_LOUD,
  1953. ("MarsAddClusterMemberToGroups: ClusterPkt %x, RetransmitOnCCVC %d, Reflect %d\n",
  1954. *ppClusterPacket, RetransmitOnCCVC, ReflectJoin));
  1955. return (ReflectJoin);
  1956. }
  1957. VOID
  1958. MarsUnlinkAllGroupsOnClusterMember(
  1959. IN PINTF pIntF,
  1960. IN PCLUSTER_MEMBER pMember
  1961. )
  1962. /*++
  1963. Routine Description:
  1964. Unlink and free all Group structures attached to a Cluster Member.
  1965. ALSO: disable any more groups from being added.
  1966. It is assumed that the caller has acquired the IntF spin lock.
  1967. Arguments:
  1968. pIntF - Ptr to Interface from which this member is to be deleted
  1969. pMember - Ptr to Cluster member
  1970. Return Value:
  1971. None
  1972. --*/
  1973. {
  1974. PGROUP_MEMBER pGroup;
  1975. PGROUP_MEMBER pNextGroup;
  1976. MARSDBGPRINT(DBG_LEVEL_NOTICE,
  1977. ("MarsUnlinkAllGroupsOnClusterMember: pMember %x, GroupList %x\n",
  1978. pMember, pMember->pGroupList));
  1979. //
  1980. // Save for later.
  1981. //
  1982. pGroup = pMember->pGroupList;
  1983. pMember->pGroupList = NULL_PGROUP_MEMBER;
  1984. //
  1985. // Make sure more groups can't be added later.
  1986. //
  1987. MARS_SET_CM_GROUP_STATE(pMember, CM_GROUP_DISABLED);
  1988. //
  1989. // De-link and free all Group structures associated with
  1990. // this cluster member.
  1991. //
  1992. for (NOTHING;
  1993. pGroup != NULL_PGROUP_MEMBER;
  1994. pGroup = pNextGroup)
  1995. {
  1996. pNextGroup = pGroup->pNextGroup;
  1997. //
  1998. // Unlink from MARS cache.
  1999. //
  2000. *(pGroup->Prev) = pGroup->Next;
  2001. if (pGroup->Next != NULL)
  2002. {
  2003. ((PENTRY_HDR)(pGroup->Next))->Prev = pGroup->Prev;
  2004. }
  2005. pGroup->pMarsEntry->NumMembers--;
  2006. pMember->NumGroups--;
  2007. FREE_MEM(pGroup);
  2008. }
  2009. }
  2010. BOOLEAN
  2011. MarsDelClusterMemberFromGroups(
  2012. IN PINTF pIntF,
  2013. IN PCLUSTER_MEMBER pMember,
  2014. IN PMCAST_ADDR_PAIR pGrpAddrRange,
  2015. IN PNDIS_PACKET Packet,
  2016. IN PMARS_JOIN_LEAVE LHdr,
  2017. IN UINT Length,
  2018. OUT PNDIS_PACKET * ppClusterPacket
  2019. )
  2020. /*++
  2021. Routine Description:
  2022. Delete a Cluster Member from membership of the indicated group (or
  2023. group range). This is called on processing a non-deregistration
  2024. LEAVE message.
  2025. It is assumed that the caller has acquired the IntF spin lock.
  2026. Arguments:
  2027. pIntF - Ptr to Interface
  2028. pMember - Ptr to Cluster member
  2029. pGrpAddrRange - Min, Max IP addresses being Left
  2030. Packet - NDIS packet containing the LEAVE
  2031. LHdr - Ptr to incoming LEAVE
  2032. Length - of incoming LEAVE
  2033. ppClusterPacket - Optionally, a packet to be sent out on ClusterControlVc.
  2034. Return Value:
  2035. TRUE if the member was deleted successfully from the indicated groups,
  2036. FALSE otherwise. If we returned TRUE, we also set *pClusterPacket optionally
  2037. to a packet to be sent out on ClusterControlVc.
  2038. --*/
  2039. {
  2040. PGROUP_MEMBER pGroup;
  2041. PGROUP_MEMBER * ppGroup, * ppDelGroup;
  2042. PMCS_ENTRY pMcsEntry;
  2043. PMARS_JOIN_LEAVE pCopyHdr;
  2044. IPADDR IPAddress;
  2045. USHORT MinMaxCount;
  2046. BOOLEAN ReflectLeave;
  2047. BOOLEAN HolePunched;
  2048. BOOLEAN RetransmitOnCCVC;
  2049. BOOLEAN WasBlockJoined;
  2050. BOOLEAN IsMcsServed;
  2051. USHORT Flags;
  2052. UNALIGNED IPADDR * pIPAddress;
  2053. ULONG LeaveCopyLength;
  2054. *ppClusterPacket = NULL;
  2055. RetransmitOnCCVC = FALSE;
  2056. ReflectLeave = FALSE;
  2057. MARSDBGPRINT(DBG_LEVEL_LOUD,
  2058. ("MarsDelClusterMemberFromGroups: pMember %x, Min ", pMember));
  2059. MARSDUMPIPADDR(DBG_LEVEL_LOUD, pGrpAddrRange->MinAddr, ", Max ");
  2060. MARSDUMPIPADDR(DBG_LEVEL_LOUD, pGrpAddrRange->MaxAddr, "\n");
  2061. do
  2062. {
  2063. if (pMember == NULL)
  2064. {
  2065. ReflectLeave = TRUE;
  2066. break;
  2067. }
  2068. GETSHORT2SHORT(&Flags, &LHdr->Flags);
  2069. pMcsEntry = pIntF->pMcsList;
  2070. if ((pGrpAddrRange->MinAddr == MIN_CLASSD_IPADDR_VALUE) &&
  2071. (pGrpAddrRange->MaxAddr == MAX_CLASSD_IPADDR_VALUE))
  2072. {
  2073. IPAddress = IPADDR_FULL_RANGE; // key for entry representing entire range
  2074. }
  2075. else
  2076. {
  2077. IPAddress = pGrpAddrRange->MinAddr;
  2078. }
  2079. //
  2080. // Gather some information:
  2081. // 1. Locate the Group member structure for this IP Address.
  2082. // 2. Check if this Cluster member has Block-Joined the entire multicast range
  2083. //
  2084. ppDelGroup = NULL;
  2085. WasBlockJoined = FALSE;
  2086. for (ppGroup = &(pMember->pGroupList);
  2087. *ppGroup != NULL_PGROUP_MEMBER;
  2088. ppGroup = &((*ppGroup)->pNextGroup))
  2089. {
  2090. //
  2091. // Is this the GROUP_MEMBER to be deleted?
  2092. //
  2093. if ((*ppGroup)->pMarsEntry->IPAddress == IPAddress)
  2094. {
  2095. ppDelGroup = ppGroup;
  2096. }
  2097. //
  2098. // Does this GROUP_MEMBER indicate that the Cluster member
  2099. // has block-joined the entire multicast range?
  2100. //
  2101. if ((*ppGroup)->pMarsEntry->IPAddress == IPADDR_FULL_RANGE)
  2102. {
  2103. WasBlockJoined = TRUE;
  2104. }
  2105. //
  2106. // Do we have all that we are looking for?
  2107. //
  2108. if (ppDelGroup && WasBlockJoined)
  2109. {
  2110. break;
  2111. }
  2112. }
  2113. if (ppDelGroup != NULL)
  2114. {
  2115. PMARS_ENTRY pMarsEntry;
  2116. pGroup = *ppDelGroup;
  2117. //
  2118. // Unlink this GROUP_MEMBER from the CLUSTER_MEMBER.
  2119. //
  2120. *ppDelGroup = (*ppDelGroup)->pNextGroup;
  2121. pMember->NumGroups--;
  2122. //
  2123. // Unlink this GROUP_MEMBER from the MARS_ENTRY.
  2124. //
  2125. *(pGroup->Prev) = pGroup->Next;
  2126. if (pGroup->Next != NULL)
  2127. {
  2128. ((PENTRY_HDR)pGroup->Next)->Prev = pGroup->Prev;
  2129. }
  2130. pMarsEntry = pGroup->pMarsEntry;
  2131. pGroup->pMarsEntry = NULL;
  2132. pMarsEntry->NumMembers--;
  2133. if (pMarsEntry->pMembers == NULL)
  2134. {
  2135. PMARS_ENTRY pNextEntry = (PMARS_ENTRY) pMarsEntry->Next;
  2136. //
  2137. // This mars entry has no more members -- remove it from the
  2138. // hash table and delete it.
  2139. //
  2140. ARPS_ASSERT(pMarsEntry->NumMembers==0);
  2141. pIntF->MarsStats.CurrentGroups--;
  2142. #if 1
  2143. MARSDBGPRINT(DBG_LEVEL_INFO,
  2144. ("MarsLookupMarsEntry: deleting entry %x for IP Addr:", pMarsEntry));
  2145. MARSDUMPIPADDR(DBG_LEVEL_INFO, pMarsEntry->IPAddress, "\n");
  2146. ARPS_ASSERT(*(pMarsEntry->Prev) == pMarsEntry);
  2147. *(pMarsEntry->Prev) = pNextEntry;
  2148. if (pNextEntry != NULL_PMARS_ENTRY)
  2149. {
  2150. ARPS_ASSERT(pNextEntry->Prev == &(pMarsEntry->Next));
  2151. pNextEntry->Prev = pMarsEntry->Prev;
  2152. }
  2153. ArpSFreeBlock(pMarsEntry);
  2154. #endif // 0
  2155. }
  2156. //
  2157. // TODO: Delete group
  2158. //
  2159. #if 1
  2160. FREE_MEM(pGroup);
  2161. #endif
  2162. MARSDUMPMAP(DBG_LEVEL_NOTICE,
  2163. "MARS: Leave ", pGrpAddrRange->MinAddr, &pMember->HwAddr.Address);
  2164. }
  2165. //
  2166. // Check if the range/group being Left is MCS-served.
  2167. //
  2168. IsMcsServed = FALSE;
  2169. for (pMcsEntry = pIntF->pMcsList;
  2170. pMcsEntry != NULL_PMCS_ENTRY;
  2171. pMcsEntry = pMcsEntry->Next)
  2172. {
  2173. if ((pMcsEntry->GrpAddrPair.MinAddr <= pGrpAddrRange->MinAddr) &&
  2174. (pMcsEntry->GrpAddrPair.MaxAddr >= pGrpAddrRange->MaxAddr))
  2175. {
  2176. IsMcsServed = TRUE;
  2177. break;
  2178. }
  2179. }
  2180. if (IPAddress == IPADDR_FULL_RANGE)
  2181. {
  2182. if (!WasBlockJoined)
  2183. {
  2184. //
  2185. // This is an attempt to leave the entire class-D
  2186. // space when in fact it has not joined it (perhaps this is
  2187. // a retransmit of an earlier LEAVE). Reflect it privately.
  2188. //
  2189. ARPS_ASSERT(!ppDelGroup);
  2190. //
  2191. // Reset PUNCHED to 0.
  2192. //
  2193. Flags &= ~JL_FLAGS_PUNCHED;
  2194. PUTSHORT2SHORT(&LHdr->Flags, Flags);
  2195. //
  2196. // Retransmit privately on VC.
  2197. //
  2198. ReflectLeave = TRUE;
  2199. break;
  2200. }
  2201. else
  2202. {
  2203. //
  2204. // This member is truly leaving the entire class-D space.
  2205. //
  2206. pIntF->MarsStats.CurrentPromiscuous--;
  2207. }
  2208. }
  2209. else
  2210. {
  2211. //
  2212. // Single group Leave. Check if this Cluster Member is still
  2213. // block-joined (to the entire Class D range), or if the group
  2214. // being left is served by MCS. In either case, we retransmit
  2215. // the LEAVE privately.
  2216. //
  2217. if (WasBlockJoined || IsMcsServed)
  2218. {
  2219. //
  2220. // Reset PUNCHED to 0.
  2221. //
  2222. Flags &= ~JL_FLAGS_PUNCHED;
  2223. PUTSHORT2SHORT(&LHdr->Flags, Flags);
  2224. //
  2225. // Retransmit privately on VC.
  2226. //
  2227. ReflectLeave = TRUE;
  2228. }
  2229. else
  2230. {
  2231. //
  2232. // Retransmit LEAVE on ClusterControlVc.
  2233. //
  2234. ReflectLeave = FALSE;
  2235. RetransmitOnCCVC = TRUE;
  2236. }
  2237. break;
  2238. }
  2239. //
  2240. // Block Leave: can be only for the "entire Class D space" range.
  2241. // Punch holes: for each group that this Cluster member still has
  2242. // "single joins" to, and for each group that is MCS-served.
  2243. //
  2244. MarsPunchHoles(
  2245. pGrpAddrRange,
  2246. pMember->pGroupList,
  2247. pIntF,
  2248. NULL,
  2249. &MinMaxCount,
  2250. &HolePunched
  2251. );
  2252. if (!HolePunched)
  2253. {
  2254. //
  2255. // No holes were punched, meaning that the Cluster member
  2256. // isn't member anymore of any groups in the LEAVE range,
  2257. // and none of the groups in the range is MCS-served.
  2258. // To propagate this information to all hosts in the Cluster,
  2259. // retransmit the LEAVE on ClusterControlVc.
  2260. //
  2261. RetransmitOnCCVC = TRUE;
  2262. break;
  2263. }
  2264. //
  2265. // One or more holes were punched. The original LEAVE
  2266. // should be transmitted back on the VC it came on, with
  2267. // PUNCHED reset to 0.
  2268. //
  2269. Flags &= ~JL_FLAGS_PUNCHED;
  2270. PUTSHORT2SHORT(&LHdr->Flags, Flags);
  2271. ReflectLeave = TRUE;
  2272. if (MinMaxCount == 0)
  2273. {
  2274. //
  2275. // The holes didn't leave anything left, so there is nothing
  2276. // more to do.
  2277. //
  2278. break;
  2279. }
  2280. //
  2281. // A copy of the LEAVE, with the hole-punched list, is to be
  2282. // sent on ClusterControlVc.
  2283. //
  2284. // The copy will contain (MinMaxCount - 1) _additional_ address
  2285. // pairs.
  2286. //
  2287. LeaveCopyLength = Length + ((2 * sizeof(IPADDR))*(MinMaxCount - 1));
  2288. *ppClusterPacket = MarsAllocControlPacket(
  2289. pIntF,
  2290. LeaveCopyLength,
  2291. (PUCHAR *)&pCopyHdr
  2292. );
  2293. if (*ppClusterPacket == (PNDIS_PACKET)NULL)
  2294. {
  2295. break;
  2296. }
  2297. COPY_MEM((PUCHAR)pCopyHdr, (PUCHAR)LHdr, Length);
  2298. pIPAddress = (UNALIGNED IPADDR *)((PUCHAR)pCopyHdr + Length - (2 * sizeof(IPADDR)));
  2299. MarsPunchHoles(
  2300. pGrpAddrRange,
  2301. pMember->pGroupList,
  2302. pIntF,
  2303. pIPAddress,
  2304. &MinMaxCount,
  2305. &HolePunched
  2306. );
  2307. //
  2308. // Update the LEAVE copy.
  2309. //
  2310. PUTSHORT2SHORT(&pCopyHdr->NumGrpAddrPairs, MinMaxCount);
  2311. Flags |= JL_FLAGS_PUNCHED;
  2312. PUTSHORT2SHORT(&pCopyHdr->Flags, Flags);
  2313. break;
  2314. }
  2315. while (FALSE);
  2316. if (RetransmitOnCCVC)
  2317. {
  2318. ARPS_ASSERT(!ReflectLeave);
  2319. *ppClusterPacket = Packet;
  2320. }
  2321. MARSDBGPRINT(DBG_LEVEL_LOUD,
  2322. ("MarsDelClusterMemberFromGroups: ClusterPkt %x, RetransmitOnCCVC %d, Reflect %d\n",
  2323. *ppClusterPacket, RetransmitOnCCVC, ReflectLeave));
  2324. return (ReflectLeave);
  2325. }
  2326. PNDIS_PACKET
  2327. MarsAllocControlPacket(
  2328. IN PINTF pIntF,
  2329. IN ULONG PacketLength,
  2330. OUT PUCHAR * pPacketStart
  2331. )
  2332. /*++
  2333. Routine Description:
  2334. Allocate and return a packet that can be used to send a MARS control packet.
  2335. Arguments:
  2336. pIntF - Ptr to Interface on which to allocate the packet
  2337. PacketLength - Total length in bytes
  2338. pPacketStart - Place to return pointer to start of allocated packet.
  2339. Return Value:
  2340. Pointer to NDIS packet if successful, NULL otherwise. If successful, we
  2341. also set *pPacketStart to the start of the allocated (contiguous) memory.
  2342. --*/
  2343. {
  2344. PNDIS_PACKET Packet;
  2345. PUCHAR pBuffer;
  2346. PNDIS_BUFFER NdisBuffer;
  2347. NDIS_STATUS Status;
  2348. PPROTOCOL_RESD Resd; // ProtocolReserved part of NDIS packet
  2349. *pPacketStart = NULL;
  2350. Packet = NULL;
  2351. NdisBuffer = NULL;
  2352. do
  2353. {
  2354. //
  2355. // Allocate space for the packet.
  2356. //
  2357. pBuffer = (PUCHAR)ALLOC_NP_MEM(PacketLength, POOL_TAG_MARS);
  2358. if (pBuffer == (PUCHAR)NULL)
  2359. {
  2360. Status = NDIS_STATUS_RESOURCES;
  2361. break;
  2362. }
  2363. //
  2364. // Make this an NDIS buffer.
  2365. //
  2366. NdisAllocateBuffer(&Status,
  2367. &NdisBuffer,
  2368. MarsBufPoolHandle,
  2369. pBuffer,
  2370. PacketLength);
  2371. if (Status != NDIS_STATUS_SUCCESS)
  2372. {
  2373. break;
  2374. }
  2375. //
  2376. // Allocate an NDIS PACKET.
  2377. //
  2378. NdisAllocatePacket(&Status, &Packet, MarsPktPoolHandle);
  2379. if (Status != NDIS_STATUS_SUCCESS)
  2380. {
  2381. break;
  2382. }
  2383. NdisChainBufferAtFront(Packet, NdisBuffer);
  2384. //
  2385. // Fill in the Protocol reserved fields properly:
  2386. //
  2387. Resd = RESD_FROM_PKT(Packet);
  2388. ZERO_MEM(Resd, sizeof(PROTOCOL_RESD));
  2389. Resd->Flags = (RESD_FLAG_MARS_PKT | RESD_FLAG_FREEBUF);
  2390. Resd->PacketStart = pBuffer;
  2391. break;
  2392. }
  2393. while (FALSE);
  2394. if (Status == NDIS_STATUS_SUCCESS)
  2395. {
  2396. *pPacketStart = pBuffer;
  2397. }
  2398. else
  2399. {
  2400. //
  2401. // Undo all that we have done so far.
  2402. //
  2403. if (NdisBuffer != NULL)
  2404. {
  2405. NdisFreeBuffer(NdisBuffer);
  2406. }
  2407. if (pBuffer != (PUCHAR)NULL)
  2408. {
  2409. FREE_MEM(pBuffer);
  2410. }
  2411. }
  2412. if (Packet == NULL)
  2413. {
  2414. MARSDBGPRINT(DBG_LEVEL_ERROR,
  2415. ("MarsAllocControlPacket: FAILED"));
  2416. }
  2417. return(Packet);
  2418. }
  2419. VOID
  2420. MarsFreePacket(
  2421. IN PNDIS_PACKET Packet
  2422. )
  2423. /*++
  2424. Routine Description:
  2425. Free a packet and any associated buffers. Three kinds of packets
  2426. are handled here:
  2427. 1. Copy of a received control packet that has been forwarded. We might
  2428. have queued this for sending on CC VC, but later decided to abort.
  2429. 2. Packet generated by MARS (e.g. MARS_MULTI, hole-punched MARS_JOIN).
  2430. 3. Received multicast data packet that has been forwarded.
  2431. Arguments:
  2432. Packet - Packet to be freed
  2433. Return Value:
  2434. None
  2435. --*/
  2436. {
  2437. PPROTOCOL_RESD Resd; // ProtocolReserved part of NDIS packet
  2438. PNDIS_BUFFER NdisBuffer;
  2439. PUCHAR pBuffer;
  2440. ULONG BufferLength, TotalLength;
  2441. Resd = RESD_FROM_PKT(Packet);
  2442. //
  2443. // 1. Is this a copy of a received MARS control packet?
  2444. //
  2445. if ((Resd->Flags & RESD_FLAG_MARS_PKT) == 0)
  2446. {
  2447. ExInterlockedPushEntrySList(&ArpSPktList,
  2448. &Resd->FreeList,
  2449. &ArpSPktListLock);
  2450. ArpSDereferenceVc(Resd->Vc, FALSE, TRUE);
  2451. }
  2452. else
  2453. //
  2454. // 2. Is this a packet generated by MARS?
  2455. //
  2456. if (Resd->Flags & RESD_FLAG_FREEBUF)
  2457. {
  2458. //
  2459. // Type 1 in Routine Description: everything belongs to MARS
  2460. //
  2461. NdisGetFirstBufferFromPacket(
  2462. Packet,
  2463. &NdisBuffer,
  2464. (PVOID *)&pBuffer,
  2465. &BufferLength,
  2466. &TotalLength
  2467. );
  2468. ARPS_ASSERT(BufferLength == TotalLength);
  2469. FREE_MEM(pBuffer);
  2470. NdisFreeBuffer(NdisBuffer);
  2471. }
  2472. else
  2473. //
  2474. // 3. This must be Multicast data that we forwarded
  2475. //
  2476. {
  2477. //
  2478. // Type 2 in Routine Description: only the first packet header
  2479. // belongs to MARS. The protocol reserved part contains a pointer
  2480. // to the original packet.
  2481. //
  2482. PNDIS_PACKET OriginalPacket;
  2483. OriginalPacket = Resd->OriginalPkt;
  2484. ARPS_ASSERT(OriginalPacket != NULL);
  2485. NdisReturnPackets(&OriginalPacket, 1);
  2486. }
  2487. NdisFreePacket(Packet);
  2488. }
  2489. PNDIS_PACKET
  2490. MarsAllocPacketHdrCopy(
  2491. IN PNDIS_PACKET Packet
  2492. )
  2493. /*++
  2494. Routine Description:
  2495. Given an NDIS packet, allocate a new NDIS_PACKET structure, and make
  2496. this new packet point to the buffer chain in the old one.
  2497. Arguments:
  2498. Packet - Packet to make a linked copy of.
  2499. Return Value:
  2500. Pointer to the newly allocated and initialized packet if successful,
  2501. else NULL.
  2502. --*/
  2503. {
  2504. PNDIS_PACKET PacketCopy;
  2505. NDIS_STATUS Status;
  2506. PPROTOCOL_RESD Resd;
  2507. //
  2508. // Allocate an NDIS PACKET.
  2509. //
  2510. NdisAllocatePacket(&Status, &PacketCopy, MarsPktPoolHandle);
  2511. if (Status == NDIS_STATUS_SUCCESS)
  2512. {
  2513. //
  2514. // Make this new packet point to the buffer chain in the old one.
  2515. //
  2516. PacketCopy->Private.Head = Packet->Private.Head;
  2517. PacketCopy->Private.Tail = Packet->Private.Tail;
  2518. PacketCopy->Private.ValidCounts = FALSE;
  2519. //
  2520. // Fill in the ProtocolReserved part with all information
  2521. // we need when we free this packet later.
  2522. //
  2523. Resd = RESD_FROM_PKT(PacketCopy);
  2524. ZERO_MEM(Resd, sizeof(PROTOCOL_RESD));
  2525. Resd->Flags = RESD_FLAG_MARS_PKT;
  2526. Resd->OriginalPkt = Packet;
  2527. }
  2528. else
  2529. {
  2530. PacketCopy = (PNDIS_PACKET)NULL;
  2531. }
  2532. return (PacketCopy);
  2533. }
  2534. VOID
  2535. MarsSendOnClusterControlVc(
  2536. IN PINTF pIntF,
  2537. IN PNDIS_PACKET Packet OPTIONAL
  2538. )
  2539. /*++
  2540. Routine Description:
  2541. Start sends on ClusterControlVc, if we have the connection active,
  2542. and we have tried to AddParty all cluster members. Otherwise, enqueue
  2543. the (optional) Packet on the Cluster Control Packet queue.
  2544. TBD: Protect this from reentrancy!
  2545. Arguments:
  2546. pIntF - Interface on which this packet is to be sent
  2547. Packet - Packet to be sent
  2548. Return Value:
  2549. None
  2550. --*/
  2551. {
  2552. KIRQL OldIrql;
  2553. NDIS_HANDLE NdisVcHandle;
  2554. PPROTOCOL_RESD Resd;
  2555. PLIST_ENTRY pEntry;
  2556. MARSDBGPRINT(DBG_LEVEL_LOUD,
  2557. ("MarsSendOnCC: pIntF %x/%x, Pkt %x\n", pIntF, pIntF->Flags, Packet));
  2558. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  2559. if (Packet != (PNDIS_PACKET)NULL)
  2560. {
  2561. if (pIntF->NumClusterMembers == 0)
  2562. {
  2563. //
  2564. // No point in queueing this packet.
  2565. //
  2566. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  2567. MarsFreePacket(Packet);
  2568. return;
  2569. }
  2570. //
  2571. // Queue this packet.
  2572. //
  2573. Resd = RESD_FROM_PKT(Packet);
  2574. InsertTailList(&pIntF->CCPacketQueue, &Resd->ReqList);
  2575. }
  2576. //
  2577. // Make sure not more than one thread enters here.
  2578. //
  2579. if (pIntF->Flags & INTF_SENDING_ON_CC_VC)
  2580. {
  2581. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  2582. return;
  2583. }
  2584. pIntF->Flags |= INTF_SENDING_ON_CC_VC;
  2585. //
  2586. // Send now if the PMP connection is made, and we have tried to AddParty
  2587. // all Cluster Members.
  2588. //
  2589. if ((pIntF->ClusterControlVc != NULL_PMARS_VC) &&
  2590. (MARS_GET_VC_CONN_STATE(pIntF->ClusterControlVc) == MVC_CONN_ACTIVE) &&
  2591. (pIntF->CCAddingParties == 0))
  2592. {
  2593. NdisVcHandle = pIntF->ClusterControlVc->NdisVcHandle;
  2594. ARPS_ASSERT(NdisVcHandle != NULL);
  2595. //
  2596. // Send all packets.
  2597. //
  2598. while (!IsListEmpty(&pIntF->CCPacketQueue))
  2599. {
  2600. pEntry = RemoveHeadList(&pIntF->CCPacketQueue);
  2601. ARPS_ASSERT (pEntry != (PLIST_ENTRY)NULL);
  2602. {
  2603. Resd = CONTAINING_RECORD(pEntry, PROTOCOL_RESD, ReqList);
  2604. Packet = CONTAINING_RECORD(Resd, NDIS_PACKET, ProtocolReserved);
  2605. //
  2606. // If this is a MARS Control packet, fill in CSN, and
  2607. // update our Cluster Sequence Number.
  2608. //
  2609. if ((Resd->Flags & RESD_FLAG_FREEBUF) || // Locally generated MARS CTL
  2610. ((Resd->Flags & RESD_FLAG_MARS_PKT) == 0)) // Forwarded MARS CTL
  2611. {
  2612. PULONG pCSN;
  2613. pCSN = (PULONG)(Resd->PacketStart + FIELD_OFFSET(MARS_JOIN_LEAVE, MarsSequenceNumber));
  2614. PUTULONG2ULONG(pCSN, pIntF->CSN);
  2615. pIntF->CSN++;
  2616. }
  2617. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  2618. NDIS_SET_PACKET_STATUS(Packet, NDIS_STATUS_SUCCESS);
  2619. NdisCoSendPackets(NdisVcHandle, &Packet, 1);
  2620. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  2621. }
  2622. }
  2623. }
  2624. pIntF->Flags &= ~INTF_SENDING_ON_CC_VC;
  2625. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  2626. }
  2627. VOID
  2628. MarsFreePacketsQueuedForClusterControlVc(
  2629. IN PINTF pIntF
  2630. )
  2631. /*++
  2632. Routine Description:
  2633. Free any packets queued for sending on ClusterControlVc.
  2634. Arguments:
  2635. pIntF - Ptr to Interface
  2636. Return Value:
  2637. None
  2638. --*/
  2639. {
  2640. KIRQL OldIrql;
  2641. PPROTOCOL_RESD Resd;
  2642. PLIST_ENTRY pEntry;
  2643. PNDIS_PACKET Packet;
  2644. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  2645. while (!IsListEmpty(&pIntF->CCPacketQueue))
  2646. {
  2647. pEntry = RemoveHeadList(&pIntF->CCPacketQueue);
  2648. ARPS_ASSERT (pEntry != (PLIST_ENTRY)NULL);
  2649. Resd = CONTAINING_RECORD(pEntry, PROTOCOL_RESD, ReqList);
  2650. Packet = CONTAINING_RECORD(Resd, NDIS_PACKET, ProtocolReserved);
  2651. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  2652. MarsFreePacket(Packet);
  2653. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  2654. }
  2655. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  2656. }
  2657. BOOLEAN
  2658. MarsDelMemberFromClusterControlVc(
  2659. IN PINTF pIntF,
  2660. IN PCLUSTER_MEMBER pMember,
  2661. IN BOOLEAN fIfLockedOnEntry,
  2662. IN KIRQL OldIrql OPTIONAL
  2663. )
  2664. /*++
  2665. Routine Description:
  2666. Drop a Cluster Member from ClusterControlVc. Handle all three
  2667. possibilities:
  2668. (a) Not connected to ClusterControlVc
  2669. (b) Connection setup (MakeCall or AddParty) in progress
  2670. (c) Connected to ClusterControlVc
  2671. Arguments:
  2672. pIntF - Ptr to Interface
  2673. pMember - Ptr to Cluster Member to be deleted
  2674. fIfLockedOnEntry- If TRUE, IF is locked on entry, else IF is unlocked on entry.
  2675. OldIrql -- Required IFF fIfLockedOnEntry is TRUE. This is the
  2676. Irql to return to.
  2677. Return Value:
  2678. TRUE IFF IF lock was NEVER released and continues to be held.
  2679. FALSE IFF IF lock WAS release AND and is released on exit AND
  2680. there was some change of state that is NOT idempotent.
  2681. Thus, if IF lock is ever released in this function, it MUST be released on on
  2682. exit and the return value MUST be false, AND this must only be done in a
  2683. situation which changes the state of pMember in a non-idempotent way (so calling
  2684. it over and over again will not result in endlessly returning FALSE).
  2685. Why these complexities? To make it safe to call this function while enumerating
  2686. over all members -- check out MarsAbortAllMembers.
  2687. --*/
  2688. {
  2689. NDIS_STATUS Status;
  2690. NDIS_HANDLE NdisVcHandle;
  2691. NDIS_HANDLE NdisPartyHandle;
  2692. BOOLEAN LockReleased;
  2693. MARSDBGPRINT(DBG_LEVEL_NOTICE,
  2694. ("MarsDelMemberFromCCVC: pIntF %x, pMember %x, ConnSt %x, PartyHandle %x\n",
  2695. pIntF, pMember, MARS_GET_CM_CONN_STATE(pMember), pMember->NdisPartyHandle));
  2696. LockReleased = FALSE;
  2697. if (!fIfLockedOnEntry)
  2698. {
  2699. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  2700. }
  2701. if (!MarsIsValidClusterMember(pIntF, pMember))
  2702. {
  2703. //
  2704. // Oops, the member has gone away in the
  2705. // mean time. We silently return.
  2706. //
  2707. MARSDBGPRINT(DBG_LEVEL_NOTICE,
  2708. ("MarsDelMemberFromCCVC: pIntF %x, pMember %x: pMember INVALID!\n",
  2709. pIntF, pMember));
  2710. if (!fIfLockedOnEntry)
  2711. {
  2712. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  2713. return FALSE; // ***** EARLY RETURN *******
  2714. }
  2715. else
  2716. {
  2717. //
  2718. // We shouldn't have an invalid member if the lock is held on entry!
  2719. //
  2720. ARPS_ASSERT(!"INVALID MEMBER WHEN LOCK IS HELD!");
  2721. return TRUE; // ***** EARLY RETURN *******
  2722. }
  2723. }
  2724. switch (MARS_GET_CM_CONN_STATE(pMember))
  2725. {
  2726. case CM_CONN_ACTIVE:
  2727. NdisPartyHandle = pMember->NdisPartyHandle;
  2728. ARPS_ASSERT(NdisPartyHandle != NULL);
  2729. if (pIntF->CCActiveParties + pIntF->CCAddingParties > 1)
  2730. {
  2731. MARS_SET_CM_CONN_STATE(pMember, CM_CONN_CLOSING);
  2732. pIntF->CCActiveParties--;
  2733. pIntF->CCDroppingParties++;
  2734. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  2735. LockReleased = TRUE;
  2736. Status = NdisClDropParty(NdisPartyHandle, NULL, 0);
  2737. if (Status != NDIS_STATUS_PENDING)
  2738. {
  2739. ArpSDropPartyComplete(Status, (NDIS_HANDLE)pMember);
  2740. }
  2741. }
  2742. else
  2743. {
  2744. //
  2745. // This is the last active party. Check if any DropParty()'s are
  2746. // yet to finish.
  2747. //
  2748. #if 0
  2749. if ((pIntF->CCDroppingParties != 0) &&
  2750. (MARS_GET_VC_CONN_STATE(pIntF->ClusterControlVc) !=
  2751. MVC_CONN_CLOSE_RECEIVED))
  2752. #else
  2753. if (pIntF->CCDroppingParties != 0)
  2754. #endif
  2755. {
  2756. //
  2757. // This member will have to wait till all DropParty()s are
  2758. // complete. Mark the ClusterControlVc so that we send
  2759. // a CloseCall() when all DropParty()s are done.
  2760. //
  2761. MARS_SET_VC_CONN_STATE(pIntF->ClusterControlVc, MVC_CONN_NEED_CLOSE);
  2762. }
  2763. else
  2764. {
  2765. //
  2766. // Last active party, and no DropParty pending.
  2767. //
  2768. NdisVcHandle = pIntF->ClusterControlVc->NdisVcHandle;
  2769. MARS_SET_VC_CONN_STATE(pIntF->ClusterControlVc, MVC_CONN_CLOSING);
  2770. MARS_SET_CM_CONN_STATE(pMember, CM_CONN_CLOSING);
  2771. pIntF->CCActiveParties--;
  2772. pIntF->CCDroppingParties++;
  2773. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  2774. LockReleased = TRUE;
  2775. Status = NdisClCloseCall(
  2776. NdisVcHandle,
  2777. NdisPartyHandle,
  2778. NULL,
  2779. 0
  2780. );
  2781. if (Status != NDIS_STATUS_PENDING)
  2782. {
  2783. ArpSCloseCallComplete(
  2784. Status,
  2785. (NDIS_HANDLE)(pIntF->ClusterControlVc),
  2786. (NDIS_HANDLE)pMember
  2787. );
  2788. }
  2789. }
  2790. }
  2791. break;
  2792. case CM_CONN_SETUP_IN_PROGRESS:
  2793. //
  2794. // Mark it so that we'll delete it when the AddParty/MakeCall
  2795. // completes.
  2796. //
  2797. pMember->Flags |= CM_INVALID;
  2798. break;
  2799. case CM_CONN_CLOSING:
  2800. NOTHING;
  2801. break;
  2802. case CM_CONN_IDLE:
  2803. //
  2804. // No connection. Just unlink this from the IntF and free it.
  2805. //
  2806. MarsDeleteClusterMember(pIntF, pMember);
  2807. break;
  2808. default:
  2809. ARPS_ASSERT(FALSE);
  2810. break;
  2811. }
  2812. if (LockReleased)
  2813. {
  2814. return FALSE;
  2815. }
  2816. else
  2817. {
  2818. if (fIfLockedOnEntry)
  2819. {
  2820. return TRUE;
  2821. }
  2822. else
  2823. {
  2824. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  2825. return FALSE;
  2826. }
  2827. }
  2828. }
  2829. VOID
  2830. MarsAddMemberToClusterControlVc(
  2831. IN PINTF pIntF,
  2832. IN PCLUSTER_MEMBER pMember
  2833. )
  2834. /*++
  2835. Routine Description:
  2836. Add a Cluster Member as a party to ClusterControlVc. If this is the
  2837. only (or first) Cluster Member known to us, then place a call to
  2838. this cluster member.
  2839. Arguments:
  2840. pIntF - Ptr to Interface
  2841. pMember - Ptr to Cluster Member to be deleted
  2842. Return Value:
  2843. None
  2844. --*/
  2845. {
  2846. KIRQL OldIrql;
  2847. PMARS_VC pVc=NULL;
  2848. PCO_CALL_PARAMETERS pCallParameters;
  2849. BOOLEAN LockReleased;
  2850. NDIS_HANDLE NdisVcHandle;
  2851. NDIS_HANDLE NdisPartyHandle;
  2852. NDIS_HANDLE ProtocolVcContext;
  2853. NDIS_HANDLE ProtocolPartyContext;
  2854. NDIS_STATUS Status;
  2855. LockReleased = FALSE;
  2856. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  2857. do
  2858. {
  2859. if (MARS_GET_CM_CONN_STATE(pMember) != CM_CONN_IDLE)
  2860. {
  2861. // Get out of here.
  2862. //
  2863. MARSDBGPRINT(DBG_LEVEL_WARN,
  2864. ("AddMemberToCC: pVc %x, pMember %x, Member ConnState %x NOT IDLE\n",
  2865. pVc, pMember, MARS_GET_CM_CONN_STATE(pMember)));
  2866. break;
  2867. }
  2868. pVc = pIntF->ClusterControlVc;
  2869. if (pVc == NULL_PMARS_VC)
  2870. {
  2871. pVc = pIntF->ClusterControlVc = ALLOC_NP_MEM(sizeof(MARS_VC), POOL_TAG_MARS);
  2872. if (pVc == NULL_PMARS_VC)
  2873. {
  2874. MARSDBGPRINT(DBG_LEVEL_FATAL,
  2875. ("AddMemberToCC: Cannot allocate CC Vc!\n"));
  2876. break;
  2877. }
  2878. ZERO_MEM(pVc, sizeof(MARS_VC));
  2879. pVc->pIntF = pIntF;
  2880. pVc->VcType = VC_TYPE_MARS_CC;
  2881. }
  2882. MARSDBGPRINT(DBG_LEVEL_INFO,
  2883. ("AddMemberToCC: pVc %x, pMember %x, ConnState %x\n",
  2884. pVc, pMember, MARS_GET_VC_CONN_STATE(pVc)));
  2885. ProtocolVcContext = (NDIS_HANDLE)pVc;
  2886. ProtocolPartyContext = (NDIS_HANDLE)pMember;
  2887. NdisVcHandle = pVc->NdisVcHandle;
  2888. if (MARS_GET_VC_CONN_STATE(pVc) == MVC_CONN_IDLE)
  2889. {
  2890. if (pVc->NdisVcHandle == NULL)
  2891. {
  2892. Status = NdisCoCreateVc(
  2893. pIntF->NdisBindingHandle,
  2894. pIntF->NdisAfHandle,
  2895. (NDIS_HANDLE)pVc,
  2896. &pVc->NdisVcHandle
  2897. );
  2898. if (Status != NDIS_STATUS_SUCCESS)
  2899. {
  2900. break;
  2901. }
  2902. NdisVcHandle = pVc->NdisVcHandle;
  2903. MARSDBGPRINT(DBG_LEVEL_LOUD,
  2904. ("AddMemberToCC: Created VC, CCVC %x, NdisVcHandle %x\n",
  2905. pVc, pVc->NdisVcHandle));
  2906. }
  2907. pCallParameters = MarsPrepareCallParameters(pIntF, &pMember->HwAddr, TRUE);
  2908. if (pCallParameters == (PCO_CALL_PARAMETERS)NULL)
  2909. {
  2910. break;
  2911. }
  2912. MARS_SET_VC_CONN_STATE(pVc, MVC_CONN_SETUP_IN_PROGRESS);
  2913. MARS_SET_CM_CONN_STATE(pMember, CM_CONN_SETUP_IN_PROGRESS);
  2914. pIntF->CCAddingParties++;
  2915. pIntF->MarsStats.TotalCCVCAddParties++;
  2916. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  2917. LockReleased = TRUE;
  2918. Status = NdisClMakeCall(
  2919. NdisVcHandle,
  2920. pCallParameters,
  2921. ProtocolPartyContext,
  2922. &pMember->NdisPartyHandle
  2923. );
  2924. if (Status != NDIS_STATUS_PENDING)
  2925. {
  2926. ArpSMakeCallComplete(
  2927. Status,
  2928. ProtocolVcContext,
  2929. pMember->NdisPartyHandle,
  2930. pCallParameters
  2931. );
  2932. }
  2933. }
  2934. else if (MARS_GET_VC_CONN_STATE(pVc) == MVC_CONN_ACTIVE)
  2935. {
  2936. pCallParameters = MarsPrepareCallParameters(pIntF, &pMember->HwAddr, FALSE);
  2937. if (pCallParameters == (PCO_CALL_PARAMETERS)NULL)
  2938. {
  2939. break;
  2940. }
  2941. MARS_SET_CM_CONN_STATE(pMember, CM_CONN_SETUP_IN_PROGRESS);
  2942. pIntF->CCAddingParties++;
  2943. pIntF->MarsStats.TotalCCVCAddParties++;
  2944. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  2945. LockReleased = TRUE;
  2946. Status = NdisClAddParty(
  2947. NdisVcHandle,
  2948. ProtocolPartyContext,
  2949. pCallParameters,
  2950. &pMember->NdisPartyHandle
  2951. );
  2952. if (Status != NDIS_STATUS_PENDING)
  2953. {
  2954. ArpSAddPartyComplete(
  2955. Status,
  2956. ProtocolPartyContext,
  2957. pMember->NdisPartyHandle,
  2958. pCallParameters
  2959. );
  2960. }
  2961. }
  2962. else
  2963. {
  2964. //
  2965. // First call in progress.
  2966. //
  2967. NOTHING;
  2968. }
  2969. break;
  2970. }
  2971. while (FALSE);
  2972. if (!LockReleased)
  2973. {
  2974. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  2975. }
  2976. }
  2977. PCO_CALL_PARAMETERS
  2978. MarsPrepareCallParameters(
  2979. IN PINTF pIntF,
  2980. IN PHW_ADDR pHwAddr,
  2981. IN BOOLEAN IsMakeCall
  2982. )
  2983. /*++
  2984. Routine Description:
  2985. Allocate and fill in call parameters for use in a MakeCall(PMP)
  2986. or AddParty.
  2987. Arguments:
  2988. pIntF - Ptr to Interface
  2989. pHwAddr - Points to the Called ATM address and subaddress
  2990. Return Value:
  2991. None
  2992. --*/
  2993. {
  2994. PMARS_FLOW_SPEC pFlowSpec;
  2995. PCO_CALL_PARAMETERS pCallParameters;
  2996. PCO_CALL_MANAGER_PARAMETERS pCallMgrParameters;
  2997. PQ2931_CALLMGR_PARAMETERS pAtmCallMgrParameters;
  2998. //
  2999. // All Info Elements that we need to fill:
  3000. //
  3001. Q2931_IE UNALIGNED * pIe;
  3002. AAL_PARAMETERS_IE UNALIGNED * pAalIe;
  3003. ATM_TRAFFIC_DESCRIPTOR_IE UNALIGNED * pTrafficDescriptor;
  3004. ATM_BROADBAND_BEARER_CAPABILITY_IE UNALIGNED * pBbc;
  3005. ATM_BLLI_IE UNALIGNED * pBlli;
  3006. ATM_QOS_CLASS_IE UNALIGNED * pQos;
  3007. ULONG RequestSize;
  3008. RequestSize = sizeof(CO_CALL_PARAMETERS) +
  3009. sizeof(CO_CALL_MANAGER_PARAMETERS) +
  3010. sizeof(Q2931_CALLMGR_PARAMETERS) +
  3011. (IsMakeCall? MARS_MAKE_CALL_IE_SPACE : MARS_ADD_PARTY_IE_SPACE) +
  3012. 0;
  3013. pCallParameters = (PCO_CALL_PARAMETERS)ALLOC_NP_MEM(RequestSize, POOL_TAG_MARS);
  3014. if (pCallParameters == (PCO_CALL_PARAMETERS)NULL)
  3015. {
  3016. return (pCallParameters);
  3017. }
  3018. pFlowSpec = &(pIntF->CCFlowSpec);
  3019. //
  3020. // Zero out everything
  3021. //
  3022. ZERO_MEM((PUCHAR)pCallParameters, RequestSize);
  3023. //
  3024. // Distribute space amongst the various structures
  3025. //
  3026. pCallMgrParameters = (PCO_CALL_MANAGER_PARAMETERS)
  3027. ((PUCHAR)pCallParameters +
  3028. sizeof(CO_CALL_PARAMETERS));
  3029. //
  3030. // Set pointers to link the above structures together
  3031. //
  3032. pCallParameters->CallMgrParameters = pCallMgrParameters;
  3033. pCallParameters->MediaParameters = (PCO_MEDIA_PARAMETERS)NULL;
  3034. pCallMgrParameters->CallMgrSpecific.ParamType = 0;
  3035. pCallMgrParameters->CallMgrSpecific.Length =
  3036. sizeof(Q2931_CALLMGR_PARAMETERS) +
  3037. (IsMakeCall? MARS_MAKE_CALL_IE_SPACE : MARS_ADD_PARTY_IE_SPACE);
  3038. pAtmCallMgrParameters = (PQ2931_CALLMGR_PARAMETERS)
  3039. pCallMgrParameters->CallMgrSpecific.Parameters;
  3040. pCallParameters->Flags |= MULTIPOINT_VC;
  3041. //
  3042. // Call Manager generic flow parameters:
  3043. //
  3044. pCallMgrParameters->Transmit.TokenRate = (pFlowSpec->SendBandwidth);
  3045. pCallMgrParameters->Transmit.TokenBucketSize = (pFlowSpec->SendMaxSize);
  3046. pCallMgrParameters->Transmit.MaxSduSize = pFlowSpec->SendMaxSize;
  3047. pCallMgrParameters->Transmit.PeakBandwidth = (pFlowSpec->SendBandwidth);
  3048. pCallMgrParameters->Transmit.ServiceType = pFlowSpec->ServiceType;
  3049. //
  3050. // For PMP calls, receive side values are 0's.
  3051. //
  3052. pCallMgrParameters->Receive.ServiceType = pFlowSpec->ServiceType;
  3053. //
  3054. // Q2931 Call Manager Parameters:
  3055. //
  3056. //
  3057. // Called address:
  3058. //
  3059. // TBD: Add Called Subaddress IE in outgoing call.
  3060. //
  3061. pAtmCallMgrParameters->CalledParty = pHwAddr->Address;
  3062. //
  3063. // Calling address:
  3064. //
  3065. pAtmCallMgrParameters->CallingParty = pIntF->ConfiguredAddress;
  3066. //
  3067. // RFC 1755 (Sec 5) says that the following IEs MUST be present in the
  3068. // SETUP message, so fill them all.
  3069. //
  3070. // AAL Parameters
  3071. // Traffic Descriptor (MakeCall only)
  3072. // Broadband Bearer Capability (MakeCall only)
  3073. // Broadband Low Layer Info
  3074. // QoS (MakeCall only)
  3075. //
  3076. //
  3077. // Initialize the Info Element list
  3078. //
  3079. pAtmCallMgrParameters->InfoElementCount = 0;
  3080. pIe = (PQ2931_IE)(pAtmCallMgrParameters->InfoElements);
  3081. //
  3082. // AAL Parameters:
  3083. //
  3084. {
  3085. UNALIGNED AAL5_PARAMETERS *pAal5;
  3086. pIe->IEType = IE_AALParameters;
  3087. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_AAL_PARAMETERS_IE;
  3088. pAalIe = (PAAL_PARAMETERS_IE)pIe->IE;
  3089. pAalIe->AALType = AAL_TYPE_AAL5;
  3090. pAal5 = &(pAalIe->AALSpecificParameters.AAL5Parameters);
  3091. pAal5->ForwardMaxCPCSSDUSize = pFlowSpec->SendMaxSize;
  3092. pAal5->BackwardMaxCPCSSDUSize = pFlowSpec->ReceiveMaxSize;
  3093. }
  3094. pAtmCallMgrParameters->InfoElementCount++;
  3095. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  3096. //
  3097. // Traffic Descriptor:
  3098. //
  3099. if (IsMakeCall)
  3100. {
  3101. pIe->IEType = IE_TrafficDescriptor;
  3102. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_ATM_TRAFFIC_DESCR_IE;
  3103. pTrafficDescriptor = (PATM_TRAFFIC_DESCRIPTOR_IE)pIe->IE;
  3104. if (pFlowSpec->ServiceType == SERVICETYPE_BESTEFFORT)
  3105. {
  3106. pTrafficDescriptor->ForwardTD.PeakCellRateCLP01 =
  3107. BYTES_TO_CELLS(pFlowSpec->SendBandwidth);
  3108. pTrafficDescriptor->BestEffort = TRUE;
  3109. }
  3110. else
  3111. {
  3112. // Predictive/Guaranteed service (we map this to CBR, see BBC below)
  3113. pTrafficDescriptor->ForwardTD.PeakCellRateCLP01 =
  3114. BYTES_TO_CELLS(pFlowSpec->SendBandwidth);
  3115. pTrafficDescriptor->BestEffort = FALSE;
  3116. }
  3117. pAtmCallMgrParameters->InfoElementCount++;
  3118. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  3119. }
  3120. //
  3121. // Broadband Bearer Capability
  3122. //
  3123. if (IsMakeCall)
  3124. {
  3125. pIe->IEType = IE_BroadbandBearerCapability;
  3126. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_ATM_BBC_IE;
  3127. pBbc = (PATM_BROADBAND_BEARER_CAPABILITY_IE)pIe->IE;
  3128. pBbc->BearerClass = BCOB_X;
  3129. pBbc->UserPlaneConnectionConfig = UP_P2P;
  3130. if (pFlowSpec->ServiceType == SERVICETYPE_BESTEFFORT)
  3131. {
  3132. pBbc->TrafficType = TT_NOIND;
  3133. pBbc->TimingRequirements = TR_NOIND;
  3134. pBbc->ClippingSusceptability = CLIP_NOT;
  3135. }
  3136. else
  3137. {
  3138. pBbc->TrafficType = TT_CBR;
  3139. pBbc->TimingRequirements = TR_END_TO_END;
  3140. pBbc->ClippingSusceptability = CLIP_SUS;
  3141. }
  3142. pAtmCallMgrParameters->InfoElementCount++;
  3143. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  3144. }
  3145. //
  3146. // Broadband Lower Layer Information
  3147. //
  3148. pIe->IEType = IE_BLLI;
  3149. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_ATM_BLLI_IE;
  3150. pBlli = (PATM_BLLI_IE)pIe->IE;
  3151. COPY_MEM((PUCHAR)pBlli,
  3152. (PUCHAR)&ArpSDefaultBlli,
  3153. sizeof(ATM_BLLI_IE));
  3154. pAtmCallMgrParameters->InfoElementCount++;
  3155. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  3156. //
  3157. // QoS
  3158. //
  3159. if (IsMakeCall)
  3160. {
  3161. pIe->IEType = IE_QOSClass;
  3162. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_ATM_QOS_IE;
  3163. pQos = (PATM_QOS_CLASS_IE)pIe->IE;
  3164. if (pFlowSpec->ServiceType == SERVICETYPE_BESTEFFORT)
  3165. {
  3166. pQos->QOSClassForward = pQos->QOSClassBackward = 0;
  3167. }
  3168. else
  3169. {
  3170. pQos->QOSClassForward = pQos->QOSClassBackward = 1;
  3171. }
  3172. pAtmCallMgrParameters->InfoElementCount++;
  3173. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  3174. }
  3175. return (pCallParameters);
  3176. }
  3177. BOOLEAN
  3178. MarsSendRedirect(
  3179. IN PINTF pIntF,
  3180. IN PTIMER Timer,
  3181. IN BOOLEAN TimerShuttingDown
  3182. )
  3183. /*++
  3184. Routine Description:
  3185. Send a MARS_REDIRECT on ClusterControlVc, as part of a periodic keepalive
  3186. for Cluster members, unless we are shutting down.
  3187. Arguments:
  3188. pIntF - Ptr to Interface
  3189. Timer - Ptr to timer that went off
  3190. TimerShuttingDown - Indicates whether we are shutting down
  3191. Return Value:
  3192. TRUE iff TimerShuttingDown is FALSE.
  3193. --*/
  3194. {
  3195. ULONG PacketLength;
  3196. PNDIS_PACKET RedirPacket;
  3197. PMARS_REDIRECT_MAP RHdr;
  3198. PATM_ADDRESS pAtmAddress;
  3199. KIRQL OldIrql;
  3200. PUCHAR p;
  3201. INT i;
  3202. BOOLEAN LockAcquired;
  3203. MARSDBGPRINT(DBG_LEVEL_LOUD,
  3204. ("MarsSendRedirect: pIntF %x, Timer %x, ShuttingDown %x\n",
  3205. pIntF, Timer, TimerShuttingDown));
  3206. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  3207. LockAcquired = TRUE;
  3208. if (pIntF->NumAddressesRegd > pIntF->NumAllocedRegdAddresses)
  3209. {
  3210. //
  3211. // 12/22/1998 JosephJ: We shouldn't get here, but we have in the past, hence this assert.
  3212. // I made a change to ArpSCoRequestComplete -- see 12/22/1998 note there -- which should
  3213. // make us never get here.
  3214. ASSERT(!"Redirect: NumRegd>NumAlloced");
  3215. // If somehow we do, we fix up NumAddresesRegd
  3216. //
  3217. pIntF->NumAddressesRegd = pIntF->NumAllocedRegdAddresses;
  3218. }
  3219. if (!TimerShuttingDown)
  3220. {
  3221. PacketLength = sizeof(MARS_REDIRECT_MAP) +
  3222. //
  3223. // Source ATM Address
  3224. //
  3225. pIntF->ConfiguredAddress.NumberOfDigits +
  3226. //
  3227. // List of MARS ATM Addresses =
  3228. // Our configured address + registered addresses
  3229. //
  3230. pIntF->ConfiguredAddress.NumberOfDigits +
  3231. (ATM_ADDRESS_LENGTH * pIntF->NumAddressesRegd);
  3232. ARPS_ASSERT(PacketLength <= pIntF->MaxPacketSize);
  3233. RedirPacket = MarsAllocControlPacket(pIntF, PacketLength, (PUCHAR *)&RHdr);
  3234. if (RedirPacket != (PNDIS_PACKET)NULL)
  3235. {
  3236. ZERO_MEM(RHdr, PacketLength);
  3237. //
  3238. // Fill in the packet.
  3239. //
  3240. COPY_MEM(RHdr, &MarsCntrlHdr, sizeof(MarsCntrlHdr));
  3241. RHdr->Opcode = OP_MARS_REDIRECT_MAP;
  3242. RHdr->TgtAddressTL = ATM_ADDRESS_LENGTH;
  3243. PUTSHORT2SHORT(&(RHdr->NumTgtAddr), 1 + pIntF->NumAddressesRegd);
  3244. p = (PUCHAR)(RHdr + 1);
  3245. //
  3246. // Source ATM Number
  3247. //
  3248. COPY_MEM(p, pIntF->ConfiguredAddress.Address, pIntF->ConfiguredAddress.NumberOfDigits);
  3249. p += pIntF->ConfiguredAddress.NumberOfDigits;
  3250. pAtmAddress = pIntF->RegAddresses;
  3251. for (i = pIntF->NumAddressesRegd;
  3252. i != 0;
  3253. i--)
  3254. {
  3255. ARPS_ASSERT(pAtmAddress->NumberOfDigits <= 20);
  3256. COPY_MEM(p, pAtmAddress->Address, pAtmAddress->NumberOfDigits);
  3257. p += pAtmAddress->NumberOfDigits;
  3258. pAtmAddress++;
  3259. }
  3260. PacketLength = (ULONG)(p - (PUCHAR)RHdr);
  3261. NdisAdjustBufferLength(RedirPacket->Private.Head, PacketLength);
  3262. RedirPacket->Private.ValidCounts = FALSE;
  3263. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  3264. LockAcquired = FALSE;
  3265. MarsSendOnClusterControlVc(pIntF, RedirPacket);
  3266. }
  3267. }
  3268. if (LockAcquired)
  3269. {
  3270. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  3271. }
  3272. return (!TimerShuttingDown);
  3273. }
  3274. VOID
  3275. MarsAbortAllMembers(
  3276. IN PINTF pIntF
  3277. )
  3278. /*++
  3279. Routine Description:
  3280. Abort all Cluster Members on the specified Interface, by removing
  3281. all their group memberships, and dropping them off ClusterControlVc.
  3282. Arguments:
  3283. pIntF - Ptr to Interface
  3284. Return Value:
  3285. None
  3286. --*/
  3287. {
  3288. PCLUSTER_MEMBER pMember = NULL;
  3289. PCLUSTER_MEMBER pNextMember;
  3290. KIRQL OldIrql;
  3291. BOOLEAN fLockPreserved;
  3292. UINT uInitialMembersEnumerated;
  3293. UINT uTotalMembersEnumerated;
  3294. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  3295. //
  3296. // TODO: disable more members from being added.
  3297. //
  3298. //
  3299. // First with the IntF lock held, we go through unlinking groups from
  3300. // all cluster members.
  3301. //
  3302. uInitialMembersEnumerated = 0;
  3303. for (pMember = pIntF->ClusterMembers;
  3304. pMember != NULL_PCLUSTER_MEMBER;
  3305. pMember = (PCLUSTER_MEMBER)pMember->Next)
  3306. {
  3307. uInitialMembersEnumerated++;
  3308. MARSDBGPRINT(DBG_LEVEL_NOTICE,
  3309. ("MarsAbortAllMembers: pIntF %x, Unlinking groups on Cluster Member %x\n",
  3310. pIntF, pMember));
  3311. //
  3312. // Delete all groups from this member
  3313. // AND disable further groups from being added.
  3314. //
  3315. MarsUnlinkAllGroupsOnClusterMember(pIntF, pMember);
  3316. }
  3317. //
  3318. // Then we initiate the deletion of each cluster member.
  3319. //
  3320. uTotalMembersEnumerated = 0;
  3321. do
  3322. {
  3323. fLockPreserved = TRUE;
  3324. if (uTotalMembersEnumerated >
  3325. (uInitialMembersEnumerated*uInitialMembersEnumerated))
  3326. {
  3327. //
  3328. // This really shouldn't happen. In the worst case, we expect
  3329. // total enumerations to be around N*(N-1)/2, where N is
  3330. // uInitialMembersEnumerated.
  3331. // NOTE: the squaring above could theoretically result in an overflow.
  3332. // But we're really not shooting to support 65536 cluster members!
  3333. // If we where, our O(N^2) algorithms will breakdown anyway!
  3334. //
  3335. ASSERT(!"Not making progress deleting members.");
  3336. break;
  3337. }
  3338. for (pMember = pIntF->ClusterMembers;
  3339. pMember != NULL_PCLUSTER_MEMBER;
  3340. pMember = pNextMember)
  3341. {
  3342. pNextMember = (PCLUSTER_MEMBER)pMember->Next;
  3343. uTotalMembersEnumerated++;
  3344. MARSDBGPRINT(DBG_LEVEL_NOTICE,
  3345. ("MarsAbortAllMembers: pIntF %x, Deleting Cluster Member %x\n",
  3346. pIntF, pMember));
  3347. fLockPreserved = MarsDelMemberFromClusterControlVc(
  3348. pIntF,
  3349. pMember,
  3350. TRUE,
  3351. OldIrql
  3352. );
  3353. if (!fLockPreserved)
  3354. {
  3355. //
  3356. // This means that MarsDelMemberFromClusterControlVc has
  3357. // made some non-idempotent change to pMember which has
  3358. // required it to release the pIntF lock.
  3359. //
  3360. // We will re-acquire the lock and start enumeration from scratch.
  3361. //
  3362. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  3363. break;
  3364. }
  3365. }
  3366. } while (!fLockPreserved);
  3367. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  3368. }
  3369. VOID
  3370. MarsStopInterface(
  3371. IN PINTF pIntF
  3372. )
  3373. /*++
  3374. Routine Description:
  3375. Shut down all MARS activity on the specified Interface.
  3376. 1. Free any packets queued for transmission on ClusterControlVc.
  3377. 2. Delete all Cluster Members, and drop them from ClusterControlVc.
  3378. 3. Clean up the MARS cache.
  3379. Arguments:
  3380. pIntF - Ptr to Interface
  3381. Return Value:
  3382. None
  3383. --*/
  3384. {
  3385. PMARS_ENTRY pMarsEntry;
  3386. PMARS_ENTRY pNextMarsEntry;
  3387. ULONG i;
  3388. KIRQL OldIrql;
  3389. MARSDBGPRINT(DBG_LEVEL_NOTICE,
  3390. ("=>MarsStopInterface: pIntF %x, Flags %x, Ref %x\n",
  3391. pIntF, pIntF->Flags, pIntF->RefCount));
  3392. MarsFreePacketsQueuedForClusterControlVc(pIntF);
  3393. //
  3394. // Delete all cluster members.
  3395. //
  3396. MarsAbortAllMembers(pIntF);
  3397. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  3398. if (pIntF->pMcsList != NULL)
  3399. {
  3400. FREE_MEM(pIntF->pMcsList);
  3401. pIntF->pMcsList = NULL;
  3402. }
  3403. //
  3404. // Clean up the MARS cache.
  3405. //
  3406. for (i = 0; i < MARS_TABLE_SIZE; i++)
  3407. {
  3408. // Remove the list at pIntF->MarsCache[i] and nuke all items in it.
  3409. // Be sure to set pIntF->MarsCache[i] to NULL so no one else tries to
  3410. // get to these entries in the mean time.
  3411. //
  3412. pMarsEntry = pIntF->MarsCache[i];
  3413. pIntF->MarsCache[i] = NULL;
  3414. for (;
  3415. pMarsEntry != NULL_PMARS_ENTRY;
  3416. pMarsEntry = pNextMarsEntry)
  3417. {
  3418. pNextMarsEntry = (PMARS_ENTRY)pMarsEntry->Next;
  3419. MARSDBGPRINT(DBG_LEVEL_INFO,
  3420. ("MarsStopIntf: pIntF %x, Freeing MARS Entry %x, IP Addr: ",
  3421. pIntF, pMarsEntry));
  3422. MARSDUMPIPADDR(DBG_LEVEL_INFO, pMarsEntry->IPAddress, "\n");
  3423. ARPS_ASSERT(pMarsEntry->pMembers == NULL_PGROUP_MEMBER);
  3424. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  3425. ArpSFreeBlock(pMarsEntry);
  3426. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  3427. }
  3428. }
  3429. MARSDBGPRINT(DBG_LEVEL_NOTICE,
  3430. ("<=MarsStopInterface: pIntF %x, Flags %x, Ref %x\n",
  3431. pIntF, pIntF->Flags, pIntF->RefCount));
  3432. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  3433. return;
  3434. }
  3435. #if DBG
  3436. VOID
  3437. MarsDumpPacket(
  3438. IN PUCHAR Packet,
  3439. IN UINT PktLen
  3440. )
  3441. {
  3442. UINT i;
  3443. MARSDBGPRINT(DBG_LEVEL_INFO, (" PacketDump: "));
  3444. for (i = 0; i < PktLen; i++)
  3445. {
  3446. MARSDBGPRINT(DBG_LEVEL_INFO+DBG_NO_HDR,
  3447. ("%02x ", Packet[i]));
  3448. }
  3449. MARSDBGPRINT(DBG_LEVEL_INFO+DBG_NO_HDR, ("\n"));
  3450. }
  3451. VOID
  3452. MarsDumpIpAddr(
  3453. IN IPADDR IpAddr,
  3454. IN PCHAR String
  3455. )
  3456. {
  3457. PUCHAR p = (PUCHAR)&IpAddr;
  3458. DbgPrint("%d.%d.%d.%d%s", p[0], p[1], p[2], p[3], String);
  3459. }
  3460. VOID
  3461. MarsDumpAtmAddr(
  3462. IN PATM_ADDRESS AtmAddr,
  3463. IN PCHAR String
  3464. )
  3465. {
  3466. ULONG i;
  3467. ULONG NumOfDigits;
  3468. PUCHAR pSrc, pDst;
  3469. UCHAR AddrString[(ATM_ADDRESS_LENGTH*2) + 1];
  3470. //
  3471. // Prepare the Address string in ASCII
  3472. //
  3473. if ((NumOfDigits = AtmAddr->NumberOfDigits) > ATM_ADDRESS_LENGTH)
  3474. {
  3475. NumOfDigits = ATM_ADDRESS_LENGTH;
  3476. }
  3477. pSrc = AtmAddr->Address;
  3478. pDst = AddrString;
  3479. for (i = 0; i < NumOfDigits; i++, pSrc++)
  3480. {
  3481. *pDst = ((*pSrc) >> 4);
  3482. *pDst += (((*pDst) > 9) ? ('A' - 10) : '0');
  3483. pDst++;
  3484. *pDst = ((*pSrc) & 0x0F);
  3485. *pDst += (((*pDst) > 9) ? ('A' - 10) : '0');
  3486. pDst++;
  3487. }
  3488. *pDst = '\0';
  3489. DbgPrint("%s(%s, %d): %s\n",
  3490. String,
  3491. (AtmAddr->AddressType == ATM_E164) ? "E164" : "NSAP",
  3492. AtmAddr->NumberOfDigits,
  3493. AddrString);
  3494. }
  3495. VOID
  3496. MarsDumpMap(
  3497. IN PCHAR String,
  3498. IN IPADDR IpAddr,
  3499. IN PATM_ADDRESS AtmAddr
  3500. )
  3501. {
  3502. PUCHAR pIpAddrVal = (PUCHAR)&IpAddr;
  3503. DbgPrint("MARS: %s %d.%d.%d.%d : ",
  3504. String,
  3505. ((PUCHAR)pIpAddrVal)[3],
  3506. ((PUCHAR)pIpAddrVal)[2],
  3507. ((PUCHAR)pIpAddrVal)[1],
  3508. ((PUCHAR)pIpAddrVal)[0]
  3509. );
  3510. MarsDumpAtmAddr(AtmAddr, "");
  3511. }
  3512. #endif // DBG
  3513. BOOLEAN
  3514. MarsIsValidClusterMember(
  3515. PINTF pIntF,
  3516. PCLUSTER_MEMBER pPossibleMember
  3517. )
  3518. /*++
  3519. Routine Description:
  3520. Verify that pPossibleMember is a valid member,
  3521. by checking if it is in the list of members.
  3522. pMember COULD be an invalid pointer.
  3523. The interface lock is expected to be held and is not released.
  3524. Arguments:
  3525. pIntF - Ptr to Interface
  3526. pPossibleMember - Ptr to Cluster Member to be validated.
  3527. Return Value:
  3528. TRUE IFF pMember is in the cluster member list.
  3529. --*/
  3530. {
  3531. PCLUSTER_MEMBER pMember;
  3532. for (pMember = pIntF->ClusterMembers;
  3533. pMember != NULL_PCLUSTER_MEMBER;
  3534. pMember = (PCLUSTER_MEMBER)pMember->Next)
  3535. {
  3536. if (pMember == pPossibleMember)
  3537. {
  3538. return TRUE;
  3539. }
  3540. }
  3541. return FALSE;
  3542. }