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.

446 lines
11 KiB

  1. //============================================================================
  2. // Copyright (c) 1995, Microsoft Corporation
  3. //
  4. // File: timer.c
  5. //
  6. // History:
  7. // V Raman June-25-1997 Created.
  8. //
  9. // Functions to manager ageing out of MFEs.
  10. //============================================================================
  11. #include "pchmgm.h"
  12. #pragma hdrstop
  13. //----------------------------------------------------------------------------
  14. // DeleteFromForwarder
  15. //
  16. // This function is an entry point for IP RouterManager. It is invoked
  17. // in response to deletion (because of timeouts) of MFEs in the kernel
  18. // mode forwarder. This entry point is invoked with a list of deleted
  19. // MFEs.
  20. //
  21. // This function flags each of the MFEs that have been deleted by the
  22. // forwarder as "not present in the forwarder"
  23. //----------------------------------------------------------------------------
  24. DWORD
  25. DeleteFromForwarder(
  26. DWORD dwEntryCount,
  27. PIPMCAST_DELETE_MFE pimdmMfes
  28. )
  29. {
  30. DWORD dwInd, dwGrpBucket, dwSrcBucket;
  31. PGROUP_ENTRY pge;
  32. PSOURCE_ENTRY pse;
  33. PLIST_ENTRY pleHead;
  34. TRACE1( TIMER, "ENTERED DeleteFromForwarder, Entries %x", dwEntryCount );
  35. //
  36. // for each MFE that has been deleted from the KMF
  37. //
  38. for ( dwInd = 0; dwInd < dwEntryCount; dwInd++ )
  39. {
  40. //
  41. // 1. Lookup the MFE in MGM
  42. //
  43. //
  44. // 1.1 Find group entry
  45. //
  46. dwGrpBucket = GROUP_TABLE_HASH( pimdmMfes[ dwInd ].dwGroup, 0 );
  47. ACQUIRE_GROUP_LOCK_SHARED( dwGrpBucket );
  48. pleHead = GROUP_BUCKET_HEAD( dwGrpBucket );
  49. pge = GetGroupEntry( pleHead, pimdmMfes[ dwInd ].dwGroup, 0 );
  50. if ( pge != NULL )
  51. {
  52. //
  53. // 1.2 Group entry found, find source entry
  54. //
  55. ACQUIRE_GROUP_ENTRY_LOCK_EXCLUSIVE( pge );
  56. dwSrcBucket = SOURCE_TABLE_HASH(
  57. pimdmMfes[ dwInd ].dwSource,
  58. pimdmMfes[ dwInd ].dwSrcMask
  59. );
  60. pleHead = SOURCE_BUCKET_HEAD( pge, dwSrcBucket );
  61. pse = GetSourceEntry(
  62. pleHead,
  63. pimdmMfes[ dwInd ].dwSource,
  64. pimdmMfes[ dwInd ].dwSrcMask
  65. );
  66. if ( pse != NULL )
  67. {
  68. pse-> bInForwarder = FALSE;
  69. }
  70. else
  71. {
  72. TRACE2(
  73. TIMER, "DeleteFromForwarder - Source Entry not found : "
  74. "( %x, %x )", pimdmMfes[ dwInd ].dwSource,
  75. pimdmMfes[ dwInd ].dwSrcMask
  76. );
  77. }
  78. RELEASE_GROUP_ENTRY_LOCK_EXCLUSIVE( pge );
  79. }
  80. else
  81. {
  82. TRACE1(
  83. TIMER, "DeleteFromForwarder - Group Entry not found : "
  84. "( %x )", pimdmMfes[ dwInd ].dwGroup
  85. );
  86. }
  87. RELEASE_GROUP_LOCK_SHARED( dwGrpBucket );
  88. }
  89. TRACE0( TIMER, "LEAVING DeleteFromForwarder\n" );
  90. return NO_ERROR;
  91. }
  92. //----------------------------------------------------------------------------
  93. // MFETimerProc
  94. //
  95. // This function is invoked by the MFE timer mechanism.
  96. // It deletes the MFE that has timed out from the source/group table.
  97. // If the MFE is currently present in the Kernel mode forwarder, then
  98. // it is deleted from the forwarder as well.
  99. //
  100. // If this MFE was in use by the forwarder, it will be recreated on the
  101. // next packet miss.
  102. //
  103. //----------------------------------------------------------------------------
  104. VOID
  105. MFETimerProc(
  106. PVOID pvContext,
  107. BOOLEAN pbFlag
  108. )
  109. {
  110. BOOL bUnLock = FALSE, bUnMark = FALSE;
  111. DWORD dwIfBucket, dwErr;
  112. PLIST_ENTRY pleIfHead;
  113. PIF_ENTRY pie = NULL;
  114. PIF_REFERENCE_ENTRY pire = NULL;
  115. PTIMER_CONTEXT ptwc = (PTIMER_CONTEXT) pvContext;
  116. RTM_NET_ADDRESS rnaSource;
  117. RTM_DEST_INFO rdiDestInfo;
  118. PBYTE pbOpaqueInfo = NULL;
  119. PMGM_LOCKED_LIST pmllMfeList;
  120. PROUTE_REFERENCE_ENTRY prreNew = NULL;
  121. TRACE4(
  122. TIMER, "ENTERED MFETimerProc, Source : %x %x, Group : %x %x",
  123. ptwc-> dwSourceAddr, ptwc-> dwSourceMask,
  124. ptwc-> dwGroupAddr, ptwc-> dwGroupMask
  125. );
  126. do
  127. {
  128. //
  129. // delete the reference to this MFE in the route used for its RPF
  130. //
  131. do
  132. {
  133. //
  134. // Lookup route to source
  135. //
  136. RTM_IPV4_MAKE_NET_ADDRESS(
  137. &rnaSource, ptwc-> dwSourceAddr, IPv4_ADDR_LEN
  138. );
  139. dwErr = RtmGetMostSpecificDestination(
  140. g_hRtmHandle, &rnaSource, RTM_BEST_PROTOCOL,
  141. RTM_VIEW_MASK_MCAST, &rdiDestInfo
  142. );
  143. if ( dwErr != NO_ERROR )
  144. {
  145. TRACE2(
  146. ANY, "No Route to source %x, %d", ptwc-> dwSourceAddr,
  147. dwErr
  148. );
  149. break;
  150. }
  151. //
  152. // Lock the dest
  153. //
  154. dwErr = RtmLockDestination(
  155. g_hRtmHandle, rdiDestInfo.DestHandle, TRUE, TRUE
  156. );
  157. if ( dwErr != NO_ERROR )
  158. {
  159. TRACE1( ANY, "Failed to lock dest %x", dwErr );
  160. break;
  161. }
  162. bUnLock = TRUE;
  163. //
  164. // Get the opaque pointer
  165. //
  166. dwErr = RtmGetOpaqueInformationPointer(
  167. g_hRtmHandle, rdiDestInfo.DestHandle, &pbOpaqueInfo
  168. );
  169. if ( dwErr != NO_ERROR )
  170. {
  171. TRACE1( ANY, "Failed to retrieve opaque pointer %x", dwErr );
  172. break;
  173. }
  174. //
  175. // if opaque info is present
  176. //
  177. if ( *( ( PBYTE * ) pbOpaqueInfo ) != NULL )
  178. {
  179. pmllMfeList = ( PMGM_LOCKED_LIST ) *( ( PBYTE *) pbOpaqueInfo );
  180. ACQUIRE_ROUTE_LOCK_EXCLUSIVE( pmllMfeList );
  181. //
  182. // delete the rre from the list
  183. //
  184. if ( FindRouteRefEntry(
  185. &pmllMfeList-> leHead, ptwc-> dwSourceAddr,
  186. ptwc-> dwSourceMask, ptwc-> dwGroupAddr,
  187. ptwc-> dwGroupMask, &prreNew
  188. ) )
  189. {
  190. DeleteRouteRef( prreNew );
  191. }
  192. else
  193. {
  194. TRACE1(
  195. ANY, "Reference does not exist for source %x",
  196. ptwc-> dwSourceAddr
  197. );
  198. }
  199. //
  200. // if there are no more references to this dest, delete the locked list
  201. //
  202. if ( IsListEmpty( &pmllMfeList-> leHead ) )
  203. {
  204. //
  205. // Clear opaque pointer info
  206. //
  207. *( ( PBYTE * ) pbOpaqueInfo ) = NULL;
  208. //
  209. // release list lock
  210. //
  211. RELEASE_ROUTE_LOCK_EXCLUSIVE( pmllMfeList );
  212. MGM_FREE( pmllMfeList );
  213. //
  214. // unmark the dest. Change notifications for this
  215. // dest are no longer required.
  216. //
  217. bUnMark = TRUE;
  218. }
  219. else
  220. {
  221. //
  222. // release the list lock
  223. //
  224. RELEASE_ROUTE_LOCK_EXCLUSIVE( pmllMfeList );
  225. }
  226. dwErr = NO_ERROR;
  227. }
  228. } while ( FALSE );
  229. //
  230. // Unlock dest
  231. //
  232. if ( bUnLock )
  233. {
  234. dwErr = RtmLockDestination(
  235. g_hRtmHandle, rdiDestInfo.DestHandle,
  236. TRUE, FALSE
  237. );
  238. if ( dwErr != NO_ERROR )
  239. {
  240. TRACE1( ANY, "Failed to unlock dest : %x", dwErr );
  241. }
  242. }
  243. //
  244. // Unmark dest
  245. //
  246. if ( bUnMark )
  247. {
  248. dwErr = RtmMarkDestForChangeNotification(
  249. g_hRtmHandle, g_hNotificationHandle,
  250. rdiDestInfo.DestHandle, FALSE
  251. );
  252. if ( dwErr != NO_ERROR )
  253. {
  254. TRACE1( ANY, "Failed to unmark DEST: %x", dwErr );
  255. }
  256. }
  257. //
  258. // delete the MFE and the reference to it in the
  259. // incoming interface entry
  260. //
  261. //
  262. // find If entry for incomng interface of the MFE
  263. //
  264. dwIfBucket = IF_TABLE_HASH( ptwc-> dwIfIndex );
  265. ACQUIRE_IF_LOCK_EXCLUSIVE( dwIfBucket );
  266. pleIfHead = IF_BUCKET_HEAD( dwIfBucket );
  267. if ( !FindIfEntry(
  268. pleIfHead, ptwc-> dwIfIndex, ptwc-> dwIfNextHopAddr, &pie ) )
  269. {
  270. //
  271. // specified incoming interface does not exist,
  272. // this is an error condition. All MFEs using this
  273. // interface should have been deleted when this interface
  274. // was removed. print an error message and quit.
  275. //
  276. TRACE2(
  277. ANY, "MFETimerProc has invalid incoming interface : %x, %x",
  278. ptwc-> dwIfIndex, ptwc-> dwIfNextHopAddr
  279. );
  280. TRACE4(
  281. ANY, "Source : %x %x, Group : %x %x",
  282. ptwc-> dwSourceAddr, ptwc-> dwSourceMask,
  283. ptwc-> dwGroupAddr, ptwc-> dwGroupMask
  284. );
  285. break;
  286. }
  287. LookupAndDeleteYourMfe(
  288. ptwc-> dwSourceAddr, ptwc-> dwSourceMask,
  289. ptwc-> dwGroupAddr, ptwc-> dwGroupMask,
  290. TRUE, NULL, NULL
  291. );
  292. //
  293. // delete reference to this MFE from the incoming refeence list
  294. // for this interface
  295. //
  296. pleIfHead = &pie-> leInIfList;
  297. if ( !FindRefEntry( pleIfHead, ptwc-> dwSourceAddr, ptwc-> dwSourceMask,
  298. ptwc-> dwGroupAddr, ptwc-> dwGroupMask, &pire ) )
  299. {
  300. //
  301. // Apparently this interface is not reference by the specified
  302. // MFE. This is a non-critical error. Log a message too track
  303. // this condition.
  304. //
  305. TRACE2(
  306. ANY, "MFETimerProc : No reference for interface : %x, %x",
  307. ptwc-> dwIfIndex, ptwc-> dwIfNextHopAddr
  308. );
  309. TRACE4(
  310. ANY, "Source : %x %x, Group : %x %x",
  311. ptwc-> dwSourceAddr, ptwc-> dwSourceMask,
  312. ptwc-> dwGroupAddr, ptwc-> dwGroupMask
  313. );
  314. break;
  315. }
  316. RemoveEntryList( &pire-> leRefList );
  317. MGM_FREE( pire );
  318. } while ( FALSE );
  319. RELEASE_IF_LOCK_EXCLUSIVE( dwIfBucket );
  320. //
  321. // release route reference.
  322. //
  323. MGM_FREE( ptwc );
  324. TRACE0( TIMER, "LEAVING MFETimerProc\n" );
  325. }