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.

562 lines
13 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. tcpip\ip\ipmcast.h
  5. Abstract:
  6. Defines and internal structures for IP Multicasting
  7. Author:
  8. Amritansh Raghav
  9. Revision History:
  10. AmritanR Created
  11. Notes:
  12. --*/
  13. #ifndef __IPMCAST_H__
  14. #define __IPMCAST_H__
  15. typedef unsigned long DWORD, *PDWORD;
  16. typedef unsigned char BYTE, *PBYTE;
  17. #include "iproute.h"
  18. #include "iprtdef.h"
  19. #include "debug.h"
  20. #include "ipmlock.h"
  21. #include "ddipmcst.h"
  22. #define is ==
  23. #define isnot !=
  24. #define or ||
  25. #define and &&
  26. //
  27. // Symbolic link into DOS space
  28. //
  29. #define WIN32_IPMCAST_SYMBOLIC_LINK L"\\DosDevices\\IPMULTICAST"
  30. //
  31. // Nifty macro for printing IP Addresses
  32. //
  33. #define PRINT_IPADDR(x) \
  34. ((x)&0x000000FF),(((x)&0x0000FF00)>>8),(((x)&0x00FF0000)>>16),(((x)&0xFF000000)>>24)
  35. //
  36. // We use lookaside lists for a lot of stuff. The following #defines are for
  37. // the depths of the lists
  38. //
  39. #define GROUP_LOOKASIDE_DEPTH 16
  40. #define SOURCE_LOOKASIDE_DEPTH 64
  41. #define OIF_LOOKASIDE_DEPTH 128
  42. #define MSG_LOOKASIDE_DEPTH 8
  43. //
  44. // The number of packets pending per (S,G) entry when queuing is being done
  45. //
  46. #define MAX_PENDING 4
  47. //
  48. // The multicast state
  49. // MCAST_STARTED is again defined in iproute.c and MUST be kept in synch with
  50. // this #define
  51. //
  52. #define MCAST_STOPPED 0
  53. #define MCAST_STARTED 1
  54. //
  55. // The groups are kept in a hash tableof size GROUP_TABLE_SIZE
  56. // GROUP_HASH is the hash function
  57. //
  58. //
  59. // TODO: Need to refine the hash function
  60. //
  61. #define GROUP_TABLE_SIZE 127
  62. #define GROUP_HASH(addr) (addr % GROUP_TABLE_SIZE)
  63. //
  64. // The number of seconds of inactivity after which an SOURCE is deleted
  65. //
  66. #define INACTIVITY_PERIOD (10 * 60)
  67. //
  68. // The default timeout when a MFE is created
  69. //
  70. #define DEFAULT_LIFETIME (1 * 60)
  71. //
  72. // Number of seconds before which another wrong i/f upcall can be generated
  73. //
  74. #define UPCALL_PERIOD (3 * 60)
  75. //
  76. // Some #defines for time/timeticks conversions
  77. //
  78. #define TIMER_IN_MILLISECS (60 * 1000)
  79. #define SYS_UNITS_IN_ONE_MILLISEC (1000 * 10)
  80. #define MILLISECS_TO_TICKS(ms) \
  81. ((LONGLONG)(ms) * SYS_UNITS_IN_ONE_MILLISEC / KeQueryTimeIncrement())
  82. #define SECS_TO_TICKS(s) \
  83. ((LONGLONG)MILLISECS_TO_TICKS((s) * 1000))
  84. //
  85. // We walk only BUCKETS_PER_QUANTUM number of buckets each time the Timer DPC
  86. // fires. This way we do not hog up too much CPU. So currently we walk enough
  87. // so that we need to fire 5 times every INACTIVITY_PERIOD
  88. //
  89. #define BUCKETS_PER_QUANTUM ((GROUP_TABLE_SIZE/5) + 1)
  90. //
  91. // All IOCTLs are handled by functions with the prototype below. This allows
  92. // us to build a table of pointers and call out to them instead of doing
  93. // a switch
  94. //
  95. typedef
  96. NTSTATUS
  97. (*PFN_IOCTL_HNDLR)(
  98. PIRP pIrp,
  99. ULONG ulInLength,
  100. ULONG ulOutLength
  101. );
  102. //
  103. // If an IRP is not available, the forwarder queues the notification message
  104. // onto a list. Then next time an IRP is posted, a message is pulled of the
  105. // list, copied to the IRP and the IRP is then completed.
  106. //
  107. typedef struct _NOTIFICATION_MSG
  108. {
  109. LIST_ENTRY leMsgLink;
  110. IPMCAST_NOTIFICATION inMessage;
  111. }NOTIFICATION_MSG, *PNOTIFICATION_MSG;
  112. //
  113. // The information for the GROUP entry
  114. //
  115. typedef struct _GROUP
  116. {
  117. //
  118. // Link to the hash bucket
  119. //
  120. LIST_ENTRY leHashLink;
  121. //
  122. // Class D IP Address of the Group
  123. //
  124. DWORD dwGroup;
  125. //
  126. // The number of sources on this group. Not really used for anything
  127. // right now.
  128. //
  129. ULONG ulNumSources;
  130. //
  131. // Linked list of sources active on the group. We should make this
  132. // a singly linked list.
  133. //
  134. LIST_ENTRY leSrcHead;
  135. }GROUP, *PGROUP;
  136. typedef struct _OUT_IF OUT_IF, *POUT_IF;
  137. //
  138. // The information for each outgoing interface
  139. //
  140. struct _OUT_IF
  141. {
  142. //
  143. // Link to the list of OIFs hanging off a source
  144. //
  145. POUT_IF pNextOutIf;
  146. //
  147. // Pointer to IP's Interface structure for the correspongind interface
  148. // If DemandDial, then it points to DummyInterface, when disconnected
  149. //
  150. Interface *pIpIf;
  151. //
  152. // The Interface Index.
  153. //
  154. DWORD dwIfIndex;
  155. //
  156. // The NextHopAddr is either the IP Address of the receiver, for RAS client
  157. // and NBMA type interfaces, or the Group Address.
  158. //
  159. DWORD dwNextHopAddr;
  160. //
  161. // The context to dial out with in case of Demand Dial interfaces
  162. //
  163. DWORD dwDialContext;
  164. //
  165. // The following fields are statistics kept for the OIF
  166. //
  167. ULONG ulTtlTooLow;
  168. ULONG ulFragNeeded;
  169. ULONG ulOutPackets;
  170. ULONG ulOutDiscards;
  171. };
  172. typedef struct _EXCEPT_IF EXCEPT_IF, *PEXCEPT_IF;
  173. struct _EXCEPT_IF
  174. {
  175. //
  176. // Link to the list of i/fs that are exceptions to the wrong i/f bit
  177. //
  178. PEXCEPT_IF pNextExceptIf;
  179. //
  180. // We just store the index - it makes a lot of pnp issues go away
  181. //
  182. DWORD dwIfIndex;
  183. };
  184. //
  185. // Information about an active source
  186. //
  187. typedef struct _SOURCE
  188. {
  189. //
  190. // Link on the list of sources hanging off a group
  191. //
  192. LIST_ENTRY leGroupLink;
  193. //
  194. // IP Address of the source
  195. //
  196. DWORD dwSource;
  197. //
  198. // Mask associated with the source. Not used. Must be 0xFFFFFFFF
  199. //
  200. DWORD dwSrcMask;
  201. //
  202. // The index of the correct incoming interface
  203. //
  204. DWORD dwInIfIndex;
  205. //
  206. // The lock for the structure
  207. //
  208. RT_LOCK mlLock;
  209. //
  210. // Pointer to the IP Interface corresponding to the incoming interface
  211. //
  212. Interface *pInIpIf;
  213. //
  214. // The number of outgoing interfaces
  215. //
  216. ULONG ulNumOutIf;
  217. //
  218. // Singly linked list of OIFs
  219. //
  220. POUT_IF pFirstOutIf;
  221. //
  222. // Singly linked list of wrong i/f exception interfaces
  223. //
  224. PEXCEPT_IF pFirstExceptIf;
  225. //
  226. // Number of packets queued
  227. //
  228. ULONG ulNumPending;
  229. //
  230. // The list of queued packets
  231. //
  232. FWQ fwqPending;
  233. //
  234. // Used to refcount the structure
  235. //
  236. LONG lRefCount;
  237. //
  238. // Some stats pertaining to this source
  239. //
  240. ULONG ulInPkts;
  241. ULONG ulInOctets;
  242. ULONG ulPktsDifferentIf;
  243. ULONG ulQueueOverflow;
  244. ULONG ulUninitMfe;
  245. ULONG ulNegativeMfe;
  246. ULONG ulInDiscards;
  247. ULONG ulInHdrErrors;
  248. ULONG ulTotalOutPackets;
  249. //
  250. // The KeQueryTickCount() value the last time this structure was used
  251. //
  252. LONGLONG llLastActivity;
  253. //
  254. // User supplied timeout. If 0, then the source is timed out on the basis
  255. // of inactivity after INACTIVITY_PERIOD
  256. //
  257. LONGLONG llTimeOut;
  258. //
  259. // The time the structure was created
  260. //
  261. LONGLONG llCreateTime;
  262. //
  263. // The state of the source
  264. //
  265. BYTE byState;
  266. }SOURCE, *PSOURCE;
  267. #define UpdateActivityTime(pSource) \
  268. KeQueryTickCount((PLARGE_INTEGER)&(((pSource)->llLastActivity)))
  269. //
  270. // The states of the MFE
  271. //
  272. #define MFE_UNINIT 0x0
  273. #define MFE_NEGATIVE 0x1
  274. #define MFE_QUEUE 0x2
  275. #define MFE_INIT 0x3
  276. //
  277. // The structure of a hash bucket
  278. //
  279. typedef struct _GROUP_ENTRY
  280. {
  281. //
  282. // List of Groups that fall in the bucket
  283. //
  284. LIST_ENTRY leHashHead;
  285. #if DBG
  286. //
  287. // Current number of groups
  288. //
  289. ULONG ulGroupCount;
  290. ULONG ulCacheHits;
  291. ULONG ulCacheMisses;
  292. #endif
  293. //
  294. // One deep cache
  295. //
  296. PGROUP pGroup;
  297. RW_LOCK rwlLock;
  298. }GROUP_ENTRY, *PGROUP_ENTRY;
  299. //
  300. // The LIST_ENTRY macros from ntrtl.h modified to work on FWQ
  301. //
  302. #define InsertTailFwq(ListHead, Entry) \
  303. { \
  304. FWQ *_EX_Blink; \
  305. FWQ *_EX_ListHead; \
  306. _EX_ListHead = (ListHead); \
  307. _EX_Blink = _EX_ListHead->fq_prev; \
  308. (Entry)->fq_next = _EX_ListHead; \
  309. (Entry)->fq_prev = _EX_Blink; \
  310. _EX_Blink->fq_next = (Entry); \
  311. _EX_ListHead->fq_prev = (Entry); \
  312. }
  313. #define RemoveEntryFwq(Entry) \
  314. { \
  315. FWQ *_EX_Blink; \
  316. FWQ *_EX_Flink; \
  317. _EX_Flink = (Entry)->fq_next; \
  318. _EX_Blink = (Entry)->fq_prev; \
  319. _EX_Blink->fq_next = _EX_Flink; \
  320. _EX_Flink->fq_prev = _EX_Blink; \
  321. }
  322. #define RemoveHeadFwq(ListHead) \
  323. (ListHead)->fq_next; \
  324. {RemoveEntryFwq((ListHead)->fq_next)}
  325. #define IsFwqEmpty(ListHead) \
  326. ((ListHead)->fq_next == (ListHead))
  327. #define InitializeFwq(ListHead) \
  328. { \
  329. (ListHead)->fq_next = (ListHead)->fq_prev = (ListHead); \
  330. }
  331. #define CopyFwq(Dest, Source) \
  332. { \
  333. *(Dest) = *(Source); \
  334. (Source)->fq_next->fq_prev = (Dest); \
  335. (Source)->fq_prev->fq_next = (Dest); \
  336. }
  337. //
  338. // The ref count for a SOURCE is set to 2, once because a pointer is saved in
  339. // the group list and once because the function that creates the SOURCE will
  340. // deref it once
  341. //
  342. #define InitRefCount(pSource) \
  343. (pSource)->lRefCount = 2
  344. #define ReferenceSource(pSource) \
  345. InterlockedIncrement(&((pSource)->lRefCount))
  346. #define DereferenceSource(pSource) \
  347. { \
  348. if(InterlockedDecrement(&((pSource)->lRefCount)) == 0) \
  349. { \
  350. DeleteSource((pSource)); \
  351. } \
  352. }
  353. //
  354. // #defines to keep track of number of threads of execution in our code
  355. // This is needed for us to stop cleanly
  356. //
  357. //
  358. // EnterDriver returns if the driver is stopping
  359. //
  360. #define EnterDriver() EnterDriverWithStatus(NOTHING)
  361. #define EnterDriverWithStatus(_Status) \
  362. { \
  363. RtAcquireSpinLockAtDpcLevel(&g_rlStateLock); \
  364. if(g_dwMcastState is MCAST_STOPPED) \
  365. { \
  366. RtReleaseSpinLockFromDpcLevel(&g_rlStateLock); \
  367. return _Status; \
  368. } \
  369. g_dwNumThreads++; \
  370. RtReleaseSpinLockFromDpcLevel(&g_rlStateLock); \
  371. }
  372. #define ExitDriver() \
  373. { \
  374. RtAcquireSpinLockAtDpcLevel(&g_rlStateLock); \
  375. g_dwNumThreads--; \
  376. if((g_dwMcastState is MCAST_STOPPED) and \
  377. (g_dwNumThreads is 0)) \
  378. { \
  379. KeSetEvent(&g_keStateEvent, \
  380. 0, \
  381. FALSE); \
  382. } \
  383. RtReleaseSpinLockFromDpcLevel(&g_rlStateLock); \
  384. }
  385. #if MCAST_REF
  386. #define RefMIF(p) \
  387. { \
  388. InterlockedIncrement(&((p)->if_mfecount)); \
  389. (p)->if_refcount++; \
  390. }
  391. #define DerefMIF(p) \
  392. { \
  393. InterlockedDecrement(&((p)->if_mfecount)); \
  394. DerefIF((p)); \
  395. }
  396. #else
  397. #define RefMIF(p) \
  398. { \
  399. (p)->if_refcount++; \
  400. }
  401. #define DerefMIF(p) \
  402. { \
  403. DerefIF((p)); \
  404. }
  405. #endif // MCAST_REF
  406. #endif // __IPMCAST_H__