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.

300 lines
7.6 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. tcpip\ip\mcasttmr.c
  5. Abstract:
  6. Timer routine for cleanup of MFEs
  7. Author:
  8. Amritansh Raghav
  9. Revision History:
  10. AmritanR Created
  11. Notes:
  12. --*/
  13. #include "precomp.h"
  14. #if IPMCAST
  15. #define __FILE_SIG__ TMR_SIG
  16. #include "ipmcast.h"
  17. #include "ipmcstxt.h"
  18. #include "mcastmfe.h"
  19. VOID
  20. CompleteNotificationIrp(
  21. IN PNOTIFICATION_MSG pMsg
  22. );
  23. VOID
  24. McastTimerRoutine(
  25. PKDPC Dpc,
  26. PVOID DeferredContext,
  27. PVOID SystemArgument1,
  28. PVOID SystemArgument2
  29. );
  30. //
  31. // MUST BE PAGED IN
  32. //
  33. #pragma alloc_text(PAGEIPMc, McastTimerRoutine)
  34. VOID
  35. McastTimerRoutine(
  36. PKDPC Dpc,
  37. PVOID DeferredContext,
  38. PVOID SystemArgument1,
  39. PVOID SystemArgument2
  40. )
  41. /*++
  42. Routine Description:
  43. The DPC routine associated with the timer.
  44. The global variable g_ulNextHashIndex keeps track of the bucket
  45. that needs to be walked and checked for activity. The routine
  46. walks all the groups in BUCKETS_PER_QUANTUM number of buckets.
  47. N.B.: We should probably use a JOB object for this.
  48. Locks:
  49. Takes the lock for each hash bucket walked as writer
  50. Arguments:
  51. Dpc
  52. DeferredContext
  53. SystemArgument1
  54. SystemArgument2
  55. Return Value:
  56. NONE
  57. --*/
  58. {
  59. LONGLONG llCurrentTime, llTime;
  60. ULONG ulIndex, ulNumBuckets, ulMsgIndex;
  61. PLIST_ENTRY pleGrpNode, pleSrcNode;
  62. PGROUP pGroup;
  63. PSOURCE pSource;
  64. LARGE_INTEGER liDueTime;
  65. PNOTIFICATION_MSG pCopy;
  66. PIPMCAST_MFE_MSG pMsg;
  67. UNREFERENCED_PARAMETER(Dpc);
  68. UNREFERENCED_PARAMETER(DeferredContext);
  69. UNREFERENCED_PARAMETER(SystemArgument1);
  70. UNREFERENCED_PARAMETER(SystemArgument2);
  71. TraceEnter(TMR, "McastTimerRoutine");
  72. #pragma warning(push)
  73. #pragma warning(disable:4127)
  74. KeQueryTickCount((PLARGE_INTEGER)&llCurrentTime);
  75. #pragma warning(pop)
  76. ulIndex = g_ulNextHashIndex;
  77. ulMsgIndex = 0;
  78. pCopy = NULL;
  79. pMsg = NULL;
  80. Trace(TMR, TRACE,
  81. ("McastTimerRoutine: Starting at index %d\n",
  82. ulIndex));
  83. for(ulNumBuckets = 0;
  84. ulNumBuckets < BUCKETS_PER_QUANTUM;
  85. ulNumBuckets++)
  86. {
  87. //
  88. // Acquire the bucket lock as writer. Since we are off a TIMER
  89. // we are at DPC
  90. //
  91. EnterWriterAtDpcLevel(&g_rgGroupTable[ulIndex].rwlLock);
  92. pleGrpNode = g_rgGroupTable[ulIndex].leHashHead.Flink;
  93. while(pleGrpNode isnot &(g_rgGroupTable[ulIndex].leHashHead))
  94. {
  95. pGroup = CONTAINING_RECORD(pleGrpNode, GROUP, leHashLink);
  96. pleGrpNode = pleGrpNode->Flink;
  97. pleSrcNode = pGroup->leSrcHead.Flink;
  98. while(pleSrcNode isnot &pGroup->leSrcHead)
  99. {
  100. //
  101. // We look at the SOURCE without taking the lock, because
  102. // the source can not be deleted without removing it from the
  103. // group list, which can not happen since we have the group
  104. // bucket locked as writer
  105. //
  106. pSource = CONTAINING_RECORD(pleSrcNode, SOURCE, leGroupLink);
  107. pleSrcNode = pleSrcNode->Flink;
  108. //
  109. // The TimeOut and CreateTime can be looked at without
  110. // a lock, but the LastActivity should be read only with
  111. // the lock held. However, we shall take the chance and
  112. // not use a lock
  113. //
  114. if(pSource->llTimeOut isnot 0)
  115. {
  116. //
  117. // Timeout value has been supplied, lets use that
  118. //
  119. llTime = llCurrentTime - pSource->llCreateTime;
  120. if((llCurrentTime > pSource->llCreateTime) and
  121. (llTime < pSource->llTimeOut))
  122. {
  123. continue;
  124. }
  125. Trace(TMR, TRACE,
  126. ("McastTimerRoutine: %d.%d.%d.%d %d.%d.%d.%d entry being removed due to user supplied timeout\n",
  127. PRINT_IPADDR(pGroup->dwGroup),
  128. PRINT_IPADDR(pSource->dwSource)));
  129. }
  130. else
  131. {
  132. //
  133. // Otherwise, just do this based on activity
  134. //
  135. llTime = llCurrentTime - pSource->llLastActivity;
  136. if((llCurrentTime > pSource->llLastActivity) and
  137. (llTime < SECS_TO_TICKS(INACTIVITY_PERIOD)))
  138. {
  139. continue;
  140. }
  141. Trace(TMR, TRACE,
  142. ("McastTimerRoutine: %d.%d.%d.%d %d.%d.%d.%d entry being removed due to inactiviy\n",
  143. PRINT_IPADDR(pGroup->dwGroup),
  144. PRINT_IPADDR(pSource->dwSource)));
  145. }
  146. //
  147. // Otherwise we need to delete the source, and complete an
  148. // IRP back to the router manager
  149. //
  150. if(ulMsgIndex is 0)
  151. {
  152. RtAssert(!pCopy);
  153. pCopy = ExAllocateFromNPagedLookasideList(&g_llMsgBlocks);
  154. if(pCopy is NULL)
  155. {
  156. continue;
  157. }
  158. pCopy->inMessage.dwEvent = IPMCAST_DELETE_MFE_MSG;
  159. pMsg = &(pCopy->inMessage.immMfe);
  160. pMsg->ulNumMfes = 0;
  161. }
  162. pMsg->ulNumMfes++;
  163. pMsg->idmMfe[ulMsgIndex].dwGroup = pGroup->dwGroup;
  164. pMsg->idmMfe[ulMsgIndex].dwSource = pSource->dwSource;
  165. pMsg->idmMfe[ulMsgIndex].dwSrcMask = pSource->dwSrcMask;
  166. ulMsgIndex++;
  167. ulMsgIndex %= NUM_DEL_MFES;
  168. if(ulMsgIndex is 0)
  169. {
  170. //
  171. // Complete the Irp
  172. //
  173. CompleteNotificationIrp(pCopy);
  174. pCopy = NULL;
  175. pMsg = NULL;
  176. }
  177. //
  178. // The function needs the SOURCE ref'ed and locked
  179. //
  180. ReferenceSource(pSource);
  181. RtAcquireSpinLockAtDpcLevel(&(pSource->mlLock));
  182. RemoveSource(pGroup->dwGroup,
  183. pSource->dwSource,
  184. pSource->dwSrcMask,
  185. pGroup,
  186. pSource);
  187. }
  188. }
  189. ExitWriterFromDpcLevel(&g_rgGroupTable[ulIndex].rwlLock);
  190. //
  191. // Done walking this bucket
  192. //
  193. ulIndex++;
  194. ulIndex %= GROUP_TABLE_SIZE;
  195. }
  196. //
  197. // The last message may not have been indicated up. See if it needs
  198. // to be completed
  199. //
  200. if(pCopy)
  201. {
  202. CompleteNotificationIrp(pCopy);
  203. }
  204. g_ulNextHashIndex = ulIndex;
  205. liDueTime = RtlEnlargedUnsignedMultiply(TIMER_IN_MILLISECS,
  206. SYS_UNITS_IN_ONE_MILLISEC);
  207. liDueTime = RtlLargeIntegerNegate(liDueTime);
  208. KeSetTimerEx(&g_ktTimer,
  209. liDueTime,
  210. 0,
  211. &g_kdTimerDpc);
  212. TraceLeave(TMR, "McastTimerRoutine");
  213. }
  214. #endif