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

292 lines
7.0 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. TraceEnter(TMR, "McastTimerRoutine");
  68. KeQueryTickCount((PLARGE_INTEGER)&llCurrentTime);
  69. ulIndex = g_ulNextHashIndex;
  70. ulMsgIndex = 0;
  71. pCopy = NULL;
  72. pMsg = NULL;
  73. Trace(TMR, TRACE,
  74. ("McastTimerRoutine: Starting at index %d\n",
  75. ulIndex));
  76. for(ulNumBuckets = 0;
  77. ulNumBuckets < BUCKETS_PER_QUANTUM;
  78. ulNumBuckets++)
  79. {
  80. //
  81. // Acquire the bucket lock as writer. Since we are off a TIMER
  82. // we are at DPC
  83. //
  84. EnterWriterAtDpcLevel(&g_rgGroupTable[ulIndex].rwlLock);
  85. pleGrpNode = g_rgGroupTable[ulIndex].leHashHead.Flink;
  86. while(pleGrpNode isnot &(g_rgGroupTable[ulIndex].leHashHead))
  87. {
  88. pGroup = CONTAINING_RECORD(pleGrpNode, GROUP, leHashLink);
  89. pleGrpNode = pleGrpNode->Flink;
  90. pleSrcNode = pGroup->leSrcHead.Flink;
  91. while(pleSrcNode isnot &pGroup->leSrcHead)
  92. {
  93. //
  94. // We look at the SOURCE without taking the lock, because
  95. // the source can not be deleted without removing it from the
  96. // group list, which can not happen since we have the group
  97. // bucket locked as writer
  98. //
  99. pSource = CONTAINING_RECORD(pleSrcNode, SOURCE, leGroupLink);
  100. pleSrcNode = pleSrcNode->Flink;
  101. //
  102. // The TimeOut and CreateTime can be looked at without
  103. // a lock, but the LastActivity should be read only with
  104. // the lock held. However, we shall take the chance and
  105. // not use a lock
  106. //
  107. if(pSource->llTimeOut isnot 0)
  108. {
  109. //
  110. // Timeout value has been supplied, lets use that
  111. //
  112. llTime = llCurrentTime - pSource->llCreateTime;
  113. if((llCurrentTime > pSource->llCreateTime) and
  114. (llTime < pSource->llTimeOut))
  115. {
  116. continue;
  117. }
  118. Trace(TMR, TRACE,
  119. ("McastTimerRoutine: %d.%d.%d.%d %d.%d.%d.%d entry being removed due to user supplied timeout\n",
  120. PRINT_IPADDR(pGroup->dwGroup),
  121. PRINT_IPADDR(pSource->dwSource)));
  122. }
  123. else
  124. {
  125. //
  126. // Otherwise, just do this based on activity
  127. //
  128. llTime = llCurrentTime - pSource->llLastActivity;
  129. if((llCurrentTime > pSource->llLastActivity) and
  130. (llTime < SECS_TO_TICKS(INACTIVITY_PERIOD)))
  131. {
  132. continue;
  133. }
  134. Trace(TMR, TRACE,
  135. ("McastTimerRoutine: %d.%d.%d.%d %d.%d.%d.%d entry being removed due to inactiviy\n",
  136. PRINT_IPADDR(pGroup->dwGroup),
  137. PRINT_IPADDR(pSource->dwSource)));
  138. }
  139. //
  140. // Otherwise we need to delete the source, and complete an
  141. // IRP back to the router manager
  142. //
  143. if(ulMsgIndex is 0)
  144. {
  145. RtAssert(!pCopy);
  146. pCopy = ExAllocateFromNPagedLookasideList(&g_llMsgBlocks);
  147. if(pCopy is NULL)
  148. {
  149. continue;
  150. }
  151. pCopy->inMessage.dwEvent = IPMCAST_DELETE_MFE_MSG;
  152. pMsg = &(pCopy->inMessage.immMfe);
  153. pMsg->ulNumMfes = 0;
  154. }
  155. pMsg->ulNumMfes++;
  156. pMsg->idmMfe[ulMsgIndex].dwGroup = pGroup->dwGroup;
  157. pMsg->idmMfe[ulMsgIndex].dwSource = pSource->dwSource;
  158. pMsg->idmMfe[ulMsgIndex].dwSrcMask = pSource->dwSrcMask;
  159. ulMsgIndex++;
  160. ulMsgIndex %= NUM_DEL_MFES;
  161. if(ulMsgIndex is 0)
  162. {
  163. //
  164. // Complete the Irp
  165. //
  166. CompleteNotificationIrp(pCopy);
  167. pCopy = NULL;
  168. pMsg = NULL;
  169. }
  170. //
  171. // The function needs the SOURCE ref'ed and locked
  172. //
  173. ReferenceSource(pSource);
  174. RtAcquireSpinLockAtDpcLevel(&(pSource->mlLock));
  175. RemoveSource(pGroup->dwGroup,
  176. pSource->dwSource,
  177. pSource->dwSrcMask,
  178. pGroup,
  179. pSource);
  180. }
  181. }
  182. ExitWriterFromDpcLevel(&g_rgGroupTable[ulIndex].rwlLock);
  183. //
  184. // Done walking this bucket
  185. //
  186. ulIndex++;
  187. ulIndex %= GROUP_TABLE_SIZE;
  188. }
  189. //
  190. // The last message may not have been indicated up. See if it needs
  191. // to be completed
  192. //
  193. if(pCopy)
  194. {
  195. CompleteNotificationIrp(pCopy);
  196. }
  197. g_ulNextHashIndex = ulIndex;
  198. liDueTime = RtlEnlargedUnsignedMultiply(TIMER_IN_MILLISECS,
  199. SYS_UNITS_IN_ONE_MILLISEC);
  200. liDueTime = RtlLargeIntegerNegate(liDueTime);
  201. KeSetTimerEx(&g_ktTimer,
  202. liDueTime,
  203. 0,
  204. &g_kdTimerDpc);
  205. TraceLeave(TMR, "McastTimerRoutine");
  206. }
  207. #endif