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

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