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.

2196 lines
58 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. cnpif.c
  5. Abstract:
  6. Interface management routines for the Cluster Network Protocol.
  7. Author:
  8. Mike Massa (mikemas) January 6, 1997
  9. Revision History:
  10. Who When What
  11. -------- -------- ----------------------------------------------
  12. mikemas 01-06-97 created
  13. Notes:
  14. --*/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. #include "cnpif.tmh"
  18. #include <ntddndis.h>
  19. //
  20. // Routines exported within CNP
  21. //
  22. BOOLEAN
  23. CnpIsBetterInterface(
  24. PCNP_INTERFACE Interface1,
  25. PCNP_INTERFACE Interface2
  26. )
  27. {
  28. if ( (Interface2 == NULL)
  29. ||
  30. (Interface1->State > Interface2->State)
  31. ||
  32. ( (Interface1->State == Interface2->State)
  33. &&
  34. CnpIsHigherPriority(Interface1->Priority, Interface2->Priority)
  35. )
  36. )
  37. {
  38. return(TRUE);
  39. }
  40. return(FALSE);
  41. }
  42. VOID
  43. CnpWalkInterfacesOnNode(
  44. PCNP_NODE Node,
  45. PCNP_INTERFACE_UPDATE_ROUTINE UpdateRoutine
  46. )
  47. /*++
  48. Routine Description:
  49. Walks the interface list of a node and performs a specified
  50. operation on each interface.
  51. Arguments:
  52. Node - The node on which to operate.
  53. UpdateRoutine - The operation to perform on each interface.
  54. Return Value:
  55. None.
  56. Notes:
  57. Called with node object lock held.
  58. Valid Update Routines:
  59. CnpOnlinePendingInterfaceWrapper
  60. CnpOfflineInterfaceWrapper
  61. --*/
  62. {
  63. PLIST_ENTRY entry, nextEntry;
  64. PCNP_INTERFACE interface;
  65. CnVerifyCpuLockMask(
  66. CNP_NODE_OBJECT_LOCK, // Required
  67. 0, // Forbidden
  68. CNP_NODE_OBJECT_LOCK_MAX // Maximum
  69. );
  70. entry = Node->InterfaceList.Flink;
  71. while (entry != &(Node->InterfaceList)) {
  72. //
  73. // Save a pointer to the next entry now in case we delete the
  74. // current entry.
  75. //
  76. nextEntry = entry->Flink;
  77. interface = CONTAINING_RECORD(
  78. entry,
  79. CNP_INTERFACE,
  80. NodeLinkage
  81. );
  82. CnAcquireLockAtDpc(&(interface->Network->Lock));
  83. interface->Network->Irql = DISPATCH_LEVEL;
  84. (*UpdateRoutine)(interface);
  85. //
  86. // The network object lock was released.
  87. //
  88. entry = nextEntry;
  89. }
  90. CnVerifyCpuLockMask(
  91. CNP_NODE_OBJECT_LOCK, // Required
  92. 0, // Forbidden
  93. CNP_NODE_OBJECT_LOCK_MAX // Maximum
  94. );
  95. return;
  96. } // CnpWalkInterfacesOnNode
  97. VOID
  98. CnpWalkInterfacesOnNetwork(
  99. PCNP_NETWORK Network,
  100. PCNP_INTERFACE_UPDATE_ROUTINE UpdateRoutine
  101. )
  102. /*++
  103. Routine Description:
  104. Walks the node table and the interface list of each node looking
  105. for interfaces on a specified network. Performs a specified operation
  106. on each matching interface.
  107. Arguments:
  108. Network - The target network.
  109. UpdateRoutine - The operation to perform on each matching interface.
  110. Return Value:
  111. None.
  112. Notes:
  113. Called with no locks held.
  114. Valid Update Routines:
  115. CnpOnlinePendingInterfaceWrapper
  116. CnpOfflineInterfaceWrapper
  117. CnpDeleteInterface
  118. CnpRecalculateInterfacePriority
  119. --*/
  120. {
  121. ULONG i;
  122. CN_IRQL tableIrql;
  123. PCNP_NODE node;
  124. PLIST_ENTRY entry;
  125. PCNP_INTERFACE interface;
  126. CnVerifyCpuLockMask(
  127. 0, // Required
  128. CNP_LOCK_RANGE, // Forbidden
  129. CNP_PRECEEDING_LOCK_RANGE // Maximum
  130. );
  131. CnAcquireLock(&CnpNodeTableLock, &tableIrql);
  132. CnAssert(CnMinValidNodeId != ClusterInvalidNodeId);
  133. CnAssert(CnMaxValidNodeId != ClusterInvalidNodeId);
  134. for (i=CnMinValidNodeId; i <= CnMaxValidNodeId; i++) {
  135. node = CnpNodeTable[i];
  136. if (node != NULL) {
  137. CnAcquireLockAtDpc(&(node->Lock));
  138. CnReleaseLockFromDpc(&CnpNodeTableLock);
  139. node->Irql = tableIrql;
  140. for (entry = node->InterfaceList.Flink;
  141. entry != &(node->InterfaceList);
  142. entry = entry->Flink
  143. )
  144. {
  145. interface = CONTAINING_RECORD(
  146. entry,
  147. CNP_INTERFACE,
  148. NodeLinkage
  149. );
  150. if (interface->Network == Network) {
  151. CnAcquireLockAtDpc(&(Network->Lock));
  152. Network->Irql = DISPATCH_LEVEL;
  153. (*UpdateRoutine)(interface);
  154. //
  155. // The network object lock was released.
  156. // The node object lock is still held.
  157. //
  158. break;
  159. }
  160. }
  161. CnReleaseLock(&(node->Lock), node->Irql);
  162. CnAcquireLock(&CnpNodeTableLock, &tableIrql);
  163. }
  164. }
  165. CnReleaseLock(&CnpNodeTableLock, tableIrql);
  166. CnVerifyCpuLockMask(
  167. 0, // Required
  168. CNP_LOCK_RANGE, // Forbidden
  169. CNP_PRECEEDING_LOCK_RANGE // Maximum
  170. );
  171. return;
  172. } // CnpWalkInterfacesOnNetwork
  173. NTSTATUS
  174. CnpOnlinePendingInterface(
  175. PCNP_INTERFACE Interface
  176. )
  177. /*++
  178. Routine Description:
  179. Changes an Offline interface to the OnlinePending state.
  180. This will enable heartbeats over this interface. When a heartbeat
  181. is established, the interface will move to the Online state.
  182. Arguments:
  183. Interface - A pointer to the interface to change.
  184. Return Value:
  185. An NT status value.
  186. Notes:
  187. Called with associated node and network locks held.
  188. Returns with network lock released.
  189. Conforms to calling convention for PCNP_INTERFACE_UPDATE_ROUTINE.
  190. --*/
  191. {
  192. NTSTATUS status = STATUS_SUCCESS;
  193. PCNP_NODE node = Interface->Node;
  194. PCNP_NETWORK network = Interface->Network;
  195. BOOLEAN networkLocked = TRUE;
  196. CnVerifyCpuLockMask(
  197. (CNP_NODE_OBJECT_LOCK | CNP_NETWORK_OBJECT_LOCK), // Required
  198. 0, // Forbidden
  199. CNP_NETWORK_OBJECT_LOCK_MAX // Maximum
  200. );
  201. if ( (Interface->State == ClusnetInterfaceStateOffline) &&
  202. (network->State == ClusnetNetworkStateOnline) &&
  203. // Place an active reference on the associated network,
  204. // and verify that it is not going away.
  205. (CnpActiveReferenceNetwork(network))
  206. )
  207. {
  208. IF_CNDBG( CN_DEBUG_IFOBJ )
  209. CNPRINT((
  210. "[CNP] Moving interface (%u, %u) to OnlinePending state.\n",
  211. node->Id,
  212. network->Id
  213. ));
  214. Interface->State = ClusnetInterfaceStateOnlinePending;
  215. Interface->MissedHBs = 0;
  216. //
  217. // Update the node's CurrentInterface if appropriate.
  218. //
  219. if ( !CnpIsNetworkRestricted(network) &&
  220. !CnpIsNetworkLocalDisconn(network) &&
  221. CnpIsBetterInterface(Interface, node->CurrentInterface)
  222. )
  223. {
  224. node->CurrentInterface = Interface;
  225. IF_CNDBG( CN_DEBUG_IFOBJ )
  226. CNPRINT((
  227. "[CNP] Network %u is now the best route to node %u\n",
  228. network->Id,
  229. node->Id
  230. ));
  231. if (CnpIsNodeUnreachable(node)) {
  232. CnTrace(
  233. CNP_IF_DETAIL,
  234. CnpTraceOnlinePendingIfReach,
  235. "[CNP] Declaring node %u reachable after "
  236. "setting interface on network %u to online pending.\n",
  237. node->Id, network->Id
  238. );
  239. CnpDeclareNodeReachable(node);
  240. }
  241. }
  242. //
  243. // Clear multicast-received flag and start multicast discovery
  244. // packets.
  245. //
  246. // This call releases the network lock.
  247. //
  248. if (CnpIsNetworkMulticastCapable(network)) {
  249. CnpStartInterfaceMcastTransition(Interface);
  250. networkLocked = FALSE;
  251. }
  252. }
  253. else {
  254. status = STATUS_CLUSTER_INVALID_REQUEST;
  255. }
  256. if (networkLocked) {
  257. CnReleaseLockFromDpc(&(network->Lock));
  258. networkLocked = FALSE;
  259. }
  260. CnVerifyCpuLockMask(
  261. (CNP_NODE_OBJECT_LOCK), // Required
  262. 0, // Forbidden
  263. CNP_NODE_OBJECT_LOCK_MAX // Maximum
  264. );
  265. return(status);
  266. } // CnpOnlinePendingInterface
  267. VOID
  268. CnpOnlinePendingInterfaceWrapper(
  269. PCNP_INTERFACE Interface
  270. )
  271. /*++
  272. Routine Description:
  273. Wrapper for CnpOnlinePendingInterface that conforms to the calling
  274. convention for PCNP_INTERFACE_UPDATE_ROUTINE.
  275. Arguments:
  276. Interface - A pointer to the interface to change.
  277. Return Value:
  278. None.
  279. Notes:
  280. Called with associated node and network locks held.
  281. Returns with network lock released.
  282. --*/
  283. {
  284. (VOID) CnpOnlinePendingInterface(Interface);
  285. return;
  286. } // CnpOnlinePendingInterfaceWrapper
  287. NTSTATUS
  288. CnpOfflineInterface(
  289. PCNP_INTERFACE Interface
  290. )
  291. /*++
  292. Routine Description:
  293. Called to change an interface to the Offline state
  294. when the associated network goes offline or the interface
  295. is being deleted.
  296. Arguments:
  297. Interface - A pointer to the interface to change.
  298. Return Value:
  299. An NT status value.
  300. Notes:
  301. Called with associated node and network locks held.
  302. Returns with network lock released.
  303. Conforms to calling convention for PCNP_INTERFACE_UPDATE_ROUTINE.
  304. --*/
  305. {
  306. NTSTATUS status = STATUS_SUCCESS;
  307. PCNP_NODE node = Interface->Node;
  308. PCNP_NETWORK network = Interface->Network;
  309. CnVerifyCpuLockMask(
  310. (CNP_NODE_OBJECT_LOCK | CNP_NETWORK_OBJECT_LOCK), // Required
  311. 0, // Forbidden
  312. CNP_NETWORK_OBJECT_LOCK_MAX // Maximum
  313. );
  314. if (Interface->State != ClusnetInterfaceStateOffline) {
  315. IF_CNDBG( CN_DEBUG_IFOBJ )
  316. CNPRINT((
  317. "[CNP] Moving interface (%u, %u) to Offline state.\n",
  318. node->Id,
  319. network->Id
  320. ));
  321. Interface->State = ClusnetInterfaceStateOffline;
  322. //
  323. // Release the network lock.
  324. //
  325. CnReleaseLock(&(network->Lock), network->Irql);
  326. //
  327. // Update the node's CurrentInterface value if appropriate.
  328. //
  329. if (node->CurrentInterface == Interface) {
  330. CnpUpdateNodeCurrentInterface(node);
  331. if ( !CnpIsNodeUnreachable(node)
  332. &&
  333. ( (node->CurrentInterface == NULL) ||
  334. ( node->CurrentInterface->State <
  335. ClusnetInterfaceStateOnlinePending
  336. )
  337. )
  338. )
  339. {
  340. //
  341. // This node is now unreachable.
  342. //
  343. CnTrace(
  344. CNP_IF_DETAIL,
  345. CnpTraceOfflineIfUnreach,
  346. "[CNP] Declaring node %u unreachable after "
  347. "taking interface on network %u offline.\n",
  348. node->Id, network->Id
  349. );
  350. CnpDeclareNodeUnreachable(node);
  351. }
  352. }
  353. //
  354. // Change the node's reachability status via this network.
  355. //
  356. CnpMulticastChangeNodeReachability(
  357. network,
  358. node,
  359. FALSE, // not reachable
  360. TRUE, // raise event
  361. NULL // OUT new mask
  362. );
  363. //
  364. // Remove the active reference on the associated network.
  365. // This releases the network lock.
  366. //
  367. CnAcquireLock(&(network->Lock), &(network->Irql));
  368. CnpActiveDereferenceNetwork(network);
  369. }
  370. else {
  371. CnAssert(network->Irql == DISPATCH_LEVEL);
  372. CnReleaseLockFromDpc(&(network->Lock));
  373. status = STATUS_CLUSTER_INVALID_REQUEST;
  374. }
  375. CnVerifyCpuLockMask(
  376. (CNP_NODE_OBJECT_LOCK), // Required
  377. 0, // Forbidden
  378. CNP_NODE_OBJECT_LOCK_MAX // Maximum
  379. );
  380. return(status);
  381. } // CnpOfflineInterface
  382. VOID
  383. CnpOfflineInterfaceWrapper(
  384. PCNP_INTERFACE Interface
  385. )
  386. /*++
  387. Routine Description:
  388. Wrapper for CnpOfflineInterface that conforms to the calling
  389. convention for PCNP_INTERFACE_UPDATE_ROUTINE.
  390. Arguments:
  391. Interface - A pointer to the interface to change.
  392. Return Value:
  393. None.
  394. Notes:
  395. Called with associated node and network locks held.
  396. Returns with network lock released.
  397. --*/
  398. {
  399. (VOID) CnpOfflineInterface(Interface);
  400. return;
  401. } // CnpOfflineInterfaceWrapper
  402. NTSTATUS
  403. CnpOnlineInterface(
  404. PCNP_INTERFACE Interface
  405. )
  406. /*++
  407. Routine Description:
  408. Called to change an OnlinePending interface to the Online state
  409. after a heartbeat has been (re)established.
  410. Arguments:
  411. Interface - A pointer to the interface to change.
  412. Return Value:
  413. None.
  414. Notes:
  415. Called with associated node and network locks held.
  416. Returns with network lock released.
  417. --*/
  418. {
  419. NTSTATUS status = STATUS_SUCCESS;
  420. PCNP_NODE node = Interface->Node;
  421. PCNP_NETWORK network = Interface->Network;
  422. CnVerifyCpuLockMask(
  423. (CNP_NODE_OBJECT_LOCK | CNP_NETWORK_OBJECT_LOCK), // Required
  424. 0, // Forbidden
  425. CNP_NETWORK_OBJECT_LOCK_MAX // Maximum
  426. );
  427. if ( (network->State == ClusnetNetworkStateOnline) &&
  428. ( (Interface->State == ClusnetInterfaceStateOnlinePending) ||
  429. (Interface->State == ClusnetInterfaceStateUnreachable)
  430. )
  431. )
  432. {
  433. IF_CNDBG( CN_DEBUG_IFOBJ )
  434. CNPRINT((
  435. "[CNP] Moving interface (%u, %u) to Online state.\n",
  436. node->Id,
  437. network->Id
  438. ));
  439. //
  440. // Move the interface to the online state.
  441. //
  442. Interface->State = ClusnetInterfaceStateOnline;
  443. CnAssert(network->Irql == DISPATCH_LEVEL);
  444. CnReleaseLockFromDpc(&(network->Lock));
  445. //
  446. // Update the node's CurrentInterface if appropriate.
  447. //
  448. if (!CnpIsNetworkRestricted(network) &&
  449. !CnpIsNetworkLocalDisconn(network) ) {
  450. if (CnpIsBetterInterface(Interface, node->CurrentInterface)) {
  451. node->CurrentInterface = Interface;
  452. IF_CNDBG( CN_DEBUG_IFOBJ )
  453. CNPRINT((
  454. "[CNP] Network %u is now the best route to node %u\n",
  455. network->Id,
  456. node->Id
  457. ));
  458. }
  459. if (CnpIsNodeUnreachable(node)) {
  460. CnTrace(
  461. CNP_IF_DETAIL,
  462. CnpTraceOnlineIfReach,
  463. "[CNP] Declaring node %u reachable after "
  464. "bring interface on network %u online.\n",
  465. node->Id, network->Id
  466. );
  467. CnpDeclareNodeReachable(node);
  468. }
  469. }
  470. }
  471. else {
  472. CnAssert(network->Irql == DISPATCH_LEVEL);
  473. CnReleaseLockFromDpc(&(network->Lock));
  474. status = STATUS_CLUSTER_INVALID_REQUEST;
  475. }
  476. CnVerifyCpuLockMask(
  477. (CNP_NODE_OBJECT_LOCK), // Required
  478. 0, // Forbidden
  479. CNP_NODE_OBJECT_LOCK_MAX // Maximum
  480. );
  481. return(status);
  482. } // CnpOnlineInterface
  483. NTSTATUS
  484. CnpFailInterface(
  485. PCNP_INTERFACE Interface
  486. )
  487. /*++
  488. Routine Description:
  489. Called to change an Online or OnlinePending interface to the Failed
  490. state after the heartbeat has been lost for some time.
  491. Arguments:
  492. Interface - A pointer to the interface to change.
  493. Return Value:
  494. None.
  495. Notes:
  496. Called with associated node and network locks held.
  497. Returns with network lock released.
  498. --*/
  499. {
  500. NTSTATUS status = STATUS_SUCCESS;
  501. PCNP_NODE node = Interface->Node;
  502. PCNP_NETWORK network = Interface->Network;
  503. CnVerifyCpuLockMask(
  504. (CNP_NODE_OBJECT_LOCK | CNP_NETWORK_OBJECT_LOCK), // Required
  505. 0, // Forbidden
  506. CNP_NETWORK_OBJECT_LOCK_MAX // Maximum
  507. );
  508. if ( (network->State == ClusnetNetworkStateOnline) &&
  509. (Interface->State >= ClusnetInterfaceStateOnlinePending)
  510. )
  511. {
  512. IF_CNDBG( CN_DEBUG_IFOBJ )
  513. CNPRINT((
  514. "[CNP] Moving interface (%u, %u) to Failed state.\n",
  515. node->Id,
  516. network->Id
  517. ));
  518. Interface->State = ClusnetInterfaceStateUnreachable;
  519. //
  520. // Clear the multicast received flag so that we "rediscover"
  521. // multicast if ever this interface comes back up.
  522. //
  523. if (Interface->Node != CnpLocalNode) {
  524. CnpInterfaceClearReceivedMulticast(Interface);
  525. }
  526. CnAssert(network->Irql == DISPATCH_LEVEL);
  527. //
  528. // Reference the network so that it can't be deleted
  529. // while we release the lock.
  530. //
  531. CnpReferenceNetwork(network);
  532. CnReleaseLockFromDpc(&(network->Lock));
  533. //
  534. // Update the node's CurrentInterface value if appropriate.
  535. //
  536. if (node->CurrentInterface == Interface) {
  537. CnpUpdateNodeCurrentInterface(node);
  538. if ( (node->CurrentInterface == NULL)
  539. ||
  540. ( node->CurrentInterface->State <
  541. ClusnetInterfaceStateOnlinePending
  542. )
  543. )
  544. {
  545. //
  546. // This node is now unreachable.
  547. //
  548. CnTrace(
  549. CNP_IF_DETAIL,
  550. CnpTraceFailIfUnreach,
  551. "[CNP] Declaring node %u unreachable after "
  552. "marking interface on network %u failed.\n",
  553. node->Id, network->Id
  554. );
  555. CnpDeclareNodeUnreachable(node);
  556. }
  557. }
  558. //
  559. // Change the node's reachability status via this network.
  560. //
  561. CnpMulticastChangeNodeReachability(
  562. network,
  563. node,
  564. FALSE, // not reachable
  565. TRUE, // raise event
  566. NULL // OUT new mask
  567. );
  568. //
  569. // Drop the network reference. This releases the network
  570. // lock.
  571. //
  572. CnAcquireLock(&(network->Lock), &(network->Irql));
  573. CnpDereferenceNetwork(network);
  574. }
  575. else {
  576. CnAssert(network->Irql == DISPATCH_LEVEL);
  577. CnReleaseLockFromDpc(&(network->Lock));
  578. status = STATUS_CLUSTER_INVALID_REQUEST;
  579. }
  580. CnVerifyCpuLockMask(
  581. (CNP_NODE_OBJECT_LOCK), // Required
  582. 0, // Forbidden
  583. CNP_NODE_OBJECT_LOCK_MAX // Maximum
  584. );
  585. return(status);
  586. } // CnpFailInterface
  587. VOID
  588. CnpDeleteInterface(
  589. IN PCNP_INTERFACE Interface
  590. )
  591. /*++
  592. /*++
  593. Routine Description:
  594. Called to delete an interface.
  595. Arguments:
  596. Interface - A pointer to the interface to delete.
  597. Return Value:
  598. None.
  599. Notes:
  600. Called with node and network object locks held.
  601. Returns with the network lock released.
  602. Conforms to calling convention for PCNP_INTERFACE_UPDATE_ROUTINE.
  603. --*/
  604. {
  605. CL_NODE_ID nodeId = Interface->Node->Id;
  606. CL_NETWORK_ID networkId = Interface->Network->Id;
  607. PCNP_NODE node = Interface->Node;
  608. PCNP_NETWORK network = Interface->Network;
  609. BOOLEAN isLocal = FALSE;
  610. CnVerifyCpuLockMask(
  611. (CNP_NODE_OBJECT_LOCK | CNP_NETWORK_OBJECT_LOCK), // Required
  612. 0, // Forbidden
  613. CNP_NETWORK_OBJECT_LOCK_MAX // Maximum
  614. );
  615. IF_CNDBG( CN_DEBUG_IFOBJ )
  616. CNPRINT((
  617. "[CNP] Deleting interface (%u, %u)\n",
  618. nodeId,
  619. networkId
  620. ));
  621. if (Interface->State >= ClusnetInterfaceStateUnreachable) {
  622. (VOID) CnpOfflineInterface(Interface);
  623. //
  624. // The call released the network lock.
  625. // Reacquire it.
  626. //
  627. CnAcquireLockAtDpc(&(network->Lock));
  628. network->Irql = DISPATCH_LEVEL;
  629. }
  630. //
  631. // Remove the interface from the node's interface list.
  632. //
  633. #if DBG
  634. {
  635. PLIST_ENTRY entry;
  636. PCNP_INTERFACE oldInterface = NULL;
  637. for (entry = node->InterfaceList.Flink;
  638. entry != &(node->InterfaceList);
  639. entry = entry->Flink
  640. )
  641. {
  642. oldInterface = CONTAINING_RECORD(
  643. entry,
  644. CNP_INTERFACE,
  645. NodeLinkage
  646. );
  647. if (oldInterface == Interface) {
  648. break;
  649. }
  650. }
  651. CnAssert(oldInterface == Interface);
  652. }
  653. #endif // DBG
  654. RemoveEntryList(&(Interface->NodeLinkage));
  655. //
  656. // Remove the base reference that this node had on the network.
  657. // This releases the network lock.
  658. //
  659. CnpDereferenceNetwork(network);
  660. //
  661. // Update the node's CurrentInterface if appropriate.
  662. //
  663. if (node->CurrentInterface == Interface) {
  664. if (IsListEmpty(&(node->InterfaceList))) {
  665. node->CurrentInterface = NULL;
  666. }
  667. else {
  668. CnpUpdateNodeCurrentInterface(node);
  669. }
  670. }
  671. CnFreePool(Interface);
  672. IF_CNDBG( CN_DEBUG_IFOBJ )
  673. CNPRINT((
  674. "[CNP] Deleted interface (%u, %u)\n",
  675. nodeId,
  676. networkId
  677. ));
  678. CnVerifyCpuLockMask(
  679. (CNP_NODE_OBJECT_LOCK), // Required
  680. 0, // Forbidden
  681. CNP_NODE_OBJECT_LOCK_MAX // Maximum
  682. );
  683. return;
  684. } // CnpDeleteInterface
  685. VOID
  686. CnpReevaluateInterfaceRole(
  687. IN PCNP_INTERFACE Interface
  688. )
  689. /*++
  690. Routine Description:
  691. Reevaluates the role of an interface after the corresponding network's
  692. restriction state has been changed.
  693. Arguments:
  694. Interface - A pointer to the interface on which to operate.
  695. Return Value:
  696. None.
  697. Notes:
  698. Called with associated node and network locks held.
  699. Returns with network lock released.
  700. Conforms to calling convention for PCNP_INTERFACE_UPDATE_ROUTINE.
  701. --*/
  702. {
  703. PCNP_NODE node = Interface->Node;
  704. PCNP_NETWORK network = Interface->Network;
  705. BOOLEAN restricted = CnpIsNetworkRestricted(network);
  706. CnVerifyCpuLockMask(
  707. (CNP_NODE_OBJECT_LOCK | CNP_NETWORK_OBJECT_LOCK), // Required
  708. 0, // Forbidden
  709. CNP_NETWORK_OBJECT_LOCK_MAX // Maximum
  710. );
  711. //
  712. // We don't really need the network lock. It's just part of
  713. // the calling convention.
  714. //
  715. CnReleaseLockFromDpc(&(network->Lock));
  716. if (restricted) {
  717. if (node->CurrentInterface == Interface) {
  718. CnpUpdateNodeCurrentInterface(node);
  719. }
  720. }
  721. else if (node->CurrentInterface != Interface) {
  722. CnpUpdateNodeCurrentInterface(node);
  723. }
  724. if (node->CurrentInterface == NULL && !CnpIsNodeUnreachable(node)) {
  725. //
  726. // This node is now unreachable.
  727. //
  728. CnTrace(
  729. CNP_IF_DETAIL,
  730. CnpTraceEvalRoleUnreach,
  731. "[CNP] Declaring node %u unreachable after "
  732. "evaluating role of interface on network %u.\n",
  733. node->Id, network->Id
  734. );
  735. CnpDeclareNodeUnreachable(node);
  736. } else if (node->CurrentInterface != NULL && CnpIsNodeUnreachable(node)) {
  737. //
  738. // This node may now be reachable.
  739. //
  740. CnTrace(
  741. CNP_IF_DETAIL,
  742. CnpTraceEvalRoleReach,
  743. "[CNP] Declaring node %u reachable after "
  744. "evaluating role of interface on network %u.\n",
  745. node->Id, network->Id
  746. );
  747. CnpDeclareNodeReachable(node);
  748. }
  749. CnVerifyCpuLockMask(
  750. (CNP_NODE_OBJECT_LOCK), // Required
  751. 0, // Forbidden
  752. CNP_NODE_OBJECT_LOCK_MAX // Maximum
  753. );
  754. return;
  755. } // CnpReevaluateInterfaceRole
  756. VOID
  757. CnpRecalculateInterfacePriority(
  758. IN PCNP_INTERFACE Interface
  759. )
  760. /*++
  761. Routine Description:
  762. Recalculates the priority of interfaces which get their
  763. priority from their associated network. Called after the network's
  764. priority changes.
  765. Arguments:
  766. Interface - A pointer to the interface on which to operate.
  767. Return Value:
  768. None.
  769. Notes:
  770. Called with associated node and network locks held.
  771. Returns with network lock released.
  772. Conforms to calling convention for PCNP_INTERFACE_UPDATE_ROUTINE.
  773. --*/
  774. {
  775. PCNP_NODE node = Interface->Node;
  776. PCNP_NETWORK network = Interface->Network;
  777. ULONG networkPriority = network->Priority;
  778. ULONG oldPriority = Interface->Priority;
  779. BOOLEAN restricted = CnpIsNetworkRestricted(network);
  780. BOOLEAN localDisconn = CnpIsNetworkLocalDisconn(network);
  781. CnVerifyCpuLockMask(
  782. (CNP_NODE_OBJECT_LOCK | CNP_NETWORK_OBJECT_LOCK), // Required
  783. 0, // Forbidden
  784. CNP_NETWORK_OBJECT_LOCK_MAX // Maximum
  785. );
  786. //
  787. // We don't really need the network lock. It's just part of
  788. // the calling convention.
  789. //
  790. CnReleaseLockFromDpc(&(network->Lock));
  791. if (CnpIsInterfaceUsingNetworkPriority(Interface)) {
  792. Interface->Priority = networkPriority;
  793. if (!restricted) {
  794. if (Interface == node->CurrentInterface) {
  795. if (CnpIsLowerPriority(Interface->Priority, oldPriority)) {
  796. //
  797. // Our priority got worse. Recalculate the best route.
  798. //
  799. CnpUpdateNodeCurrentInterface(node);
  800. }
  801. //
  802. // Else, priority same or better. Nothing to do.
  803. //
  804. }
  805. else if ( !localDisconn &&
  806. CnpIsBetterInterface(
  807. Interface,
  808. node->CurrentInterface
  809. )
  810. )
  811. {
  812. //
  813. // Our priority got better.
  814. //
  815. IF_CNDBG(( CN_DEBUG_NODEOBJ | CN_DEBUG_NETOBJ ))
  816. CNPRINT((
  817. "[CNP] Network %u is now the best route to node %u\n",
  818. network->Id,
  819. node->Id
  820. ));
  821. node->CurrentInterface = Interface;
  822. }
  823. }
  824. }
  825. CnVerifyCpuLockMask(
  826. (CNP_NODE_OBJECT_LOCK), // Required
  827. 0, // Forbidden
  828. CNP_NODE_OBJECT_LOCK_MAX // Maximum
  829. );
  830. return;
  831. } // CnpRecalculateInterfacePriority
  832. VOID
  833. CnpUpdateNodeCurrentInterface(
  834. IN PCNP_NODE Node
  835. )
  836. /*++
  837. Routine Description:
  838. Called to determine the best available interface for a node
  839. after one of its interfaces changes state or priority.
  840. Arguments:
  841. Node - A pointer to the node on which to operate.
  842. Return Value:
  843. None.
  844. Notes:
  845. Called with node object lock held.
  846. --*/
  847. {
  848. PLIST_ENTRY entry;
  849. PCNP_INTERFACE interface;
  850. PCNP_INTERFACE bestInterface = NULL;
  851. CnVerifyCpuLockMask(
  852. CNP_NODE_OBJECT_LOCK, // Required
  853. 0, // Forbidden
  854. CNP_NODE_OBJECT_LOCK_MAX // Maximum
  855. );
  856. CnAssert(!IsListEmpty(&(Node->InterfaceList)));
  857. // CnAssert(Node->CurrentInterface != NULL);
  858. for (entry = Node->InterfaceList.Flink;
  859. entry != &(Node->InterfaceList);
  860. entry = entry->Flink
  861. )
  862. {
  863. interface = CONTAINING_RECORD(entry, CNP_INTERFACE, NodeLinkage);
  864. if ( !CnpIsNetworkRestricted(interface->Network) &&
  865. !CnpIsNetworkLocalDisconn(interface->Network) &&
  866. CnpIsBetterInterface(interface, bestInterface)
  867. )
  868. {
  869. bestInterface = interface;
  870. }
  871. }
  872. Node->CurrentInterface = bestInterface;
  873. IF_CNDBG(( CN_DEBUG_NODEOBJ | CN_DEBUG_NETOBJ )) {
  874. if (bestInterface == NULL) {
  875. CNPRINT((
  876. "[CNP] No route for node %u!!!!\n",
  877. Node->Id
  878. ));
  879. }
  880. else {
  881. CNPRINT((
  882. "[CNP] Best route for node %u is now network %u.\n",
  883. Node->Id,
  884. bestInterface->Network->Id
  885. ));
  886. }
  887. }
  888. CnVerifyCpuLockMask(
  889. CNP_NODE_OBJECT_LOCK, // Required
  890. 0, // Forbidden
  891. CNP_NODE_OBJECT_LOCK_MAX // Maximum
  892. );
  893. return;
  894. } // CnpUpdateNodeCurrentInterface
  895. VOID
  896. CnpResetAndOnlinePendingInterface(
  897. IN PCNP_INTERFACE Interface
  898. )
  899. /*++
  900. Routine Description:
  901. Resets the sequence numbers used to authenticate packets
  902. sent by a node over a particular network. Also takes the
  903. node's interface online.
  904. This operation is performed when a node is joining a cluster.
  905. Arguments:
  906. Interface - A pointer to the interface on which to operate.
  907. Return Value:
  908. None.
  909. Notes:
  910. Called with associated node and network locks held.
  911. Returns with network lock released.
  912. Conforms to calling convention for PCNP_INTERFACE_UPDATE_ROUTINE.
  913. --*/
  914. {
  915. PCNP_NODE node = Interface->Node;
  916. PCNP_NETWORK network = Interface->Network;
  917. CnVerifyCpuLockMask(
  918. (CNP_NODE_OBJECT_LOCK | CNP_NETWORK_OBJECT_LOCK), // Required
  919. 0, // Forbidden
  920. CNP_NETWORK_OBJECT_LOCK_MAX // Maximum
  921. );
  922. IF_CNDBG(( CN_DEBUG_NODEOBJ | CN_DEBUG_NETOBJ ))
  923. CNPRINT((
  924. "[CNP] Reseting sequence numbers for node %u on network %u\n",
  925. node->Id,
  926. network->Id
  927. ));
  928. Interface->SequenceToSend = 0;
  929. Interface->LastSequenceReceived = 0;
  930. //
  931. // Take the interface online.
  932. //
  933. (VOID) CnpOnlinePendingInterface(Interface);
  934. CnVerifyCpuLockMask(
  935. (CNP_NODE_OBJECT_LOCK), // Required
  936. 0, // Forbidden
  937. CNP_NODE_OBJECT_LOCK_MAX // Maximum
  938. );
  939. return;
  940. } // CnpRecalculateInterfacePriority
  941. NTSTATUS
  942. CnpFindInterface(
  943. IN CL_NODE_ID NodeId,
  944. IN CL_NETWORK_ID NetworkId,
  945. OUT PCNP_INTERFACE * Interface
  946. )
  947. {
  948. NTSTATUS status;
  949. PCNP_INTERFACE interface;
  950. PCNP_NODE node;
  951. PCNP_NETWORK network;
  952. PLIST_ENTRY entry;
  953. CnVerifyCpuLockMask(
  954. 0, // Required
  955. 0, // Forbidden
  956. CNP_PRECEEDING_LOCK_RANGE // Maximum
  957. );
  958. status = CnpValidateAndFindNode(NodeId, &node);
  959. if (status == STATUS_SUCCESS) {
  960. network = CnpFindNetwork(NetworkId);
  961. if (network != NULL) {
  962. for (entry = node->InterfaceList.Flink;
  963. entry != &(node->InterfaceList);
  964. entry = entry->Flink
  965. )
  966. {
  967. interface = CONTAINING_RECORD(
  968. entry,
  969. CNP_INTERFACE,
  970. NodeLinkage
  971. );
  972. if (interface->Network == network) {
  973. *Interface = interface;
  974. CnVerifyCpuLockMask(
  975. (CNP_NODE_OBJECT_LOCK | CNP_NETWORK_OBJECT_LOCK),
  976. 0, // Forbidden
  977. CNP_NETWORK_OBJECT_LOCK_MAX // Maximum
  978. );
  979. return(STATUS_SUCCESS);
  980. }
  981. }
  982. CnReleaseLock(&(network->Lock), network->Irql);
  983. }
  984. CnReleaseLock(&(node->Lock), node->Irql);
  985. }
  986. CnVerifyCpuLockMask(
  987. 0, // Required
  988. 0, // Forbidden
  989. CNP_PRECEEDING_LOCK_RANGE // Maximum
  990. );
  991. return(STATUS_CLUSTER_NETINTERFACE_NOT_FOUND);
  992. } // CnpFindInterface
  993. //
  994. // Cluster Transport Public Routines
  995. //
  996. NTSTATUS
  997. CxRegisterInterface(
  998. CL_NODE_ID NodeId,
  999. CL_NETWORK_ID NetworkId,
  1000. ULONG Priority,
  1001. PUWSTR AdapterId,
  1002. ULONG AdapterIdLength,
  1003. ULONG TdiAddressLength,
  1004. PTRANSPORT_ADDRESS TdiAddress,
  1005. PULONG MediaStatus
  1006. )
  1007. {
  1008. NTSTATUS status;
  1009. PLIST_ENTRY entry;
  1010. PCNP_INTERFACE interface;
  1011. PCNP_NODE node;
  1012. PCNP_NETWORK network;
  1013. ULONG allocSize;
  1014. PWCHAR adapterDevNameBuffer = NULL;
  1015. HANDLE adapterDevHandle = NULL;
  1016. BOOLEAN localAdapter = FALSE;
  1017. CnVerifyCpuLockMask(
  1018. 0, // Required
  1019. 0xFFFFFFFF, // Forbidden
  1020. 0 // Maximum
  1021. );
  1022. //
  1023. // Allocate and initialize an interface object.
  1024. //
  1025. allocSize = FIELD_OFFSET(CNP_INTERFACE, TdiAddress) + TdiAddressLength;
  1026. interface = CnAllocatePool(allocSize);
  1027. if (interface == NULL) {
  1028. return(STATUS_INSUFFICIENT_RESOURCES);
  1029. }
  1030. RtlZeroMemory(interface, allocSize);
  1031. CN_INIT_SIGNATURE(interface, CNP_INTERFACE_SIG);
  1032. interface->State = ClusnetInterfaceStateOffline;
  1033. RtlMoveMemory(&(interface->TdiAddress), TdiAddress, TdiAddressLength);
  1034. interface->TdiAddressLength = TdiAddressLength;
  1035. //
  1036. // Register the new interface object
  1037. //
  1038. status = CnpValidateAndFindNode(NodeId, &node);
  1039. if (NT_SUCCESS(status)) {
  1040. //
  1041. // If this adapter is on the local node, use the adapter ID
  1042. // to find the corresponding WMI Provider ID.
  1043. //
  1044. localAdapter = (BOOLEAN)(node == CnpLocalNode);
  1045. if (localAdapter) {
  1046. PWCHAR adapterDevNamep, brace;
  1047. PFILE_OBJECT adapterFileObject;
  1048. PDEVICE_OBJECT adapterDeviceObject;
  1049. // first drop the node lock
  1050. CnReleaseLock(&(node->Lock), node->Irql);
  1051. // allocate a buffer for the adapter device name
  1052. allocSize = wcslen(L"\\Device\\") * sizeof(WCHAR)
  1053. + AdapterIdLength
  1054. + sizeof(UNICODE_NULL);
  1055. brace = L"{";
  1056. if (*((PWCHAR)AdapterId) != *brace) {
  1057. allocSize += 2 * sizeof(WCHAR);
  1058. }
  1059. adapterDevNameBuffer = CnAllocatePool(allocSize);
  1060. if (adapterDevNameBuffer == NULL) {
  1061. status = STATUS_INSUFFICIENT_RESOURCES;
  1062. goto error_exit;
  1063. }
  1064. // build the adapter device name from the adapter ID
  1065. RtlZeroMemory(adapterDevNameBuffer, allocSize);
  1066. adapterDevNamep = adapterDevNameBuffer;
  1067. RtlCopyMemory(
  1068. adapterDevNamep,
  1069. L"\\Device\\",
  1070. wcslen(L"\\Device\\") * sizeof(WCHAR)
  1071. );
  1072. adapterDevNamep += wcslen(L"\\Device\\");
  1073. if (*((PWCHAR)AdapterId) != *brace) {
  1074. *adapterDevNamep = *brace;
  1075. adapterDevNamep++;
  1076. }
  1077. RtlCopyMemory(adapterDevNamep, AdapterId, AdapterIdLength);
  1078. if (*((PWCHAR)AdapterId) != *brace) {
  1079. brace = L"}";
  1080. adapterDevNamep =
  1081. (PWCHAR)((PUCHAR)adapterDevNamep + AdapterIdLength);
  1082. *adapterDevNamep = *brace;
  1083. }
  1084. // open the adapter device
  1085. status = CnpOpenDevice(
  1086. adapterDevNameBuffer,
  1087. &adapterDevHandle
  1088. );
  1089. if (!NT_SUCCESS(status)) {
  1090. IF_CNDBG( CN_DEBUG_IFOBJ )
  1091. CNPRINT((
  1092. "[CNP] Failed to open adapter "
  1093. "device %S while registering "
  1094. "interface (%u, %u), status %lx.\n",
  1095. adapterDevNameBuffer,
  1096. NodeId,
  1097. NetworkId,
  1098. status
  1099. ));
  1100. goto error_exit;
  1101. }
  1102. status = ObReferenceObjectByHandle(
  1103. adapterDevHandle,
  1104. 0L, // DesiredAccess
  1105. NULL,
  1106. KernelMode,
  1107. &adapterFileObject,
  1108. NULL
  1109. );
  1110. if (!NT_SUCCESS(status)) {
  1111. IF_CNDBG( CN_DEBUG_IFOBJ )
  1112. CNPRINT((
  1113. "[CNP] Failed to reference handle "
  1114. "for adapter device %S while "
  1115. "registering interface (%u, %u), "
  1116. "status %lx.\n",
  1117. adapterDevNameBuffer,
  1118. NodeId,
  1119. NetworkId,
  1120. status
  1121. ));
  1122. ZwClose(adapterDevHandle);
  1123. adapterDevHandle = NULL;
  1124. goto error_exit;
  1125. }
  1126. adapterDeviceObject = IoGetRelatedDeviceObject(
  1127. adapterFileObject
  1128. );
  1129. // convert the adapter device object into the
  1130. // WMI provider ID
  1131. interface->AdapterWMIProviderId =
  1132. IoWMIDeviceObjectToProviderId(adapterDeviceObject);
  1133. IF_CNDBG( CN_DEBUG_IFOBJ )
  1134. CNPRINT((
  1135. "[CNP] Found WMI Provider ID %lx for adapter "
  1136. "device %S while "
  1137. "registering interface (%u, %u).\n",
  1138. interface->AdapterWMIProviderId,
  1139. adapterDevNameBuffer,
  1140. NodeId,
  1141. NetworkId
  1142. ));
  1143. // we no longer need the file object or device name
  1144. // buffer, but we hold onto the adapter device handle
  1145. // in order to query the current media status.
  1146. ObDereferenceObject(adapterFileObject);
  1147. CnFreePool(adapterDevNameBuffer);
  1148. adapterDevNameBuffer = NULL;
  1149. // reacquire the local node lock
  1150. status = CnpValidateAndFindNode(NodeId, &node);
  1151. if (!NT_SUCCESS(status)) {
  1152. status = STATUS_CLUSTER_NODE_NOT_FOUND;
  1153. goto error_exit;
  1154. }
  1155. }
  1156. network = CnpFindNetwork(NetworkId);
  1157. if (network != NULL) {
  1158. //
  1159. // Check if the specified interface already exists.
  1160. //
  1161. status = STATUS_SUCCESS;
  1162. for (entry = node->InterfaceList.Flink;
  1163. entry != &(node->InterfaceList);
  1164. entry = entry->Flink
  1165. )
  1166. {
  1167. PCNP_INTERFACE oldInterface = CONTAINING_RECORD(
  1168. entry,
  1169. CNP_INTERFACE,
  1170. NodeLinkage
  1171. );
  1172. if (oldInterface->Network == network) {
  1173. status = STATUS_CLUSTER_NETINTERFACE_EXISTS;
  1174. break;
  1175. }
  1176. }
  1177. if (NT_SUCCESS(status)) {
  1178. interface->Node = node;
  1179. interface->Network = network;
  1180. if (Priority != 0) {
  1181. interface->Priority = Priority;
  1182. }
  1183. else {
  1184. interface->Priority = network->Priority;
  1185. interface->Flags |= CNP_IF_FLAG_USE_NETWORK_PRIORITY;
  1186. }
  1187. IF_CNDBG( CN_DEBUG_IFOBJ )
  1188. CNPRINT((
  1189. "[CNP] Registering interface (%u, %u) pri %u...\n",
  1190. NodeId,
  1191. NetworkId,
  1192. interface->Priority
  1193. ));
  1194. //
  1195. // Place a reference on the network for this interface.
  1196. //
  1197. CnpReferenceNetwork(network);
  1198. //
  1199. // Insert the interface into the node's interface list.
  1200. //
  1201. InsertTailList(
  1202. &(node->InterfaceList),
  1203. &(interface->NodeLinkage)
  1204. );
  1205. //
  1206. // Update the node's CurrentInterface if appropriate.
  1207. //
  1208. if ( !CnpIsNetworkRestricted(network) &&
  1209. !CnpIsNetworkLocalDisconn(network) &&
  1210. CnpIsBetterInterface(interface, node->CurrentInterface)
  1211. )
  1212. {
  1213. IF_CNDBG( CN_DEBUG_IFOBJ )
  1214. CNPRINT((
  1215. "[CNP] Network %u is now the best route to node %u.\n",
  1216. network->Id,
  1217. node->Id
  1218. ));
  1219. node->CurrentInterface = interface;
  1220. if (CnpIsNodeUnreachable(node)) {
  1221. CnTrace(
  1222. CNP_IF_DETAIL,
  1223. CnpTraceOnlinePendingIfReach,
  1224. "[CNP] Declaring node %u reachable after "
  1225. "registering interface on network %u.\n",
  1226. node->Id, network->Id
  1227. );
  1228. CnpDeclareNodeReachable(node);
  1229. }
  1230. }
  1231. IF_CNDBG( CN_DEBUG_IFOBJ )
  1232. CNPRINT((
  1233. "[CNP] Registered interface (%u, %u).\n",
  1234. NodeId,
  1235. NetworkId
  1236. ));
  1237. if (network->State == ClusnetNetworkStateOnline) {
  1238. (VOID) CnpOnlinePendingInterface(interface);
  1239. //
  1240. // The network lock was released.
  1241. //
  1242. }
  1243. else {
  1244. CnReleaseLockFromDpc(&(network->Lock));
  1245. }
  1246. CnReleaseLock(&(node->Lock), node->Irql);
  1247. //
  1248. // Determine the initial media status state of this
  1249. // interface if it is local.
  1250. //
  1251. if (localAdapter) {
  1252. CxQueryMediaStatus(
  1253. adapterDevHandle,
  1254. NetworkId,
  1255. MediaStatus
  1256. );
  1257. } else {
  1258. //
  1259. // Assume remote interfaces are connected
  1260. //
  1261. *MediaStatus = NdisMediaStateConnected;
  1262. }
  1263. if (adapterDevHandle != NULL) {
  1264. ZwClose(adapterDevHandle);
  1265. adapterDevHandle = NULL;
  1266. }
  1267. return(STATUS_SUCCESS);
  1268. }
  1269. CnReleaseLockFromDpc(&(network->Lock));
  1270. }
  1271. else {
  1272. status = STATUS_CLUSTER_NETWORK_NOT_FOUND;
  1273. }
  1274. CnReleaseLock(&(node->Lock), node->Irql);
  1275. }
  1276. else {
  1277. status = STATUS_CLUSTER_NODE_NOT_FOUND;
  1278. }
  1279. error_exit:
  1280. if (!NT_SUCCESS(status)) {
  1281. CnFreePool(interface);
  1282. }
  1283. if (adapterDevHandle != NULL) {
  1284. ZwClose(adapterDevHandle);
  1285. adapterDevHandle = NULL;
  1286. }
  1287. if (adapterDevNameBuffer != NULL) {
  1288. CnFreePool(adapterDevNameBuffer);
  1289. adapterDevNameBuffer = NULL;
  1290. }
  1291. CnVerifyCpuLockMask(
  1292. 0, // Required
  1293. 0xFFFFFFFF, // Forbidden
  1294. 0 // Maximum
  1295. );
  1296. return(status);
  1297. } // CxRegisterInterface
  1298. NTSTATUS
  1299. CxDeregisterInterface(
  1300. CL_NODE_ID NodeId,
  1301. CL_NETWORK_ID NetworkId
  1302. )
  1303. {
  1304. NTSTATUS status;
  1305. PCNP_INTERFACE interface;
  1306. ULONG i;
  1307. PCNP_NODE node;
  1308. PCNP_NETWORK network;
  1309. CN_IRQL tableIrql;
  1310. if ((NodeId == ClusterAnyNodeId) && (NetworkId == ClusterAnyNetworkId)) {
  1311. //
  1312. // Destroy all interfaces on all networks.
  1313. //
  1314. IF_CNDBG(( CN_DEBUG_IFOBJ | CN_DEBUG_CLEANUP ))
  1315. CNPRINT(("[CNP] Destroying all interfaces on all networks\n"));
  1316. CnAcquireLock(&CnpNodeTableLock, &tableIrql);
  1317. CnAssert(CnMinValidNodeId != ClusterInvalidNodeId);
  1318. CnAssert(CnMaxValidNodeId != ClusterInvalidNodeId);
  1319. for (i=CnMinValidNodeId; i <= CnMaxValidNodeId; i++) {
  1320. node = CnpNodeTable[i];
  1321. if (node != NULL) {
  1322. CnAcquireLockAtDpc(&(node->Lock));
  1323. CnReleaseLockFromDpc(&CnpNodeTableLock);
  1324. node->Irql = tableIrql;
  1325. CnpWalkInterfacesOnNode(node, CnpDeleteInterface);
  1326. CnReleaseLock(&(node->Lock), node->Irql);
  1327. CnAcquireLock(&CnpNodeTableLock, &tableIrql);
  1328. }
  1329. }
  1330. CnReleaseLock(&CnpNodeTableLock, tableIrql);
  1331. status = STATUS_SUCCESS;
  1332. }
  1333. else if (NodeId == ClusterAnyNodeId) {
  1334. //
  1335. // Destroy all interfaces on a specific network.
  1336. //
  1337. IF_CNDBG(( CN_DEBUG_IFOBJ | CN_DEBUG_NETOBJ | CN_DEBUG_CLEANUP ))
  1338. CNPRINT((
  1339. "[CNP] Destroying all interfaces on network %u\n",
  1340. NetworkId
  1341. ));
  1342. network = CnpFindNetwork(NetworkId);
  1343. if (network != NULL) {
  1344. CnpReferenceNetwork(network);
  1345. CnReleaseLock(&(network->Lock), network->Irql);
  1346. CnpWalkInterfacesOnNetwork(network, CnpDeleteInterface);
  1347. CnAcquireLock(&(network->Lock), &(network->Irql));
  1348. CnpDereferenceNetwork(network);
  1349. status = STATUS_SUCCESS;
  1350. }
  1351. else {
  1352. status = STATUS_CLUSTER_NETWORK_NOT_FOUND;
  1353. }
  1354. }
  1355. else if (NetworkId == ClusterAnyNetworkId) {
  1356. //
  1357. // Destroy all interfaces on a specified node.
  1358. //
  1359. IF_CNDBG(( CN_DEBUG_IFOBJ | CN_DEBUG_NODEOBJ | CN_DEBUG_CLEANUP ))
  1360. CNPRINT((
  1361. "[CNP] Destroying all interfaces on node %u\n",
  1362. NodeId
  1363. ));
  1364. status = CnpValidateAndFindNode(NodeId, &node);
  1365. if (status == STATUS_SUCCESS) {
  1366. CnpWalkInterfacesOnNode(node, CnpDeleteInterface);
  1367. CnReleaseLock(&(node->Lock), node->Irql);
  1368. }
  1369. }
  1370. else {
  1371. //
  1372. // Delete a specific interface
  1373. //
  1374. status = CnpFindInterface(NodeId, NetworkId, &interface);
  1375. if (NT_SUCCESS(status)) {
  1376. node = interface->Node;
  1377. CnpDeleteInterface(interface);
  1378. //
  1379. // The network lock was released.
  1380. //
  1381. CnReleaseLock(&(node->Lock), node->Irql);
  1382. }
  1383. }
  1384. return(status);
  1385. } // CxDeregisterNetwork
  1386. NTSTATUS
  1387. CxSetInterfacePriority(
  1388. IN CL_NODE_ID NodeId,
  1389. IN CL_NETWORK_ID NetworkId,
  1390. IN ULONG Priority
  1391. )
  1392. {
  1393. NTSTATUS status;
  1394. PCNP_INTERFACE interface;
  1395. PCNP_NODE node;
  1396. PCNP_NETWORK network;
  1397. ULONG oldPriority;
  1398. BOOLEAN restricted;
  1399. BOOLEAN localDisconn;
  1400. CnVerifyCpuLockMask(
  1401. 0, // Required
  1402. 0xFFFFFFFF, // Forbidden
  1403. 0 // Maximum
  1404. );
  1405. status = CnpFindInterface(NodeId, NetworkId, &interface);
  1406. if (status == STATUS_SUCCESS) {
  1407. node = interface->Node;
  1408. network = interface->Network;
  1409. oldPriority = interface->Priority;
  1410. restricted = CnpIsNetworkRestricted(network);
  1411. localDisconn = CnpIsNetworkLocalDisconn(network);
  1412. if (Priority != 0) {
  1413. interface->Priority = Priority;
  1414. interface->Flags &= ~(CNP_IF_FLAG_USE_NETWORK_PRIORITY);
  1415. }
  1416. else {
  1417. interface->Priority = network->Priority;
  1418. interface->Flags |= CNP_IF_FLAG_USE_NETWORK_PRIORITY;
  1419. }
  1420. IF_CNDBG( CN_DEBUG_IFOBJ )
  1421. CNPRINT((
  1422. "[CNP] Set interface (%u, %u) to priority %u\n",
  1423. NodeId,
  1424. NetworkId,
  1425. interface->Priority
  1426. ));
  1427. CnReleaseLockFromDpc(&(network->Lock));
  1428. if (!restricted) {
  1429. if (interface == node->CurrentInterface) {
  1430. if (interface->Priority > oldPriority) {
  1431. //
  1432. // Our priority got worse. Recalculate the best route.
  1433. //
  1434. CnpUpdateNodeCurrentInterface(node);
  1435. }
  1436. //
  1437. // Else interface priority is same or better. Nothing to do.
  1438. //
  1439. }
  1440. else if ( !localDisconn &&
  1441. CnpIsBetterInterface(
  1442. interface,
  1443. node->CurrentInterface
  1444. )
  1445. )
  1446. {
  1447. //
  1448. // Our priority got better.
  1449. //
  1450. IF_CNDBG(( CN_DEBUG_NODEOBJ | CN_DEBUG_NETOBJ ))
  1451. CNPRINT((
  1452. "[CNP] Network %u is now the best route to node %u\n",
  1453. network->Id,
  1454. node->Id
  1455. ));
  1456. node->CurrentInterface = interface;
  1457. }
  1458. }
  1459. CnReleaseLock(&(node->Lock), node->Irql);
  1460. }
  1461. CnVerifyCpuLockMask(
  1462. 0, // Required
  1463. 0xFFFFFFFF, // Forbidden
  1464. 0 // Maximum
  1465. );
  1466. return(status);
  1467. } // CxSetInterfacePriority
  1468. NTSTATUS
  1469. CxGetInterfacePriority(
  1470. IN CL_NODE_ID NodeId,
  1471. IN CL_NETWORK_ID NetworkId,
  1472. OUT PULONG InterfacePriority,
  1473. OUT PULONG NetworkPriority
  1474. )
  1475. {
  1476. NTSTATUS status;
  1477. PCNP_INTERFACE interface;
  1478. PCNP_NODE node;
  1479. PCNP_NETWORK network;
  1480. CnVerifyCpuLockMask(
  1481. 0, // Required
  1482. 0xFFFFFFFF, // Forbidden
  1483. 0 // Maximum
  1484. );
  1485. status = CnpFindInterface(NodeId, NetworkId, &interface);
  1486. if (status == STATUS_SUCCESS) {
  1487. node = interface->Node;
  1488. network = interface->Network;
  1489. *NetworkPriority = network->Priority;
  1490. if (CnpIsInterfaceUsingNetworkPriority(interface)) {
  1491. *InterfacePriority = 0;
  1492. }
  1493. else {
  1494. *InterfacePriority = interface->Priority;
  1495. }
  1496. CnReleaseLockFromDpc(&(network->Lock));
  1497. CnReleaseLock(&(node->Lock), node->Irql);
  1498. }
  1499. CnVerifyCpuLockMask(
  1500. 0, // Required
  1501. 0xFFFFFFFF, // Forbidden
  1502. 0 // Maximum
  1503. );
  1504. return(status);
  1505. } // CxGetInterfacePriority
  1506. NTSTATUS
  1507. CxGetInterfaceState(
  1508. IN CL_NODE_ID NodeId,
  1509. IN CL_NETWORK_ID NetworkId,
  1510. OUT PCLUSNET_INTERFACE_STATE State
  1511. )
  1512. {
  1513. NTSTATUS status;
  1514. PCNP_INTERFACE interface;
  1515. PCNP_NODE node;
  1516. PCNP_NETWORK network;
  1517. CnVerifyCpuLockMask(
  1518. 0, // Required
  1519. 0xFFFFFFFF, // Forbidden
  1520. 0 // Maximum
  1521. );
  1522. status = CnpFindInterface(NodeId, NetworkId, &interface);
  1523. if (status == STATUS_SUCCESS) {
  1524. node = interface->Node;
  1525. network = interface->Network;
  1526. *State = interface->State;
  1527. CnAssert(network->Irql == DISPATCH_LEVEL);
  1528. CnReleaseLockFromDpc(&(network->Lock));
  1529. CnReleaseLock(&(node->Lock), node->Irql);
  1530. }
  1531. CnVerifyCpuLockMask(
  1532. 0, // Required
  1533. 0xFFFFFFFF, // Forbidden
  1534. 0 // Maximum
  1535. );
  1536. return(status);
  1537. } // CxGetInterfaceState
  1538. //
  1539. // Test APIs
  1540. //
  1541. #if DBG
  1542. NTSTATUS
  1543. CxOnlinePendingInterface(
  1544. IN CL_NODE_ID NodeId,
  1545. IN CL_NETWORK_ID NetworkId
  1546. )
  1547. {
  1548. NTSTATUS status;
  1549. PCNP_INTERFACE interface;
  1550. PCNP_NODE node;
  1551. PCNP_NETWORK network;
  1552. CnVerifyCpuLockMask(
  1553. 0, // Required
  1554. 0xFFFFFFFF, // Forbidden
  1555. 0 // Maximum
  1556. );
  1557. status = CnpFindInterface(NodeId, NetworkId, &interface);
  1558. if (status == STATUS_SUCCESS) {
  1559. node = interface->Node;
  1560. network = interface->Network;
  1561. status = CnpOnlinePendingInterface(interface);
  1562. //
  1563. // The network lock was released
  1564. //
  1565. CnReleaseLock(&(node->Lock), node->Irql);
  1566. }
  1567. CnVerifyCpuLockMask(
  1568. 0, // Required
  1569. 0xFFFFFFFF, // Forbidden
  1570. 0 // Maximum
  1571. );
  1572. return(status);
  1573. } // CxOnlinePendingInterface
  1574. NTSTATUS
  1575. CxOnlineInterface(
  1576. IN CL_NODE_ID NodeId,
  1577. IN CL_NETWORK_ID NetworkId
  1578. )
  1579. {
  1580. NTSTATUS status;
  1581. PCNP_INTERFACE interface;
  1582. PCNP_NODE node;
  1583. CnVerifyCpuLockMask(
  1584. 0, // Required
  1585. 0xFFFFFFFF, // Forbidden
  1586. 0 // Maximum
  1587. );
  1588. status = CnpFindInterface(NodeId, NetworkId, &interface);
  1589. if (status == STATUS_SUCCESS) {
  1590. node = interface->Node;
  1591. status = CnpOnlineInterface(interface);
  1592. //
  1593. // The network lock was released
  1594. //
  1595. CnReleaseLock(&(node->Lock), node->Irql);
  1596. }
  1597. CnVerifyCpuLockMask(
  1598. 0, // Required
  1599. 0xFFFFFFFF, // Forbidden
  1600. 0 // Maximum
  1601. );
  1602. return(status);
  1603. } // CxOnlineInterface
  1604. NTSTATUS
  1605. CxOfflineInterface(
  1606. IN CL_NODE_ID NodeId,
  1607. IN CL_NETWORK_ID NetworkId
  1608. )
  1609. {
  1610. NTSTATUS status;
  1611. PCNP_INTERFACE interface;
  1612. PCNP_NODE node;
  1613. CnVerifyCpuLockMask(
  1614. 0, // Required
  1615. 0xFFFFFFFF, // Forbidden
  1616. 0 // Maximum
  1617. );
  1618. status = CnpFindInterface(NodeId, NetworkId, &interface);
  1619. if (status == STATUS_SUCCESS) {
  1620. node = interface->Node;
  1621. status = CnpOfflineInterface(interface);
  1622. //
  1623. // The network lock was released
  1624. //
  1625. CnReleaseLock(&(node->Lock), node->Irql);
  1626. }
  1627. CnVerifyCpuLockMask(
  1628. 0, // Required
  1629. 0xFFFFFFFF, // Forbidden
  1630. 0 // Maximum
  1631. );
  1632. return(status);
  1633. } // CxOfflineInterface
  1634. NTSTATUS
  1635. CxFailInterface(
  1636. IN CL_NODE_ID NodeId,
  1637. IN CL_NETWORK_ID NetworkId
  1638. )
  1639. {
  1640. NTSTATUS status;
  1641. PCNP_INTERFACE interface;
  1642. PCNP_NODE node;
  1643. CnVerifyCpuLockMask(
  1644. 0, // Required
  1645. 0xFFFFFFFF, // Forbidden
  1646. 0 // Maximum
  1647. );
  1648. status = CnpFindInterface(NodeId, NetworkId, &interface);
  1649. if (status == STATUS_SUCCESS) {
  1650. node = interface->Node;
  1651. status = CnpFailInterface(interface);
  1652. //
  1653. // The network lock was released
  1654. //
  1655. CnReleaseLock(&(node->Lock), node->Irql);
  1656. }
  1657. CnVerifyCpuLockMask(
  1658. 0, // Required
  1659. 0xFFFFFFFF, // Forbidden
  1660. 0 // Maximum
  1661. );
  1662. return(status);
  1663. } // CxOfflineInterface
  1664. #endif // DBG