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.

3348 lines
113 KiB

  1. StackInfo:
  2. Locks
  3. TmpRef Count
  4. TempRefs: also increment/decrement the StackInfo.TmpRef count -- on exiting top call,
  5. assert if this is nonzero.
  6. LinkObjects(Obj1, Obj2);
  7. Locking -- add option to compute checksum of object and save it. Validate checksup
  8. on unlocking. Also run object-specific validation functions just before unlocking.
  9. typedef struct
  10. {
  11. LOG *pLog;
  12. STATE *pStateHistory;
  13. ULONG Checksum;
  14. ULONG PrevState;
  15. BOOL ValidationFunction;
  16. OBJECTS *pLinkedObjects;
  17. //
  18. // Pointer to the stack record of the thread that currently owns
  19. // the lock on this object, if any. So if a function F expects an object pObj
  20. // to be locked on entry, it can do something like:
  21. // void F(STACKRECORD *pSR, FOOBAR *pObj)
  22. // {
  23. // ASSERT(pObj->pDiags->pSR == pSR);
  24. // }
  25. //
  26. STACKRECORD *pSR;
  27. } OBJECT_DIAGNOSTICS;
  28. typedef struct
  29. {
  30. ULONG Sig;
  31. ULONG State;
  32. LOCK *pLock;
  33. OBJFN pObjFn;
  34. OBJECT_DIAGNOSTICS *pDiags;
  35. ULONG TmpRefs;
  36. ULONG LinkRefs;
  37. TASKLIST *Tasks;
  38. OBJECT *pTmpNext; // Impromptu list.
  39. } OBJECT_HEADER;
  40. Enumeration functions
  41. WeakEnumerateList(list, pfn) -- calls pfn on each item in the list, but releasing
  42. list lock before calling pfn. Since it releases the list lock, it can't simply
  43. process the elements in order.
  44. Several flavors of these enumeration functions:
  45. 1. Enumerate holding list lock and object lock throughout -- strict enumeration.
  46. 2. While(change) {Run-through-items until lock released}
  47. 3. Optimistic, weak enumeration -- maintain next pointer within list structure,
  48. if next pointer matches when you next get list lock, use it, otherwise
  49. 4. Concept of using a "impromptu list", using the pTmpNext field --
  50. optimisically, all the objects that need to be worked on will have their
  51. pTmpNext field unused (set to an illegal value) so can be used to set up
  52. a temporary list -- no needto synchronize access to this list -- only the
  53. creator can use it and must disband it (set pTmpNext members back to the
  54. illegal value) when done. Potential of having multiple pTmpNext fields
  55. to minimize risk of collisions if objects are heavily used.
  56. 5. Enumeration of functions that use only static-data -- no need to claim lock.
  57. 6. Various search/modify funcions -- enumeration could return a single one, or
  58. a (perhaps impromptu) list of objects found by the the function, or
  59. could delete the objects found by the function.
  60. Goal is to not to require user code to have to enumerate lists explicitly,
  61. and to minimize the amount of explicit lock and refcount manipulation.
  62. [Enumeration functions hide any temprefing done]
  63. temporary combo impromptu list + temp-list:
  64. typedef struct
  65. {
  66. OBJECT *pImpromptuList;
  67. SLIST *pOthers; // these ones had the pTmpNext field in use so we
  68. // explicitly create an SLIST of pointers to these.
  69. } ENUMERATION_RESULT;
  70. FreeEnumerationResult(ENUMERATION_RESULT *ER, STACKRECORD *pSR, BOOLEAN fDeref)
  71. {
  72. // run throuch impromptu list, de-refing the tempref.
  73. OBJECT *pObj = pER->pImpromptuList;
  74. while (pObj!=NULL)
  75. {
  76. OBJECT *pNextObj = pObj->pTmpNext;
  77. pObj->TmpNext = ILLEGAL_POINTER;
  78. if (fDeref)
  79. {
  80. Lock(pObj, pSR);
  81. TmpDeref(pObj, pSR);
  82. Unlock(&pObj, pSR); // if object has gone, pObj will be set to NULL.
  83. }
  84. pObj = pNextObj;
  85. }
  86. // Run through pOthers list;
  87. while (pOthers != NULL)
  88. {
  89. Pop(&Others, &pObj);
  90. if (bDeref)
  91. {
  92. Lock(pObj, pSR);
  93. TmpDeref(pObj, pSR);
  94. Unlock(&pObj, pSR); // if object has gone, pObj will be set to NULL.
  95. }
  96. }
  97. }
  98. Locking:
  99. bit in lock struture can be set to prevent unlocking -- preventing a lower-level
  100. function from temporarily unlocking/locking a function
  101. Tasks -- should be associated with the adapter/interface, not each object -- because tasks -- hmm well maybe let each object decide. Timers -- are they tasks?
  102. You can have a "primary state change task pointer " for an object -- at any one time
  103. an object can have only one such task active, although it may vary depending on the
  104. state change involve -- eg ConnectCallTask to move fron unconnected to connected,
  105. and DisconnectCallTask to move from connected to unconnected.
  106. The object's primary state should reflect the task running:
  107. unconnected, connecting*, connected, disconnecting* (* means that a state-change
  108. task is running).
  109. A task can register itself to pend until some other particular task is completed.
  110. When a task completes it's list of other tasks are completed one by one, making
  111. sure locks and inter-task refcounts are properly maintained.
  112. ValidateXXXPacket function -- verifies that internal structures of incoming packets are valid, i.e., fields like sizes and offsets don't point to locations outside the packet.
  113. Concept of Collections of objects -- hides details of how the collection is organized -- hash table, list, hybrid, etc , alloc/dealloc,
  114. Use arrays of pointers freely. Possibly keep a dynamic estimate the the size
  115. of these arrays to allocate.
  116. Dynamic array class:
  117. typedef struct
  118. {
  119. UINT TotalSize;
  120. UINT UsedSize;
  121. PVOID Array; << reallocate if limit is reached, copying from old array.
  122. } DYNAMIC_POINTER_ARRAY;
  123. Could release cached empty resources every minute so.
  124. StateHistory: each entry is a pair: LUID describing where state was changed and
  125. the acutual state.
  126. LinkRecord -- each entry is a pair: LUID describing where the link was made and
  127. the actual object linked to.
  128. 10/09/1998 JosephJ
  129. Local variable used to verify that all locks claimed were released.
  130. Root task id can be used in logging.
  131. Initially label all assert cheking in retail -- log number of asserts hit
  132. in a global variable.
  133. Keep all static info about an object together -- no need to get lock when
  134. looking at that data.
  135. Does it make sense to simply use InterlockedIncrement/Decrement to maintain
  136. refcounts -- not require locking?
  137. 10/09/1998 JosephJ
  138. Review outline
  139. 14 slides
  140. 1394
  141. - 1394 bus review
  142. - 1394 bus, key characteristics (1 slide)
  143. - addressing (1 slide)
  144. - arbitration (1 slide)*
  145. - startup sequence (1 slide)
  146. - 1394 Bus API review
  147. - illustration (1 slide)*
  148. - illustration, list of apis (1 slide)
  149. ip/1394
  150. - spec review
  151. - overiew (1 slide)
  152. - Network-capabile nodes implement the "NETWORK_CHANNELS"
  153. register at hardcoded FIFO address 0xFFFF F000 0234
  154. - special "default" channel used for broadcast
  155. - the default channel is identified after bus reset and
  156. written to the NETWORK_CHANNELS register of all network-capable
  157. nodes.
  158. - encapsulation format (1 slide)
  159. - arp packet (1 slide)
  160. - mcap request/response packet (1 slide)
  161. - our architecture
  162. - goals (1 slide)
  163. - NT5 & W98 support
  164. - multi-protocol support
  165. - sound design, emphasis on testability and diagnostic support
  166. - Available to public when NT5 ships
  167. - overview (1 slide)*
  168. -diagram showing components
  169. - arp/mpcm interface details (1 slide)
  170. - mpcm/bus interface details (1 slide)*
  171. - installation (1 slide)*
  172. - testing & diagnostics (1 slide)
  173. - 1394-specific miniport tests
  174. - arp module tested using tcp/ip tests
  175. - (maybe) component tests for segmentation-and-reassembly
  176. - netmon support
  177. 11/06/1998 JosephJ
  178. Resource tracking
  179. each object has a bitmap of "static" resources plus a pointer to a table
  180. which provide more info about these static resources.
  181. typedef struct
  182. {
  183. ULONG uTag;
  184. PFN_RESOURCE_HANDLER pfnHandler;
  185. } RESOURCE_TABLE_ENTRY;
  186. typedef struct
  187. {
  188. ULONG uTag;
  189. UINT uNumEntries;
  190. RESOURCE_TABLE_ENTRY *pTable;
  191. } RESOURCE_TABLE;
  192. RESOURCE_TABLE
  193. GlobalResourceTable =
  194. {
  195. {'NtOb', arpDevObjHandler},
  196. {'IpRg', arpIPRegisterHandler}
  197. {'NdPr', arpProtocolRegistrationHandler}
  198. }
  199. AdapterResourceTable
  200. InterfaceResourceTable
  201. ResourceManagement
  202. RmAllocateResource(
  203. RESOURCE_HEADER *pParentResource,
  204. );
  205. typedef NDIS_STATUS RM_STATUS;
  206. arpDevObjHandler(
  207. cmd
  208. )
  209. {
  210. NTSTATUS Status;
  211. if (cmd->op == ALLOCATE)
  212. {
  213. CreateFile
  214. CreateSymbolicLink
  215. }
  216. else if (cmd->op == FREE)
  217. {
  218. }
  219. else if (cmd->op == Dump)
  220. {
  221. }
  222. }
  223. typedef struct RESOURCEMAP
  224. {
  225. ULONG Map;
  226. }
  227. RmAllocateResource
  228. RmSyncAllocResource
  229. RmFreeResource
  230. RmSyncFreeResource
  231. RmSyncFreeAllResources
  232. RmLockResource
  233. RmUnlockResource
  234. RmUnlockAllResources
  235. RmLinkResources
  236. RmUnlinkResources
  237. RmTmpReferenceResource
  238. RmAllocateCollection
  239. RmEnumerateCollection
  240. RmFreeCollection
  241. RmSearchCollection
  242. RmAddItemToCollection
  243. RmRemoveItemFromCollection
  244. RmInvalidateItemInCollection
  245. RmValidateItemInCollection
  246. RmAllocTask
  247. RmFreeTask
  248. RmStartSubTask
  249. RmCompleteTask
  250. RmAbortTask
  251. RmDumpTask
  252. RmChainTask
  253. RM_STATUS
  254. RmAllocateResource(
  255. pParentResource,
  256. ULONG ResourceID,
  257. );
  258. pParentResource->AllocatedResources |= (1<<ResourceID);
  259. CMD Cmd;
  260. Cmd.Op = ALLOCATE;
  261. Cmd.Parent = pParentResource;
  262. status = (pParentResource->ResourceTable->Table[ResourceID]) (
  263. &Cmd
  264. );
  265. ULONG RmFreeResource(
  266. pParentResource,
  267. ULONG ResourceID
  268. )
  269. Resource-tracking -- use variable-length hash table:
  270. Candidates for hash table--
  271. ArpCache, DbgResourceTrackingCache,
  272. read or write lock
  273. - update stats
  274. - compute hash
  275. SLIST_ENTRY pHash->Table[hash]
  276. for(... pentry = pentry->next)
  277. {
  278. if(*(UINT)(pb+key_offset) != Key)
  279. {
  280. if (comparison-function(....))
  281. {
  282. break;
  283. }
  284. }
  285. }
  286. if (found)
  287. {
  288. }
  289. Refcounting: increments tmpref before returning a found item.
  290. LinkObjects(pA, pB, uint relationID)
  291. {
  292. pA->ref++
  293. pB->ref++
  294. #if DBG
  295. ASSERT(pA->root == pB->root)
  296. {
  297. Lock(pA->root->tracker_lock);
  298. RegisterResource(pA, <link relation, relationID, pB);
  299. RegisterResource(pB, <inv-link-relation, relationID, pA);
  300. Unlock(pA->root->tracker_lock);
  301. }
  302. #endif
  303. }
  304. 12/03/1998
  305. Note that the win98 version specifies our bind-adapter in the ndis protocol
  306. characteristics, while the nt version specifies it in the call to IPRegisterARP.
  307. 12/18/1998
  308. Rm support for "groups" -- groups (lists) of objects with one primary key to
  309. search, and whose life is tied to their presence in the group. Rich enumeration
  310. functionality.
  311. RmAllocateGroup
  312. RmLookUpObjectInGroup
  313. RmDeleteAllObjectsInGroup(pGroup,pTask)
  314. RmDeallocateGroup
  315. Locking:
  316. tasks-allocators, groups, etc, have their own locks, which are
  317. only used by the rm apis, and never locked *across* APIS. This allows
  318. them to be used independently of any other locks that may be held.
  319. For simplicity, we can have a single "rm_private_lock" for this purpose.
  320. 1/11/1999 JosephJ
  321. -- preallocate critical tasks so we don't get stuck while unloading.
  322. 1/16/1999 JosephJ
  323. -- think about using the resource tracking apis, as well as implementing the
  324. extra checking in the LinkObjects code above.
  325. 2/8/1999 JosephJ
  326. Re-think the allocation of tasks ...
  327. - allocation handled by user, allowing user to embed tasks in objects, add
  328. specialized fields and so on.
  329. - no "private context" -- any private context is expected to be allocated by
  330. the user. Typically each task consists of the standard task header followed
  331. by any private data.
  332. Todo:
  333. 1. revise task apis to reflect above change.
  334. 2. revise tests
  335. 2/11/1999 JosephJ
  336. Decide to claim both pOtherTask and pTask's locks (in order) in
  337. PendTaskOnOtherTasks. It is possible to deadlock if pTaskA tries to pend to
  338. pend on pTaskB at the same time that pTaskB tries to pend on pTaskA, but that
  339. is not a valid thing to try to do anyway.
  340. Of course, one thing we can do is to 1st lock the pointer that is greater
  341. in value.
  342. Status = arpInitInterface(pIF, pSR);
  343. Status = arpCallIpAddInterface(
  344. E:\nt\public\sdk\inc\ipexport.h 2B2A == General failure.
  345. ip\init.c:
  346. //
  347. // Return the other handler pointers
  348. //
  349. *IpAddInterfaceHandler = IPAddInterface;
  350. *IpDelInterfaceHandler = IPDelInterface;
  351. *IpBindCompleteHandler = IPBindComplete;
  352. #if P2MP
  353. KdPrint(("IPRegisterArp: Passing Link callups\n"));
  354. *IpAddLinkHandler = IPAddLink;
  355. *IpDeleteLinkHandler = IPDeleteLink;
  356. #endif
  357. *IpChangeIndex = IPChangeIfIndexAndName;
  358. *IpReserveIndex = IPReserveIndex;
  359. *IpDereserveIndex = IPDereserveIndex;
  360. Failing in IPAddInterface in call to IPAddNTE.
  361. In IPAddNTE, *after* calling RegRtn (which is our DynRegister, which succeeds)
  362. Hit the following:
  363. A13: !ASSERT( Status != NDIS_STATUS_PENDING ) L:1123,F:rm.c
  364. Fix:
  365. remove asserts and dealocate(task) if state == ENDING.
  366. 2/22/1999 JosephJ Fast Send Path
  367. Use of RouteCacheEntry.
  368. We (arp module) has use of RouteCacheEntry.rce_context, (private\inc\ip.h)
  369. which is of size RCE_CONTEXT_SIZE, which is defined to be 2*sizeof(void*).
  370. So we can hold 2 pointers there.
  371. RCE is valid memory from the point it shows up in our iptransmit function until
  372. it is invalidated by a call to our invalidate-rce function.
  373. In order to make the fast-send-path as fast as possible, but still allow for
  374. invalidating the RCE when the mapping from IP->VC breaks down, we'll use the
  375. RCE as in atmarpc.sys: it contains (a) ptr to a pIP structure and (b) pointer
  376. to the next RCE entry associated with the same pIP structure.
  377. However, to speed things up, pIP will contain a pfnTransmit function which will
  378. be set to a fast-transmit-function when conditions are ideal (mapping from
  379. pIP to pVC exists, valid pVC). pfnTransmit will be set to other transmit
  380. functions if the conditions are less-than-ideal. These functions will queue
  381. the packet if registration is in progress, or may fail the packet if IP entry
  382. is in the process of being aborted.
  383. 2/23/1999 JosephJ Task params
  384. One option is to initialize the private portion of the task with whatever paramters
  385. required *before* calling RmStartTask -- no need to pass in those paramters
  386. using the single UserParam field.
  387. 2/23/1999 JosephJ RmUnloadAllObjecsInGroup:
  388. New rm function RmUnloadAllObjecsInGroup:
  389. internally creates a task and in the context of that tasks, unloads all the
  390. objects in the group one-by-one.
  391. One cool feature is that if RmUnloadAllObjectsInGroup is called several
  392. times on the same group, the "correct" thing happens: all will complete after
  393. all the objects are unloaded.
  394. 2/23/1999 JosephJ Timers
  395. To get exactly-once and proper abort semantics, consider calling the timer
  396. handler with the object's lock held.
  397. 2/29/1999 JosephJ
  398. TODO:
  399. -- create groups for the following:
  400. - local-addresses (including bcast and mcast entries)
  401. - destinations (both channels and fifos)
  402. Note: Vcs are owned by destination only.
  403. Basic ARP process:
  404. Lookup IP address;
  405. if (not yet registered) {
  406. queue packet on ip entry;// discard early pkts if queue full.
  407. if (no registration in progress)
  408. {
  409. begin registration task}
  410. }
  411. }
  412. else // registered
  413. {
  414. get destination object;
  415. if (destination has vc)
  416. {
  417. if (not yet connected)
  418. {
  419. queue on vc to be connected;
  420. }
  421. else if (closing down)
  422. {
  423. discard packet
  424. }
  425. else
  426. {
  427. send packet on vc
  428. }
  429. }
  430. else
  431. {
  432. // destination has no vc
  433. if (destination blacklisted)
  434. {
  435. discard packet
  436. }
  437. else
  438. {
  439. queue packet on distination;
  440. {create vc}
  441. {initiate task to make call on vc}
  442. }
  443. }
  444. }
  445. 3/1/1999 JosephJ Summary of associations:
  446. Instead of separately tracking who's linked to who, who is a parent/child of who,
  447. which tasks are running, etc., and also to allow arbitrary associations to be made
  448. (and later unmade), I introduced the concept of "associations", which are
  449. triples: The association is defined by the triple
  450. (Entity1, Entity2, AssociationID) -- only ONE such tuple may
  451. be registered at any time with object pParentObject.
  452. Note: It is valid for both of the following to be registered at the same
  453. time: (a, b, 1) and (a, b, 2)
  454. No association should exist at the point the object is deleted.
  455. Associations are implemented using a hash table, which is located in
  456. the diagnostic-info part of an object.
  457. 3/1/1999 JosephJ Associations and debugprinting
  458. Added support for printing information about all outstanding associations for
  459. a particular object. The format of the display is controlled by the caller
  460. of RmDbgAddAssociation -- the caller passes in an optional format string to
  461. be used when displaying the association.
  462. ARPCB_VC, *PARPCB_VC;
  463. ARPCB_DEST, *PARPCB_DEST;
  464. ARPCB_LOCAL_IP, *PARPCB_LOCAL_IP;
  465. ARPCB_DEST_IP, *PARPCB_DEST_IP;
  466. 3/2/1999 Josephj KD extensions
  467. !rm obj 0x838c7560 -- object
  468. !rm tsk 0x838c7560 -- task
  469. !rm asc 0x838c7560 -- associations
  470. !rm grp 0x838c7560 -- group
  471. !rm sr 0x838c7560 -- stack record
  472. !rm obj 0x838c7560
  473. Object 0x838c7560 (LocalIP)
  474. Hdr
  475. Sig :A13L State:0xc4db69b3 Refs:990
  476. pLock: 0x838c7560 pSIinfo:0xfdd0a965 pDInfo :0xd54d947c
  477. pParent: 0x2995941a pRoot:0x060af4a8 pHLink :0xce4294fe
  478. HdrSize: 0x123 Assoc:909
  479. !rm tsk 0x838c7560 -- task
  480. Object 0x838c7560 (Task: Initalize IF)
  481. Hdr
  482. Sig :A13L State:0xc4db69b3 Refs:990
  483. pLock: 0x838c7560 pSIinfo:0xfdd0a965 pDInfo :0xd54d947c
  484. pParent: 0x2995941a pRoot:0x060af4a8 pHLink :0xce4294fe
  485. HdrSize: 0x123 Assoc:909
  486. TskHdr
  487. pfn: 0x5399424c State:0x812d7211(IDLE) SCtxt:0x050eefc4
  488. pBlkTsk:0x377c74bc lnkFellows:0x2b88126f
  489. Pending Tasks
  490. 0x84215fa5 0xb51f9e9e 0x9e954e81 0x696095b9
  491. 0x0c07aeff
  492. !rm asc 0x9ba265f8
  493. Associations for object 0x838c7560 (LocalIP):
  494. Child of 0x010091A0 (Globals)
  495. Parent of 0x00073558 (Task2)
  496. Parent of 0x00073920 (Task3a)
  497. Parent of 0x000739F8 (Task3b)
  498. !rm grp 0x838c7560
  499. Group 0x4d650b98 (LocalIP Group) of object 0x11eafd78 (Interface)
  500. Num:11 State:ENABLED pSInfo: 0x944b6d1b pULTsk: 0x8c312bca
  501. Members:
  502. 0x8db3267c 0xa639f663 0x8f3530a6 0xa4bfe0b9
  503. 0x995dd9bf 0x61e1344b 0xd6323f50 0x606339fd
  504. 0x2e8ed2a4 0x62e52f27 0xa82b59ab
  505. !rm sr 0x838c7560
  506. Stack Record 0x838c7560
  507. TmpRefs: 2
  508. HeldLocks:
  509. 0xe916a45f 0x23d8d2d3 0x5f47a2f2
  510. 03/03/1999 JosephJ
  511. All the above dbg extensions are implemented to a T (well I don't
  512. dump the list of held locks).
  513. Associations work like a charm.
  514. The amazing thing is that after I got this to work with the user-mode
  515. test environment, it worked perfectly in the real kd environment -- everything
  516. was just perfect, including the rather hairy dumping of associations.
  517. Following is real output from kd:
  518. kd> !rm obj 0xFF8EFD68
  519. Object 0xFF8EFD68 (INTERFACE)
  520. Hdr:
  521. Sig:0x69333141 State:0x80000001 Refs:0x00000002
  522. pLock:0xFE723990 pSInfo:0xFDB22438 pDInfo:0xFF94E628
  523. pParent:0xFE723948 pRoot:0xFDB22480 pHLink:0xFF8EFDA8
  524. HdrSize:0x00000048 Assoc:5
  525. kd> !rm asc 0xFF8EFD68
  526. Associations for 0xFF8EFD68 (INTERFACE):
  527. IP IF Open
  528. Child of 0xFE723948 (Adapter)
  529. Owns group 0xFF8EFDF8 (LocalIp group)
  530. Owns group 0xFF8EFE3C (RemoteIp group)
  531. Owns group 0xFF8EFE80 (Destination group)
  532. ....
  533. kd> !rm grp 0xFE6A1CB8
  534. Group 0xFE6A1CB8 (LocalIp group) of object 0xFE6A1C28 (INTERFACE)
  535. Num:0x00000000 State:ENABLED pSInfo:0xf926d350
  536. pULTsk:0x00000000
  537. No members.
  538. 03/04/1999 JosephJ MCast address adds/removes.
  539. From IP/ATM code, we see that we may get multiple adds for the same
  540. address, and hence we need to maintain ref counts on these entries.
  541. This is not the case for unicast addresses.
  542. Since I am treating all types of IP addresses the same as far as
  543. liveness is concerned, I will keep add/remove ref counts for all types.
  544. 03/04/1999 JosephJ Adding custom information to !rm obj, tsk
  545. Some way to identify a function to call (in user mode) that knows how
  546. to print custom information about the specific instance.
  547. Eg:
  548. > tsk 0x000732C8
  549. Task 0x000732C8 (TaskO2)
  550. Hdr:
  551. Sig:0x6154524d State:0x80000000 Refs:0x00000004
  552. ...
  553. Pending tasks:
  554. 0x00073848 0x000736D0
  555. Waiting for NdisInitializeAdapter(MP=0x923450900) to complete.
  556. 03/04/1999 JosephJ "Verbose" mode for grp
  557. Currently, only the pointers to the mebers are printed, 4 to a line.
  558. In verbose mode, switch to one line per member, and allow custom printing
  559. of member information. Eg (for LocalIP entries):
  560. 0xFE723948 169.240.233.001 RESOLVED
  561. 03/04/1999 JosephJ ASSERT_SAME_LOCK_AS_PARENT
  562. Defined the above macro to assert the case that an object uses the same
  563. lock as it's parent.
  564. 03/04/1999 JosephJ Verifying things aren't changed when an object is unlocked.
  565. Partial support for is already in the RM api's (the pfnVerifier function stuff).
  566. We should condider actually using it earlier on the development phase so
  567. that we catch problems sooner.
  568. We need to change RM api's (RmLock/UnlockObject) so that they
  569. compute a checksum on entry and exit -- see earliest entry in this log.
  570. Basic algorithm:
  571. RmWriteLockObject(pObj,)
  572. {
  573. Lock object
  574. CurrentState = pfnObjVerifier(pObj, fLock==TRUE);
  575. ASSERT(CurrentState == pObj->LastSavedState);
  576. }
  577. RmUnlockObject(pObj)
  578. {
  579. pObj->LastSavedState = pfnObjVerifier(pObj, fLock=FALSE);
  580. Unlock object.
  581. }
  582. 03/04/1999 JosephJ Comments on LocID
  583. LocID is a 32-bit (typically random) number that identifies a point in the
  584. source code. I prefer this to saving line/file numbers because:
  585. 1. 32-bit number is easier to carry around.
  586. 2. It's more robust w.r.t. code changes -- simply grep for that number.
  587. On the downside, you need to make sure that the LocIDs are unique -- easy
  588. to screq up if you cut and paste code. In unimodem, I has a very elaborate scheme
  589. that would scan all sources and build a logging C++ file which would only compile
  590. if the IDs were unique. A simpler script could extract the places where
  591. these are declared and do a simple check for uniqueness.
  592. 03/04/1999 JosephJ Problems with deadlock when using Groups.
  593. Unfortunately, specifying the RM_LOCKED option could cause deadlock, especially
  594. the object being looked up does not have its own lock but instead is using
  595. its parent's lock. Need to find the proper solution to this.
  596. 03/04/1999 JosephJ Size of the context passed in ArpIpQueryInfo.
  597. Traced this (looking at ip and tcp sources and index1) to
  598. private\inc\tdiinfo.h (DON'T use tcpipmerge\h\tdiinfo.h, which is for win9x).
  599. The structure used is TCP_REQUEST_QUERY_INFORMATION_EX.Context, which
  600. is defined as:
  601. #define CONTEXT_SIZE 16
  602. ULONG_PTR Context[CONTEXT_SIZE/sizeof(ULONG_PTR)];
  603. So basically we have 4 DWORDS, which is 4ptrs in 32-bit and 2ptrs in
  604. 64-bit.
  605. 03/04/1999 JosephJ Implementing ArpIpQueryInfo.
  606. We need a mechanism that will deal with our plan to use
  607. dynamically-resizable hash tables.
  608. Solution: simply put the IP address in the context.
  609. We can add an Rm API: RmGetNextObjectInGroupByKey(,...pKey...), which
  610. will lookup an object that matches pKey and gets the object after it.
  611. It fails if it doesn't find the object with pKey, or if there is no object
  612. after the object with the given key, OR if there has been a hash
  613. table resize. How do we know if there has been a hash table resize? Hmm....
  614. We may want to add a UINT HashTableGeneration to GROUP, and add the
  615. Generation to the context.
  616. 03/04/1999 JosephJ Populating the arp cache with static arp entries.
  617. Good to do this for it's final functionality but also to get
  618. the bootstrap going.
  619. For now, just get them from an internally-compiled table.
  620. Later think about adding them via the standard mechanism.
  621. 03/04/1999 JosephJ Implementing ArpIpQueryInfo (contd...)
  622. Following are the structures returned. atmarpc.sys (arpif.c) simply
  623. declared a local char array of sizeof(IFEntry) -- since it's clearly
  624. the largest. We should probably define a union -- see later down..
  625. #define MAX_PHYSADDR_SIZE 8
  626. private\inc\llinfo.h
  627. typedef struct IPNetToMediaEntry {
  628. ulong inme_index;
  629. ulong inme_physaddrlen;
  630. uchar inme_physaddr[MAX_PHYSADDR_SIZE];
  631. ulong inme_addr;
  632. ulong inme_type;
  633. } IPNetToMediaEntry;
  634. private\inc\ipinfo.h
  635. typedef struct AddrXlatInfo {
  636. ulong axi_count;
  637. ulong axi_index;
  638. } AddrXlatInfo;
  639. private\inc\llinfo.h
  640. typedef struct IFEntry {
  641. ulong if_index;
  642. ulong if_type;
  643. ulong if_mtu;
  644. ulong if_speed;
  645. ulong if_physaddrlen;
  646. uchar if_physaddr[MAX_PHYSADDR_SIZE];
  647. ulong if_adminstatus;
  648. ulong if_operstatus;
  649. ulong if_lastchange;
  650. ulong if_inoctets;
  651. ulong if_inucastpkts;
  652. ulong if_innucastpkts;
  653. ulong if_indiscards;
  654. ulong if_inerrors;
  655. ulong if_inunknownprotos;
  656. ulong if_outoctets;
  657. ulong if_outucastpkts;
  658. ulong if_outnucastpkts;
  659. ulong if_outdiscards;
  660. ulong if_outerrors;
  661. ulong if_outqlen;
  662. ulong if_descrlen;
  663. uchar if_descr[1];
  664. } IFEntry;
  665. union
  666. {
  667. AddrXlatInfo AddrInfo;
  668. IPNetToMediaEntry ArpEntry;
  669. IFEntry Stats;
  670. } InfoBuf;
  671. ...
  672. Need to get the adapter info -- stuff in arpGetAdapterInfo, to
  673. fill out the above structure.
  674. WIN98: Win98 doesn't like more than 6 chars for IFEntry.if_physaddrlen,
  675. although it does tolerate more (at-least-7) in AddrXlatInfo.inme_pysaddrlen.
  676. WIN98 also takes at-leat-7 for LLIPBindInfo.lip_addrlen (IpAddinterfaceRtm)
  677. NT pIFEntry->if_physaddr <- set to MAC address (6 bytes) + SAP Sel(1 byte)
  678. W98 pIFEntry->if_physaddr <- set to MAC address (6 bytes, munged due toELAN)
  679. LLIPBindInfo.lip_addr <- set to ATMAddress starting at ESI offset (7 bytes)
  680. IPNetToMediaEntry.inme_physaddr <- dest atm addr at ESI offset (y bytes)
  681. Any reason why pIFEntry->if_physaddr would be different from
  682. BindInfo->lip_addr?
  683. MacAddress seems to be used ONLY for pIFEntry.
  684. 03/05/1999 JosephJ Thoughts on logging..
  685. - Log fixed-sized entries (taken from a global list, just like the association
  686. free-list -- well associations today used alloc's but that'll change).
  687. - Logs maintained per-object.
  688. - Log-entry recovery strategy:
  689. -- all object's log entries deleted when the object is deleted.
  690. -- If global log entry pool goes empty, then...
  691. if (the object's log is larger than some threshold)
  692. {
  693. we reuse the oldest log entry for that object
  694. }
  695. else
  696. {
  697. the oldest log entry in the globally-threaded list
  698. of log entries entry is reclaimed.
  699. }
  700. - KD extensions as well as IOCTLs to display an object' state and logs.
  701. 03/05/1999 JosephJ Ideas on using the same code for kd extensions AND IOCTL dump
  702. Seems possible to use the same code to both collect and dump information in KD
  703. and from a user mode app that does IOCTLs to the device object representing
  704. the driver -- after all, conceptually the same thing is going on: there
  705. is a memory-space transition.
  706. This is well worth exploring since then once you write an extension, the
  707. IOCTL support will essentially come for free!
  708. Unfortunately, we shouldn't allow the user mode app to read arbitrary
  709. memory from kernel-mode -- so we have to think about this some more.
  710. 03/05/1999 JosephJ Strategy for managing ip/1394 encapsulation header buffers
  711. Keep a fixed-sized, pre-initalized pool of these, and simply queue the packet
  712. if you run out. More precicely, the send-path would look like:
  713. Fast path case (vc available for sending, and no pkts queued waiting for
  714. bufs):
  715. if (can-back-fill)
  716. {
  717. backfill and send
  718. }
  719. else
  720. {
  721. if (allocate header buf succeeds)
  722. {
  723. chain and send
  724. }
  725. else
  726. {
  727. switch send handler to slow path;
  728. queue pkt in waiting-for-bufs queue
  729. }
  730. }
  731. 03/05/1999 More corny locking problems when parent and child share a lock.
  732. Sometimes we'd like to do the following:
  733. Lock(pParentObj)
  734. ......
  735. Create pChildObject
  736. call Func(pChildObject); // pChildObject's lock released on return from Func
  737. So RmWriteLock gets called with pParent, and RmUnlock gets called with pChild.
  738. But RmWrite (extra-checking-version) saves some context of the pParent object,
  739. so that effectively, it uses the parent's context when freeing the lock;
  740. So the parent's verifier is called, not the child's.
  741. This will actually work, but is quite strange behavior which is not at all
  742. obvious by the call to RmUnlockObject(pChild).
  743. We'll live with this for now -- see for example the code in
  744. ArpIpAddAddress.
  745. But there is a problem when we implement verification of state preservation
  746. across locking: Since pChild's verifier function is not called on exit,
  747. we will assert the NEXT time we try to lock pChild!
  748. The fix is for RmUnlockObject to call the verifier for pParent(UNLOAD),
  749. followed by calling verifier for pChild(LOAD), if it detects that
  750. the object being unlocked is not the same as the object being locked
  751. (it can do this by looking into the LOCKING_INFO context).
  752. A bit tricky, but this is fairly clear semantics.
  753. 03/05/1999 Locking problems, continued...
  754. Implemented new function RmDbgChangeLockScope which does the things
  755. described above (only if RM_EXTRA_CHECKING is defined, of course).
  756. Also now RmUnlockObject checks to make sure that the
  757. RM_LOCKING_INFO.pVerifierContext is a pointer to the object being unlocked.
  758. 03/07/1999 JosephJ Thoughts on location of kdextension sources
  759. To help things stay in synch, consider keeping a subdir .\kd, which has
  760. the kd extension code that is sensitive to privately-defined structures.
  761. This code is actually compiled as part of the debug build of the main component
  762. -- this will force the code to stay in synch.
  763. The kd extension dll (which needs to be in another directory)
  764. would need to includes these files by reaching over into this directory.
  765. 03/07/1999 JosephJ Need to move rm-private state out of Hdr.State
  766. Since object-specific info is protected by pHdr->pLock, while rm-private state
  767. is protected by the pHdr->RmPrivateLock, we can't have both of them use
  768. pHdr->State; So we need to move rm-private state into its own DWORD.
  769. This DWORD is dwRmState;
  770. 03/07/1999 JosephJ Registering root objects with RM
  771. We need to have a mechanism to register root objects with RM, so that multiple
  772. components (eg. arp1394 and nic1394) can use the RM apis.
  773. Currently, the primary reason for doing so is to maintain separate global logs
  774. for each component. Another parameter is the "InterfaceGuid" to uniquely identify
  775. the component to match up with object-specific information for KD extension
  776. dumping. More things may need to be added on a per-component basis.
  777. We have to do some work/re-specification of APIs to allow for a single binary
  778. that would work for components which have/have-not defined RM_EXTRA_CHECKING.
  779. typedef struct
  780. {
  781. GUID InterfaceGUID;
  782. #if RM_EXTRA_CHECKING
  783. UINT NumDbgLogEntries;
  784. PFN_RM_MEMORY_DEALLOCATOR pfnDbgLogBufDeallocator;
  785. #endif // RM_EXTRA_CHECKING
  786. } RM_GLOBAL_INFO, *PRM_GLOBAL_INFO;
  787. typedef struct
  788. {
  789. RM_OBJECT_HEADER Hdr;
  790. PRM_ROOT_INFO pRootInfo;
  791. LIST_ENTRY linkRegisteredEntries;
  792. } RM_ROOT_OBJECT_HEADER;
  793. RmInitializeRootObject(
  794. IN PRM_ROOT_OBJECT_HEADER,
  795. PRM_ROOT_INFO pRootInfo;
  796. ...
  797. )
  798. {
  799. if (InterlockedCompareExcahnge(RmGlobal_Initialized, 1, 0))
  800. {
  801. // Do one-time initialization, including lock and list of
  802. // global entries.
  803. }
  804. // Add component to global list of registered components.
  805. }
  806. RmDeinitializeRootObject(
  807. IN PRM_ROOT_OBJECT_HEADER,
  808. ...,
  809. )
  810. {
  811. // look for an deinitialize component
  812. // with global lock held
  813. if (last-registered-entry)
  814. {
  815. // free any globally allocated resources, except of
  816. // course the global lock itself.
  817. }
  818. }
  819. 03/07/1999 JosephJ Thoughts on the obect verifier function...
  820. To help ensure that no one is READING a piece of data when the object lock
  821. is not held, the verifier can reverse the bits of the data on unlocking and
  822. flip them back on locking.
  823. 03/08/1999 JosephJ Implemented object logging!
  824. Key features:
  825. -- Fixed-sized log entries (RM_DBG_LOG_ENTRY)
  826. -- Each entry has two LIST_ENTRYs: to be a link in the object's list
  827. of log entries and the global list of log entries.
  828. -- Logging to the object consists of allocating a log entry and inserting
  829. it in the head of the object's log list and the global log list.
  830. -- On deallocation of the object, we free all the entries in object's
  831. log.
  832. -- Provision to add a buffer to the entry which is freed when the entry
  833. is removed from the log -- for cases where the things being logged may
  834. go away when the object is still alive.
  835. Types:
  836. PFN_DBG_DUMP_LOG_ENTRY -- allows customized display of log entries
  837. RM_DBG_LOG_ENTRY -- the fixed-size log entry.
  838. Functions:
  839. RmDbgLogToObject -- make an entry in the object's log
  840. RmDbgPrintObjectLog -- dump the object log to dbgout
  841. RmDbgPrintGlobalLog -- dump the global log to dbgout.
  842. In order to initialize the global log list, I added the following two RmApis:
  843. RmInitializeRm -- call 1st, before any other rm api.
  844. RmDeinitializeRm -- call after last rm api, and all async activity complete.
  845. The above functionality is all implemented and tested via the usermode tests
  846. in .\tests.
  847. Note: Once multiple components are using the RM api's, we'll need a more
  848. sophisticated registration mechanism -- see 07/07/1999 entry "Registering root
  849. objects with RM"
  850. 03/09/1999 JosephJ Consider making init functions fail etc if associated object is
  851. deallocated.
  852. We could fail RmInitializeHeader/Task if the parent object is in the deallocated
  853. state. However, I'm not sure if it buys us anything -- after all, as soon as
  854. you return from successful RmInitializeHeader, someone could call
  855. RmDeallocateObject on the parent, and you get the same result as if the
  856. parent was already deallocated and we didn't check in RmInitializeHeader.
  857. What we really want is exact semantics on unloading/deallocating objects.
  858. 03/09/1999 Special allocator for unload-related tasks
  859. It's ugly for task allocation to fail as part of unloading an object.
  860. To address this, we should consider special allocation/deallocation for
  861. unload tasks, that must be called at passive level and will block until
  862. a free unload-task becomes available.
  863. 03/10/1999 JosephJ "Arp -a" works; Sample kd and arp -a output...
  864. kd> !e:\nt\kd\a13kd\a13kd.rm obj 0xFE65F008
  865. Loaded e:\nt\kd\a13kd\a13kd extension DLL
  866. Object 0xFE65F008 (INTERFACE)
  867. Hdr:
  868. Sig:0x49333141 State:0x00000002 Refs:0x0000000d
  869. pLock:0xFE7009F4 pSInfo:0xFD8C1490 pDInfo:0xFF8C9AE8
  870. pParent:0xFE7009A8 pRoot:0xFD8C14E0 pHLink:0xFE65F04C
  871. HdrSize:0x0000004c Assoc:16
  872. RmState: O_ALLOC
  873. kd> !rm asc 0xFE65F008
  874. Associations (50 max) for 0xFE65F008 (INTERFACE):
  875. IP IF Open
  876. Child of 0xFE7009A8 (Adapter)
  877. Owns group 0xFE65F0CC (LocalIp group)
  878. Owns group 0xFE65F110 (RemoteIp group)
  879. Owns group 0xFE65F154 (Destination group)
  880. Parent of 0xFF8D7288 (RemoteIp)
  881. Parent of 0xFE691568 (Destination)
  882. Parent of 0xFE6686C8 (RemoteIp)
  883. Parent of 0xFF92A648 (Destination)
  884. Parent of 0xFF8EE868 (RemoteIp)
  885. Parent of 0xFF92A848 (Destination)
  886. Parent of 0xFE663268 (RemoteIp)
  887. Parent of 0xFE667CE8 (Destination)
  888. Parent of 0xFF8F18C8 (LocalIp)
  889. Parent of 0xFF8B99C8 (LocalIp)
  890. Parent of 0xFF8B9EA8 (LocalIp)
  891. kd> !rm log 0xFE65F008
  892. Log entries for 0xFE65F008 (INTERFACE) (18 of 18):
  893. Del assoc: Parent of 0xFF932288 (Task: Initialize Interface)
  894. Add assoc: Parent of 0xFF8B9EA8 (LocalIp)
  895. Add assoc: IP IF Open
  896. Add assoc: Parent of 0xFF8B99C8 (LocalIp)
  897. Add assoc: Parent of 0xFF8F18C8 (LocalIp)
  898. Add assoc: Parent of 0xFE667CE8 (Destination)
  899. Add assoc: Parent of 0xFE663268 (RemoteIp)
  900. Add assoc: Parent of 0xFF92A848 (Destination)
  901. Add assoc: Parent of 0xFF8EE868 (RemoteIp)
  902. Add assoc: Parent of 0xFF92A648 (Destination)
  903. Add assoc: Parent of 0xFE6686C8 (RemoteIp)
  904. Add assoc: Parent of 0xFE691568 (Destination)
  905. Add assoc: Parent of 0xFF8D7288 (RemoteIp)
  906. Add assoc: Owns group 0xFE65F154 (Destination group)
  907. Add assoc: Owns group 0xFE65F110 (RemoteIp group)
  908. Add assoc: Owns group 0xFE65F0CC (LocalIp group)
  909. Add assoc: Parent of 0xFF932288 (Task: Initialize Interface)
  910. Add assoc: Child of 0xFE7009A8 (Adapter)
  911. kd> !rm grp 0xFE65F154
  912. Group 0xFE65F154 (Destination group) of object 0xFE65F008 (INTERFACE)
  913. Num:0x00000004 State:ENABLED pSInfo:0xfd8c1380
  914. pULTsk:0x00000000
  915. Members:
  916. 0xFE667CE8 0xFE691568 0xFF92A648 0xFF92A848
  917. kd>
  918. ARP -A output from josephj1E...
  919. E:\> arp -a
  920. Interface: 172.31.241.214 on Interface 0x2
  921. Internet Address Physical Address Type
  922. 172.31.240.1 00-10-11-60-d1-40 dynamic
  923. Interface: 192.168.75.1 on Interface 0x3
  924. Internet Address Physical Address Type
  925. 10.0.0.11 01-00-00-00-00-00-00 static
  926. 10.0.0.12 02-00-00-00-00-00-00 static
  927. 10.0.0.13 03-00-00-00-00-00-00 static
  928. 10.0.0.14 04-00-00-00-00-00-00 static
  929. E:\>net stop atmarpc
  930. The ATM ARP Client Protocol service was stopped successfully.
  931. E:\>net start atmarpc
  932. The ATM ARP Client Protocol service was started successfully.
  933. 03/10/1999 JosephJ Encapsulation buffer management design
  934. Apis:
  935. NDIS_STATUS
  936. arpInitializeEncapsulationHeaderPool(
  937. IN UINT Size,
  938. IN const *pvMem,
  939. IN UINT cbMem,
  940. IN PRM_OBJECT_HEADER *pOwningObject,
  941. OUT ARP_ENCAPSULATION_HEADER_POOL **ppPool,
  942. IN PRM_STACK_RECORD pSR
  943. );
  944. VOID
  945. arpDeinitializeEncapsulationHeaderPool(
  946. IN ARP_ENCAPSULATION_HEADER_POOL **ppPool,
  947. IN PRM_STACK_RECORD pSR
  948. );
  949. PNDIS_BUFFER
  950. arpAllocateEncapsulationHeader(
  951. ARP_ENCAPSULATION_HEADER_POOL *pPool
  952. );
  953. VOID
  954. arpDeallocateEncapsulationHeader(
  955. ARP_ENCAPSULATION_HEADER_POOL *pPool
  956. PNDIS_BUFFER pBuffer
  957. );
  958. 03/11/1999 RM api enhancements -- more on root objects
  959. (see 03/07/1999 entry "Registering root objects with RM")
  960. RootObjects should be an extended hdr structure, with the following info
  961. -- list of tasks (for debugging only)
  962. -- "name space GUID", used by kd to load custom information about all the objects
  963. under the GUID.
  964. -- Global log (one per root object).
  965. typedef struct {
  966. RM_OBJECT_HEADER Hdr;
  967. LIST_ENTRY listTasks;
  968. LIST_ENTRY listLog;
  969. ...
  970. } RM_ROOT_OBJECT_HEADER;
  971. 03/11/1999 RM api enhancements -- special "unload object" tasks.
  972. -- Given the similarity of the way shutdown tasks are handled, especially
  973. the way they deal with existing shutdown tasks, we should consider
  974. shutdown tasks to be a special kind of tasks with an extended task header
  975. (below). Also, have a field in all objects to hold THE
  976. shutdown task. The RmApis can implement the logic of waiting on THE
  977. shutdown task, etc. MOREOVER, it can then support the concept of
  978. PARALLEL unload, because it can use the extra fields in the extended
  979. shutdown task header to store stuff (LONG to be interlocked-
  980. decremented and if zero a task to be un-pended).
  981. typedef struct
  982. {
  983. RM_TASK_HEADER TskHdr;
  984. LONG TasksLeft; << interlock-decrement this and if 0 ...
  985. PRM_TASK pCoordinatingTask; << ... unpend this task.
  986. } RM_SHUTDOWN_TASK;
  987. The object's unload task handler will be only called once, regardless of
  988. howmany times someone requests to unload the object -- this is supported
  989. by a new Rm API, something like:
  990. RmUnloadObject(pObj, OPTIONAL pTask,...) -- if pTask NULL, will block.
  991. (also the existing RmUnloadAllObjectsInGroup)
  992. Since the handler function will only be called once, it can be simplified --
  993. the code to deal with existing handler-functions can be taken out.
  994. 03/11/1999 RM api enhancements -- stastics gathering(if RM_EXTENDED_CHECKING enabled)
  995. For the following
  996. - per root object (global stats)
  997. - per object
  998. Stats (current, tot, max)
  999. - tasks allocated
  1000. - object age (how long it's been around)
  1001. - number of children allocated
  1002. For Groups (current, tot, max)
  1003. -we already maintain some group stats -- rough number of accesses and
  1004. number links travesed (since it's munged (scaled down), this is not
  1005. really a true number).
  1006. - Number of adds/deletes/lookups
  1007. - Number of members
  1008. - Links traversed
  1009. - Some idea of how long objects live in the group
  1010. (age can be determined at the time the object is deallocated)
  1011. - best would be a histogram, say of multiples of 16 ms (8 DWORDS)
  1012. <=1ms, <=16ms, <=256ms, <=4s, <=65s(~1m), <=1Ks(16m), <=16Ks(4h), >..
  1013. - quick to compute histogram index: 16-char array L2 of log_2(nibble):
  1014. PUCHAR *puc = (PUCHAR) &val;
  1015. UINT Index =
  1016. (L2[puc[0]]+(L2[puc[1]]<<4)+(L2[puc[2]]<<8)+(L2[puc[3]]<<12))>>2;
  1017. 03/11/1999 JosephJ Implemented and tested (in user mode) const buffer APIs
  1018. See 03/10/1999 entry "Encapsulation buffer management design"
  1019. The APIs have been renamed as follows
  1020. arpInitializeConstBufferPool
  1021. arpDeinitializeConstBufferPool
  1022. arpAllocateConstBuffer
  1023. arpDeallocateConstBuffer
  1024. .\tests\tarp.c (function test_ArpConstBufferPool) tests the above functions
  1025. in usermode.
  1026. 03/11/1999 JosephJ Win98 -- BACK_FILL is disabled in atmarpc.sys
  1027. So we have to keep the #if BACK_FILL code.
  1028. 03/11/1999 JosephJ Ideas on logging enhancements
  1029. - Integrate debug logging with object logging -- single logging model
  1030. that optionally goes to object log and/or debug log.
  1031. (So for example a lot of stuff can get logged to the object logs, without
  1032. choking up the debugger).
  1033. - Verbosity controlled on multiple basis:
  1034. - per-object
  1035. - per stack_record
  1036. - per module
  1037. - Add a SINGLE_LIST_ENTRY to the log entry for stack_record logging -- to be able
  1038. to dump all log entries made when a particular stack record is in scope.
  1039. - rather than trying to properly deal with stack_records and/or objects going
  1040. out of scope, we simply add the log entry to the HEAD of the stack-record
  1041. list. This way we don't have to worry if log entries already in the
  1042. stack-record log are still alive (note we would need to know that if we
  1043. were using the doubly-linked SLIST_ENTRY).
  1044. - The kd extension would have to deal with the fact that some of the entries
  1045. may be deallocatd.
  1046. 03/12/1999 JosephJ RouteCacheEntry information:
  1047. From: Joseph Joy Friday, March 12, 1999 7:43 AM
  1048. Subject: questions on arp RouteCacheEntry semantics
  1049. NK,
  1050. Are the semantics of RouteCacheEntry passed in to the arp module's lip_transmit
  1051. routine documented anywhere?
  1052. [Nk Srinivas] Document ???? ;-)
  1053. If not, can you answer the following questions? (I need this for my ip/1394 arp
  1054. implementation).
  1055. 1. From the 1st time we see a particular RCE (with arp context portion all
  1056. zeros) until the point the arp modules lip_invalidate handler is called,
  1057. can we assume that the rce will always refer to the same destination IP
  1058. address?
  1059. [Nk Srinivas] Yes.
  1060. 2. Is it possible for the lip_transmit routine to be re-entered for a send with
  1061. the same RCE -- i.e., two or more concurrent calls made to lip_transmit
  1062. specifying the same RCE?
  1063. [Nk Srinivas] yes.
  1064. 3. Is #2 is true, can we assume that the FIRST time a particular RCE is
  1065. specified in lip_transmit, lip_transmit will NOT be reentered with the same
  1066. RCE until the former call to lip_transmit returns? (I hope so).
  1067. [Nk Srinivas] No. same rce will be passed in every call.
  1068. 4. In practice, under moderate to heavy loads, can I assume that the vast
  1069. majority (>99%) of lip_transmit calls are made with a non-NULL RCE?
  1070. [Nk Srinivas] [...] *All* tcp/udp/raw traffic uses RCE. Only icmp/igmp
  1071. do not use rce.
  1072. 03/12/1999 JosephJ RouteCacheEntry use; fast send path design VERSION ONE
  1073. ArpIpTransmit(...)
  1074. {
  1075. if (pRCE->context != NULL)
  1076. {
  1077. lock IF send lock
  1078. get pIpEntry from pRCE
  1079. if (can send immediately) // this includes the fact that there are
  1080. // no pkts queued waiting for buffers!
  1081. {
  1082. fRet = fast_send(&Status, pPkt, pVc); // send-lock released
  1083. if (fRet) return Status; // EARLY_RETURN
  1084. // else were out of resources, we probably need to queue pkt
  1085. }
  1086. unlock IF send lock
  1087. }
  1088. arpSlowIpTransmit(......)
  1089. }
  1090. arpSlowIpTransmit(...)
  1091. {
  1092. if (pRCE->context == NULL) // again
  1093. {
  1094. lookup/create RemoteIp entry
  1095. ASSERT_NOLOCKS()
  1096. get IF send lock
  1097. if (pRCE->context == NULL) // is it still null?
  1098. {
  1099. setup pRCE->context;
  1100. }
  1101. else
  1102. {
  1103. // no-longer null -- this means that someone else has already
  1104. // initialized it.
  1105. pTmpRemoteIp = pRemoteIp;
  1106. pRemoteIp = pRCE->context;
  1107. tmpref(pRemoteIp);
  1108. tmpderref(pOldRemoteIp);
  1109. }
  1110. release IF send lock;
  1111. }
  1112. ASSERT_NOLOCKS
  1113. if (pRemoteIP == NULL)
  1114. {
  1115. fail pkt.
  1116. }
  1117. else
  1118. {
  1119. // we've got a pRemoteIp, with a ref to it, and no locks.
  1120. get IF set lock
  1121. if (can send immediately)
  1122. {
  1123. fret = fast_send(....);
  1124. if (!fRet)
  1125. {
  1126. // we're out of resources, queue pkt on IF's pkts-waiting-for-bkts
  1127. // queue.
  1128. }
  1129. }
  1130. else
  1131. {
  1132. queue pkt on RemoteIp's send pkt queue.
  1133. }
  1134. }
  1135. }
  1136. 03/12/1999 JosephJ RouteCacheEntry use; fast send path design VERSION TWO
  1137. In this one, we first prepare the packet, including chaining a header buffer
  1138. up front, if required if we can't fast-send, we un-do the work.
  1139. // Following sits in the miniport-reserved portion of send-pkts, before they
  1140. // are sent out.
  1141. struct
  1142. {
  1143. LIST_ENTRY linkQueue;
  1144. union
  1145. {
  1146. struct
  1147. {
  1148. IP_ADDRESS IpAddress;
  1149. ULONG Flags;
  1150. #define ARPSPI_BACKFILLED 0x1
  1151. #define ARPSPI_HEADBUF 0x2
  1152. #define ARPSPI_FIFOPKT 0x4
  1153. #define ARPSPI_CHANNELPKT 0x8
  1154. } IpXmit;
  1155. };
  1156. } ARP_SEND_PKT_MPR_INFO;
  1157. ArpIpTransmit(...)
  1158. {
  1159. do
  1160. {
  1161. if (pRCE->context != NULL) break; // slow path
  1162. if (fifo_header)
  1163. {
  1164. fRet = prepare_fifo_header(pIF, pPkt);
  1165. }
  1166. else
  1167. {
  1168. fRet = prepare_channel_header(pIF, pPkt);
  1169. }
  1170. if (!fRet) break; // slow path
  1171. lock IF send lock
  1172. get pIpEntry from pRCE
  1173. if (can send immediately) // this includes the fact that there are
  1174. // no pkts queued waiting for buffers!
  1175. {
  1176. pVc->fast_send(&Status, pPkt, pVc); // send-lock released
  1177. return Status; // EARLY_RETURN
  1178. }
  1179. unlock IF send lock
  1180. }
  1181. arpSlowIpTransmit(......)
  1182. }
  1183. arpSlowIpTransmit(pPkt, pLocalIp, ...)
  1184. {
  1185. }
  1186. 03/13/1999 JosephJ New RM APIs RmResumeTaskAsync and RmResumeTaskDelayed
  1187. Added the above two APIs which seem to provide a "big bang for the buck."
  1188. Description:
  1189. RmResumeTaskAsync -- resumes task in the context of a work item
  1190. RmResumeTaskDelayed -- resumes task in the context of a timer handler.
  1191. Potential uses of RmResumeTaskAsync:
  1192. 1. There is a potential problem with the way that task completion is handled,
  1193. that could lead to excessive use of the stack.
  1194. The specific case where this would happen is if
  1195. there are a large number of objects in a group, and
  1196. their shutdown tasks all call SuspendTask and ResumeTask on themselves.
  1197. What will happen is that when RmUnloadAllObjectsInGroup is called for
  1198. this group, you will have the shutdown handlers for EACH object in the
  1199. group on the stack (in facta couple of times each).
  1200. To avoid this pathalogical situation (which except for its use of the
  1201. stack is otherwise perfectly correct), RmUnloadAllObjectsInGroup can
  1202. unload each object as a separate work item.
  1203. 2. If a task wants to do something at passive level and it can be sure
  1204. that it is currently at passive level.
  1205. Potential uses of RmResumeTaskDelayed:
  1206. 1. For debugging, to delay completion of some operation makes it extremely
  1207. easy to do it).
  1208. 2. If a task needs to do something after a fixed period of time -- say to
  1209. send a retry after 3 seconds.
  1210. 03/13/1999 JosephJ Ageing of objects
  1211. The use of ageing timers can be completely hidden from the user if objects
  1212. have ages and they WILL be unloaded (it's shutdown task will be started) if
  1213. the age expires. The rm API RmResetAgeingTimer is used to extend the object's
  1214. life.
  1215. Support for ageing of objects, plus the RmResumeTaskDelayed api described
  1216. above, should pretty-much obviate the user's need for explicit timers.
  1217. 03/14/1999 JosephJ Finished implementing RmResumeTaskAsync and RmResumeTaskDelayed
  1218. Finished implementing and testing (in user mode) the above two functions
  1219. (see 03/13/1999 entry "New RM APIs RmResumeTaskAsync and RmResumeTaskDelayed").
  1220. To test in user mode, I wrote user-mode versions of the following Ndis APIs:
  1221. NdisInitializeWorkItem
  1222. NdisScheduleWorkItem
  1223. NdisInitializeTimer
  1224. NdisSetTimer
  1225. 03/16/1999 JosephJ Implemented RmLinkToExternal* and RmUnlinkFromExternal*
  1226. The following are used for references to external objects, such as RCEs and
  1227. packets:
  1228. RmLinkToExternalFast Addrefs object
  1229. RmLinkToExternalEx Debug versions of the above, adds an association
  1230. RmUnlinkFromExternalFast Delrefs object
  1231. RmUnlinkFromExternalEx Debug version of the above, dels an association
  1232. TODO: need to make the fast versions inline, and also currently
  1233. RmUnlinkFromExternalEx declares a stack-record -- it should do this only
  1234. if the object needs to actually be deallocated (i.e call another function
  1235. which declares a stack log)
  1236. 03/19/1999 JosephJ Thoughts on cleaning up the task handlers
  1237. - Separate PendCompletion-, End- and Abort-handlers.
  1238. - No "UserParam", even on starting -- instead, just NDIS_STATUS.
  1239. - User is expected to setup the task with any required initialization parameters
  1240. *before* calling RmStartTask.
  1241. - "START" is a special pend code value of (ULONG)-1, sent to the task's
  1242. PendCompletion handler.
  1243. - RmStartTask has return type VOID.
  1244. - PendCompletion and Abort handlers have return type VOID.
  1245. - Only the End handler returns NDIS_STATUS (anything besides PENDING).
  1246. (This return status is passed on any tasks that may be pending on it).
  1247. The PendCompletion handler prototype becomes...
  1248. typedef
  1249. VOID
  1250. (*PFN_RM_TASK_PENDCOMPLETE_HANDLER)(
  1251. IN struct _RM_TASK * pTask,
  1252. IN OS_STATUS Status,
  1253. IN PRM_STACK_RECORD pSR
  1254. );
  1255. RmStartTask's prototype becomes...
  1256. VOID
  1257. RmStartTask(
  1258. IN PRM_TASK pTask,
  1259. IN PRM_STACK_RECORD pSR
  1260. );
  1261. 03/22/1999 JosephJ Support for retail debugging or RM objects
  1262. - May want to consider adding links to children and peers (4 ptrs overhead!)
  1263. purely for debugging purposes. At least make it a compile option independent
  1264. of DBG
  1265. - Support the following RM dbgextension:
  1266. !rm scantree <obj addr> <pattern>
  1267. -- scans the obj at addr <obj addr> and all its children for
  1268. pattern <pattern>
  1269. !rm tree <obj addr>
  1270. -- lists the entire tree of objects, starting at oject <obj addr>
  1271. bp atmarpc!DbgMark "dd (esp+4) l1; g poi(esp)"
  1272. 03/23/1999 JosephJ Media-specific parameters is 5 DWORDs from base ....
  1273. but NIC1394_MEDIA_PARAMETERS, whose 1st field is a union
  1274. which includes a UINT64, needs to be 8-byte aligned!
  1275. Fix? Probably redefine the UniqueID to be UniqueIDHi and UniqueIDLo
  1276. 03/24/1999 JosephJ Wierdness involving MIB processing in ip.c
  1277. Previously, the arp module could be net-stopped and started, but then
  1278. arp, ipconfig, etc wouldn't work, and what was happening is the the reloaded
  1279. arp module was being given the OLD entity instance values (from its previous
  1280. life). I found that sometime after we initiate unload by calling IP's
  1281. pDelInterfaceRtn, Ip calls ArpIpGetEList. At this stage (i.e. we are closing),
  1282. we need to set the pAT/IFEntity->tei_instance to INVALID_ENTITY_INSTANCE to
  1283. fix this problem.
  1284. 03/24/1999 JosephJ Adding to fake Ndis calls:
  1285. Adding more variations to the fake versions of the following Ndis calls:
  1286. NdisClMakeCall
  1287. NdisClCloseCall
  1288. NdisCoSendPackets
  1289. We need to randomly chose among the following variations:
  1290. - failure OR success
  1291. - async OR sync completion for make/close call
  1292. - async OR sync (i.e. while NdisCoSendPackets still on stack) completion for
  1293. SendPkts.
  1294. - For async completion of make/close call and async completion of sendpkts,
  1295. to call the completion call back in dpc OR passive level.
  1296. - For async calls, delay for some random amount of time.
  1297. 03/25/1999 JosephJ Implemented all of the above fake ndis call variations!
  1298. Check out fake.c -- it now has a pretty elaborate mechanism for controlling
  1299. the probabilities of the variations of behaviour of the fake versions of
  1300. NdisClMakeCall, NdisClCloseCall and NdisCoSendPackets -- basically it allows
  1301. you to specify weights of the above variations (failure/success, async/sync
  1302. etc) and then generates samples based on those weights. Here's an example
  1303. of how the delay amount is specified:
  1304. static
  1305. OUTCOME_PROBABILITY
  1306. DelayMsOutcomes[] =
  1307. {
  1308. {0, 5}, // Delay 0ms, etc...
  1309. {10, 5},
  1310. {100, 5},
  1311. {1000, 1},
  1312. {10000, 1}
  1313. };
  1314. The above means that 0,10, and 100ms delays each have a weight of 5 and
  1315. 1000ms and 10000ms each have a weight of 1.
  1316. TODO: May want to add jitter to the outcome values, where they make sense.
  1317. It's easy to do that -- for example Val += (R*Val/32), where R is a random
  1318. signed integer in the range of -8 to 8 (need to watch for overflow and
  1319. boundary conditions). Anyway, I don't think this will add anything tangible
  1320. (i.e. find bugs that would not have otherwise been found).
  1321. The code to generate samples based on weights, and the fake versions of the
  1322. calls themselves, were first tested in user mode via the tests in
  1323. tests\tarp.c (test functions test_ArpGenRandomInt() and test_arpDbgFakeCalls().)
  1324. test_ArpGenRandomInt actually prints out results to show that the actual
  1325. percentages match the specified weights. Here is some sample
  1326. output(pretty good results!):
  1327. NUM_TRIALS = 100....
  1328. Outcome=0x0; True%=0.032258; Computed%=0.020000
  1329. Outcome=0x1; True%=0.064516; Computed%=0.050000
  1330. Outcome=0x2; True%=0.129032; Computed%=0.170000
  1331. Outcome=0x3; True%=0.258065; Computed%=0.240000
  1332. Outcome=0x4; True%=0.516129; Computed%=0.520000
  1333. ...
  1334. NUM_TRIALS = 10000....
  1335. Outcome=0x0; True%=0.032258; Computed%=0.034800
  1336. Outcome=0x1; True%=0.064516; Computed%=0.063300
  1337. Outcome=0x2; True%=0.129032; Computed%=0.126400
  1338. Outcome=0x3; True%=0.258065; Computed%=0.256800
  1339. Outcome=0x4; True%=0.516129; Computed%=0.518700
  1340. The core random number generator is based on Numerical Recipes ran1() --
  1341. see fake.c for details.
  1342. Today I used the above fake version of the APIs to test arp1394 -- it worked
  1343. fine for basic pings, but arp1394 has just hit an assert when I tried
  1344. "net start atmarpc" while pings were ongoing. So the test infrastructure is
  1345. bearing fruit!
  1346. The great thing about these fake versions is that I can continue to use them
  1347. in the future for regression testing of arp1394.
  1348. 03/25/1999 JosephJ Ahem...above-mentioned assert is due to be a bug in fake.c
  1349. 03/25/1999 JosephJ IPDelInterface should be called at PASSIVE!
  1350. Check out the following stack trace. The bugcheck happened because
  1351. IPDelInterface was called at DPR level (our good-old fake close-call completion
  1352. callback did this, by design). So obviously we must switch to passive before
  1353. calling IPDelInterface. But this stack is an example of the potential
  1354. problem I mentioned in the 03/13/1999 note
  1355. "New RM APIs RmResumeTaskAsync and RmResumeTaskDelayed":
  1356. 1. There is a potential problem with the way that task completion
  1357. is handled, that could lead to excessive use of the stack.
  1358. So basically we need to figure out key points to do a "resume task asynch."
  1359. I could make "RmCancelPendOnOtherTask" do a RmResumeTaskAsync instead
  1360. of RmResumeTask EXCEPT that we need a work item to do this.
  1361. ntkrnlmp!KeBugCheckEx+0x12d
  1362. ntkrnlmp!ExAllocatePoolWithTag+0x3f
  1363. ntkrnlmp!ExpAllocateStringRoutine+0x10
  1364. ntkrnlmp!RtlAnsiStringToUnicodeString+0x48
  1365. netbt!LmOpenFile+0x3c
  1366. netbt!PrimeCache+0x3d
  1367. netbt!NbtResyncRemoteCache+0x8a
  1368. netbt!NbtNewDhcpAddress+0xaf
  1369. netbt!TdiAddressDeletion+0x70
  1370. TDI!TdiNotifyPnpClientList+0xcb
  1371. TDI!TdiExecuteRequest+0x173
  1372. TDI!TdiDeregisterNetAddress+0xb
  1373. tcpip!NotifyAddrChange+0xf9
  1374. tcpip!IPDelNTE
  1375. tcpip!IPDelInterface
  1376. atmarpc!RmResumeTask+0x129
  1377. atmarpc!RmCancelPendOnOtherTask+0x221
  1378. atmarpc!rmEndTask+0x13c
  1379. atmarpc!RmResumeTask+0x1fb
  1380. atmarpc!RmCancelPendOnOtherTask+0x221
  1381. atmarpc!rmEndTask+0x13c
  1382. atmarpc!RmStartTask+0x201
  1383. atmarpc!rmTaskUnloadGroup+0x452
  1384. atmarpc!RmResumeTask+0x129
  1385. atmarpc!RmCancelPendOnOtherTask+0x221
  1386. atmarpc!rmEndTask+0x13c
  1387. atmarpc!RmStartTask+0x201
  1388. atmarpc!rmTaskUnloadGroup+0x452
  1389. atmarpc!RmResumeTask+0x129
  1390. atmarpc!RmCancelPendOnOtherTask+0x221
  1391. atmarpc!rmEndTask+0x13c
  1392. atmarpc!RmStartTask+0x201
  1393. atmarpc!rmTaskUnloadGroup+0x452
  1394. atmarpc!RmResumeTask+0x129
  1395. atmarpc!RmCancelPendOnOtherTask+0x221
  1396. atmarpc!rmEndTask+0x13c
  1397. atmarpc!RmResumeTask+0x1fb
  1398. atmarpc!RmCancelPendOnOtherTask+0x221
  1399. atmarpc!rmEndTask+0x13c
  1400. atmarpc!RmResumeTask+0x1fb
  1401. atmarpc!ArpCoCloseCallComplete+0xf8
  1402. atmarpc!arpFakeCloseCallCompletionCallback+
  1403. atmarpc!arpDbgFakeCompletionTask+0x1b1
  1404. atmarpc!RmResumeTask+0x129
  1405. atmarpc!rmWorkItemHandler_ResumeTaskAsync+0
  1406. NDIS!ndisWorkItemHandler+0xa
  1407. ntkrnlmp!ExpWorkerThread+0xcb
  1408. ntkrnlmp!PspSystemThreadStartup+0x54
  1409. ntkrnlmp!KiThreadStartup+0x16
  1410. 03/26/1999 JosephJ Some proposed modifications to RM task handling ...
  1411. - RmUnloadAllObjectsInGroup causes the cascaded chain of start tasks above
  1412. if the unload task of each object returns synchronously or asynchronously
  1413. but with the original start task still on the stack. This has to change.
  1414. A One fix is for RmUnloadAllObjectsInGroup to call an unload *function*
  1415. (instead of starting a task) for each object. This unload function would
  1416. take the unload-all-objects task as an argument and if
  1417. necessary start a task and make the coordinating task pend on it. If this
  1418. function returns synchronously, however, then the unload-all-objects task
  1419. can go on to the next task.
  1420. B Another fix is to make RmPendTaskOnOtherTask return PENDING if the
  1421. task has been pended or SUCCESS if OtherTask has already completed.
  1422. Currently, typical sequence of starting and pending on another task is:
  1423. pOtherTask = AllocTask(...);
  1424. RmPendOnOtherTask(pTask, pOtherTask,...);
  1425. RmStartTask(pOtherTask,...);
  1426. With the proposed change, the sequence becomes...
  1427. pOtherTask = AllocTask(...);
  1428. RmTmpReferenceObject(&pOtherTask.Hdr,...);
  1429. RmStartTask(pOtherTask,...);
  1430. Status = RmPendTaskOnOtherTask(pTask, pOtherTask, ...);
  1431. RmTmpDereferenceObject(&pOtherTask.Hdr,...);
  1432. if (PEND(Status))
  1433. {
  1434. // we're pending on the other task.
  1435. ...
  1436. }
  1437. else
  1438. {
  1439. // Other task is complete. Go on to the next step.
  1440. //
  1441. }
  1442. For now, we can use an StartAndTryPend internal api used only
  1443. by the unload-all-objects task so we don't have to go and change things
  1444. everywhere.
  1445. Implemented option 'B', but specifically for use by rmTaskUnloadGroup.
  1446. The new version of the pend function is called RmPendTaskOnOtherTaskV2
  1447. (called only by rmTaskUnloadGroup).
  1448. 03/26/1999 JosephJ Was a bug in my code to switch to async before calling DelIF...
  1449. Following is an example of using dumps of object associations and logs to
  1450. quickly find out what's going on and where the problem is....
  1451. The net stop was hanging, but the system was otherwise available. So I broke
  1452. in and this is what I found...
  1453. kd> !rm asc 0xFE666168
  1454. Associations (50 max) for 0xFE666168 (INTERFACE):
  1455. IP IF Open
  1456. Child of 0xFF8F2A68 (Adapter)
  1457. Owns group 0xFE666234 (LocalIp group)
  1458. Owns group 0xFE666278 (RemoteIp group)
  1459. Owns group 0xFE6662BC (Destination group)
  1460. Buffer pool 0xFE666330
  1461. Parent of 0xFF8D8708 (Task: Shutdown Interface)
  1462. kd> !rm asc 0xFF8D8708
  1463. Associations (50 max) for 0xFF8D8708 (Task: Shutdown Interface):
  1464. Blocks 0xFF8F0848 (Task:Unload Object)
  1465. Child of 0xFE666168 (INTERFACE)
  1466. Resume async (param=0x00000000)
  1467. kd> !rm log 0xFE666168
  1468. Log entries for 0xFE666168 (INTERFACE) (41 of 41):
  1469. Del assoc: Parent of 0xFE6782E8 (Destination)
  1470. Del assoc: Parent of 0xFF90FBA8 (Task:UnloadAllObjectsInGroup)
  1471. Del assoc: Parent of 0xFF8EDD08 (Destination)
  1472. Del assoc: Parent of 0xFF91A4C8 (Destination)
  1473. Del assoc: Parent of 0xFF8EE6E8 (Destination)
  1474. Del assoc: Parent of 0xFF8D4268 (Task:UnloadAllObjectsInGroup)
  1475. Del assoc: Parent of 0xFF90F428 (Task:UnloadAllObjectsInGroup)
  1476. Add assoc: Parent of 0xFF90FBA8 (Task:UnloadAllObjectsInGroup)
  1477. Del assoc: Parent of 0xFF907448 (RemoteIp)
  1478. ....
  1479. Add assoc: Parent of 0xFF8F0848 (Task: Initialize Interface)
  1480. Add assoc: Child of 0xFF8F2A68 (Adapter)
  1481. kd> !rm log 0xFF8D8708
  1482. Log entries for 0xFF8D8708 (Task: Shutdown Interface) (50 of 2486):
  1483. Del assoc: Resume async (param=0x00000000)
  1484. Add assoc: Resume async (param=0x00000000)
  1485. Del assoc: Resume async (param=0x00000000)
  1486. Add assoc: Resume async (param=0x00000000)
  1487. Del assoc: Resume async (param=0x00000000)
  1488. Add assoc: Resume async (param=0x00000000)
  1489. Del assoc: Resume async (param=0x00000000)
  1490. ...
  1491. Note the 2486 log entries above!
  1492. So basically what's happening is that the IF shutdown task was in an
  1493. endless loop of switching to async -- this was because it was
  1494. checking whether it was at PASSIVE wit the IF lock held!
  1495. 03/27/1999 JosephJ ARP Packet handling
  1496. // Parsed version of the ARP request/response pkt
  1497. //
  1498. typedef struct
  1499. {
  1500. enum
  1501. {
  1502. ArpRequest = 1,
  1503. ArpResponse = 2
  1504. } OpCode;
  1505. USHORT SenderMaxRec;
  1506. USHORT SenderSspd;
  1507. NIC1394_FIFO_ADDRESS SenderHwAddr;
  1508. IP_ADDRESS SenderIpAddress;
  1509. IP_ADDRESS TargetIpAddress;
  1510. } IPV4_1394_ARP_PKT_INFO;
  1511. NDIS_STATUS
  1512. arpParseArpPkt(
  1513. IN PVOID pvPktData,
  1514. IN UINT cbPktData,
  1515. IN OUT IPV4_1394_ARP_PKT_INFO *pArpPktInfo
  1516. );
  1517. NDIS_STATUS
  1518. arpPrepareArpPkt(
  1519. IN IPV4_1394_ARP_PKT_INFO *pArpPktInfo
  1520. IN PVOID pvPktData,
  1521. IN UINT cbMaxPktData,
  1522. out PUINT pcbMaxPktData
  1523. );
  1524. 03/27/1999 JosephJ ARP Packet handling (contd..)
  1525. Defined the following over-the wire packet formats:
  1526. NIC1394_GASP_HEADER (nic1394.h)
  1527. NIC1394_FIRST_FRAGMENT_HEADER (nic1394.h)
  1528. NIC1394_FRAGMENT_HEADER (nic1394.h)
  1529. IP1394_ARP_PKT (rfc.h)
  1530. 03/28/1999 JosephJ Created subdirs w2k and win98 to build for w2k and win98.
  1531. Moved & modified makefile and sources down to w2k and also win98.
  1532. 03/28/1999 JosephJ ARP packet handling (contd...)
  1533. Implemented arpParseArpPkt and arpPrepareArpPkt (in arp.c)
  1534. 03/28/1999 JosephJ Thoughts on cleaning up RmLookupObjectInGroup
  1535. RmLookupObjectInGroup is too overloaded -- split it up into a LookupOrCreate
  1536. function and a pure Lookup function. Or maybe use macros...
  1537. 03/29/1999 JosephJ max_rec and sspd info in ARP pkts...
  1538. We should request that sspd info be removed from the ARP pkt.
  1539. Anyway, I've sent mail to georgioc asking how to get this information for the
  1540. local host.
  1541. 03/30/1999 JosephJ Yet another way to handle failures in the task handler....
  1542. From arpTaskInitializeInterface(...):
  1543. // Couldn't allocate task. Let's do a fake completion of
  1544. // this stage...
  1545. //
  1546. UNLOCKOBJ(pIF, pSR);
  1547. RmSuspendTask(pTask, PEND_SetupReceiveVc, pSR);
  1548. RmResumeTask(pTask, (UINT_PTR) Status, pSR);
  1549. 03/30/1999 JosephJ Thougts on using tasks to help write pageable code
  1550. Support for "pageable" tasks -- the rm api's can make
  1551. sure that the context is passive (switching to passive if
  1552. required) whenever the handler is called.
  1553. We can require only the START and (optional) complete handlers
  1554. to be nonpaged. Even the START handler doesn't need to be
  1555. pageable -- if we require that RmStartTask be called at
  1556. PASSIVE.
  1557. I think this is a pretty cool concept and should be explored further.
  1558. 03/30/1999 JosephJ Interesting stack traces for load/unload of atmarpc...
  1559. ntkrnlmp!IofCallDriver
  1560. nic1394!nicSubmitIrp+0x197
  1561. nic1394!nicSubmitIrp_Synch+0x173
  1562. nic1394!nicAllocateAddressRange+0x446
  1563. nic1394!nicCmMakeCallInitVc+0x6b7
  1564. nic1394!NicCmMakeCall+0x29b
  1565. NDIS!NdisClMakeCall+0x86
  1566. atmarpc!arpTaskMakeRecvFifoCall+0x3ae
  1567. atmarpc!RmStartTask+0x12f
  1568. atmarpc!arpTaskInitializeInterface+0x318
  1569. atmarpc!RmResumeTask+0x129
  1570. atmarpc!ArpCoOpenAfComplete+0x104
  1571. NDIS!NdisCmOpenAddressFamilyComplete+0xce
  1572. NDIS!NdisClOpenAddressFamily+0x1e4
  1573. atmarpc!arpTaskInitializeInterface+0x17a
  1574. atmarpc!RmStartTask+0x12f
  1575. atmarpc!ArpCoAfRegisterNotify+0x246
  1576. NDIS!ndisNotifyAfRegistration+0x62
  1577. NDIS!ndisMFinishQueuedPendingOpen+0xfd
  1578. NDIS!ndisWorkerThread+0x5c
  1579. nic1394!nicFreeAddressRange
  1580. nic1394!NicCmCloseCall+0xf0
  1581. NDIS!NdisClCloseCall+0x64
  1582. atmarpc!arpTaskCleanupRecvFifoCall+0x36a
  1583. atmarpc!RmStartTask+0x12f
  1584. atmarpc!arpTaskShutdownInterface+0x245
  1585. atmarpc!RmStartTask+0x12f
  1586. atmarpc!arpTaskShutdownAdapter+0x35c
  1587. atmarpc!RmStartTask+0x12f
  1588. atmarpc!rmTaskUnloadGroup+0x44c
  1589. atmarpc!RmStartTask+0x12f
  1590. atmarpc!RmUnloadAllObjectsInGroup+0x10e
  1591. atmarpc!arpResHandleGlobalIpBinding+0x1e0
  1592. atmarpc!RmUnloadAllGenericResources+0x101
  1593. atmarpc!ArpUnload+0x5d
  1594. ntkrnlmp!IopLoadUnloadDriver+0x14
  1595. ntkrnlmp!ExpWorkerThread+0xcb
  1596. ntkrnlmp!ObpCreateHandle+0x165
  1597. 03/31/1999 JosephJ Static ping works!
  1598. Today, we got ping and ttcp to work across two machines, over ip/1394!
  1599. Throughput was dismal -- ~ 250K bytes/sec (2M bits/sec), but otherwise
  1600. it's stable (pinged all night, continues to ping...), provided you don't
  1601. try to yank the cable etc in the middle. ADube is working on nic1394 to fix
  1602. the latter problems.
  1603. Great thing is that ABSOLUTELY NO FIXES were required in atmarpc.sys to get
  1604. this to work (I just compiled atmarpc.sys with the option to use the real
  1605. make/close call and send pkt apis.).
  1606. 04/02/1999 JosephJ RM logging contd...
  1607. Add another SLIST_ENTRY for threading together all log entries generated during
  1608. a particular stack trace. The stack record would contain the list head.
  1609. Consider putting refcounts on each log entry.
  1610. 04/07/1999 JosephJ fake api's caught case where we could be calling add if at DPC
  1611. The fake recv makecall completed at DPC level,and this caused a bugcheck when
  1612. we called IP's add IF routine. Fixed this by switching to passive if required,
  1613. before calling IP's add IF routine.
  1614. 04/07/1999 JosephJ verified that this is 64-bit clean (checked and fre)
  1615. 04/07/1999 JosephJ Added arp1394 and arp13kd sources to the tcpipmerge project.
  1616. Did this today.
  1617. 04/08/1999 JosephJ added tmp ref in RmResumeTask
  1618. RmResumeTask now tmpref task before calling pfnHandler so that it can be
  1619. sure pTask is around on return from pfnHandler. Actually hit this situation today
  1620. (and bugchecked) on the mp machine during "net stop", when using the fake
  1621. ndis apis (with delayed completions.). Had never this this before, though the
  1622. bug has been around. Chalk up another win to the fake apis (see 04/07/199
  1623. entry "fake api's caught...").
  1624. 04/08/1999 JosephJ Debug output of the fake ndis apis (during ttcp -t)
  1625. Following is debug spew during ttcp -t, on a 2-proc machine with fake
  1626. NdisCoSendPackets in place (you can see both processors being used, as well
  1627. as the variations of delay, dpc/passive, failure status).
  1628. ...
  1629. 1:A13: FakeCompletionTask:START: Delay=1000; fDpc=0; Status=0
  1630. 0:A13: FakeCompletionTask:START: Delay=10000; fDpc=0; Status=3221225473
  1631. 0:A13: FakeCompletionTask:START: Delay=10; fDpc=0; Status=0
  1632. 0:A13: FakeCompletionTask:START: Delay=10; fDpc=1; Status=0
  1633. 1:A13: FakeCompletionTask:START: Delay=100; fDpc=0; Status=3221225473
  1634. 0:A13: FakeCompletionTask:START: Delay=100; fDpc=1; Status=3221225473
  1635. 1:A13: FakeCompletionTask:START: Delay=100; fDpc=1; Status=3221225473
  1636. 1:A13: FakeCompletionTask:START: Delay=100; fDpc=1; Status=3221225473
  1637. 1:A13: FakeCompletionTask:START: Delay=10; fDpc=0; Status=0
  1638. 1:A13: FakeCompletionTask:START: Delay=10; fDpc=1; Status=0
  1639. ...
  1640. 04/10/1999 JosephJ defined ioctl commands
  1641. Defined the following operations and associated structures in ioctl.h
  1642. ARP1394_IOCTL_OP_ADD_STATIC_ENTRY
  1643. ARP1394_IOCTL_OP_DEL_STATIC_ENTRY
  1644. ARP1394_IOCTL_OP_GET_PACKET_STATS
  1645. ARP1394_IOCTL_OP_GET_TASK_STATS
  1646. ARP1394_IOCTL_OP_GET_ARPTABLE_STATS
  1647. ARP1394_IOCTL_OP_GET_CALL_STATS
  1648. 04/19/1999 JosephJ Various ways of using tasks
  1649. 1. Dealing with pre-existing tasks
  1650. 1a. Check BEFORE starting new task...
  1651. if not bound
  1652. allocate and initialize task, then bind it.
  1653. else do one of...
  1654. - succeed operation immediately
  1655. - fail operation immediately
  1656. - pend some other task on it
  1657. - block until existing task completes.
  1658. PROBLEM: what to do if some other task is bound and only one task
  1659. can be bound at a time?
  1660. 1b. Check AFTER starting new task...
  1661. if not bound
  1662. bind
  1663. do other ttuff
  1664. else do one of...
  1665. - complete task successfully
  1666. - fail task
  1667. - pend on the other task
  1668. 2. Dealing with async sub tasks...
  1669. 2a. single section of common code; pending complete parts may do some initial
  1670. processing and then go to the common code section.
  1671. 2b. no common code -- each section does stuff and initiates a real or fake
  1672. suspention to move on to the next section.
  1673. 2c. switch with fall through to lower section.
  1674. 04/19/1999 JosephJ Cleaning up interface shutdown....
  1675. ToDo:
  1676. 2. Switch to approach 2c above.
  1677. 04/19/1999 JosephJ Proposed new general format for unloadobject:
  1678. Eventually we'll move all unloads to conform to this format, and change
  1679. RmUnloadAllObjects in group to use this mechanism....
  1680. NDIS_STATUS
  1681. arpUnloadIf(
  1682. PARP1394_INTERFACE pIF,
  1683. PRM_TASK pCallingTask, // OPTIONAL
  1684. UINT SuspendCode, // OPTIONAL
  1685. PRM_STACK_RECORD pSR
  1686. )
  1687. /*++
  1688. Routine Description:
  1689. Initiate the asynchronous unload of pIF. If pIF is currently being loaded
  1690. (initialized), abort the initializeation or wait for it to complete before
  1691. unloading it. If pIF is currently being unloaded and pCallingTask is
  1692. NULL, return right away, else (pCallingTask is not NULL),
  1693. suspend pCallingTask and make it pend until the unload completes.
  1694. NO locks must be held on entrance and none are held on exit.
  1695. Arguments:
  1696. pIF - Interface to unload.
  1697. pCallingTask - Optional task to suspend if unload is completing async.
  1698. SuspendCode - SuspendCode for the above task.
  1699. Return Value:
  1700. NDIS_STATUS_SUCCESS -- on synchronous success OR pCallingTask==NULL
  1701. NDIS_STATUS_PENDING -- if pCallingTask is made to pend until the operation
  1702. completes.
  1703. --*/
  1704. {
  1705. ...
  1706. }
  1707. 04/20/1999 JosephJ Do we have a "pPrimaryTask" for an object.
  1708. Consider ARP1394_INTERFACE.
  1709. We could have 3 pointers: pLoadTask,pUnloadTask, and pReinitTask, or
  1710. we could have a single pointer: pPrimaryTask.
  1711. New\Current Loading Reiniting Unloading
  1712. Loading INVALID INVALID INVALID
  1713. Reiniting wait wait,then quit quit or wait, then quit
  1714. Unloading wait wait wait
  1715. From the above matrix, we see that in all cases if an incoming task sees that
  1716. there is an existing task, it can basically wait for it to complete before
  1717. going on to the next stage. It is simpler to do this if there is only
  1718. one "existing task" to wait for -- the pPrimaryTask.
  1719. Common code for the task handlers:
  1720. case START:
  1721. // FALL THROUGH
  1722. case PEND_ExistingPrimaryTaskComplete:
  1723. LOCKOBJ(pIF, pSR);
  1724. if (pIF->pPrimaryTask!=NULL)
  1725. {
  1726. PRM_TASK pPrimaryTask = pIF->pPrimaryTask;
  1727. tmpRef(pIF->pPrimaryTask,pSR);
  1728. UNLOCKOBJ(pIF,pSR);
  1729. RmPendTaskOnOtherTask(
  1730. pTask,
  1731. PEND_ExistingPrimaryTaskComplete,
  1732. pPrimaryTask,
  1733. pSR
  1734. );
  1735. Status = NDIS_STATUS_PENDING;
  1736. break;
  1737. }
  1738. //
  1739. // There is no primary task currently -- make pTask the primary task.
  1740. //
  1741. arpSetPrimaryIfTask(pIF, pTask, pSR);
  1742. .... start doing stuff ...
  1743. 04/20/1999 JosephJ Dbg associations: consider adding a payload
  1744. Maybe replace entity 2 by "payload" -- like szFormat, it's not used in
  1745. distinguishing different associations. This is useful if you want to make
  1746. sure that there is only one kind of a particular association, but still save
  1747. the payload as part of the association.
  1748. 04/20/1999 JosephJ Note on RM "philosophy"
  1749. - High-level logical concepts should have real data structures associated
  1750. with them -- eg "reconfiguring", "initializing" use tasks.
  1751. - Try to keep code associated with a single logical operation together
  1752. 04/21/1999 JosephJ Life of objects contd...
  1753. States: INITING INITED REINITING DEINITING DEINITED
  1754. Actions:
  1755. Create -- synchronous, leaves state in INITING stage.
  1756. Bind -- object is now visible
  1757. Initialize -- async initialization
  1758. Reinit -- async re-initialization
  1759. Deinit -- async de-initialization
  1760. deleted.
  1761. Delete -- inverse of Create, except that object is only actually freed
  1762. when the refcount goes to zero..
  1763. Sub states: ACTIVE,DEACTIVATING,ACTIVATING, DEACTIVATED
  1764. Sub actions:
  1765. Activate -- async activation
  1766. Deactivate -- async deactivation
  1767. 04/23/1999 JosephJ arpTaskUnloadRemoteIp <-> arpTaskSendPktsOnRemoteIp interaction
  1768. arpTaskUnloadRemoteIp checks only on starting if there is a send-task bound
  1769. to pRemoteIp -- it relies on the fact that once the unload task is
  1770. bound, no NEW pSendTask will bind to pRemoteIp. The sendpkts task thus
  1771. needs to check whether there is a pUnloadTask bound and if so not bind
  1772. itself. This fix was added today -- I hit it during stress. There may be
  1773. analogous bugs hiding elsewhere.
  1774. We should consider how to make these things "automatic" -- somehow the
  1775. unload task waits for all tasks started before unload to finish,
  1776. and all non-unload-related tasks automatically fail if unload is in progress.
  1777. 04/25/1999 JosephJ More Task Stats
  1778. -- count of number of times a task's handler is called
  1779. 04/30/1999 JosephJ Bug in the way we read adapter config.
  1780. Basically, immediately after our call to NdisOpenAdapter completes, we may
  1781. get a call to our ArpCoAfRegisterNotify. The latter can't assume that
  1782. the task that issued NdisOpenAdapter is in fact completed, and on MP machines,
  1783. in fact it sometimes doesn't complete.
  1784. So what to do? Currently we fix this by pending on the adapter bind task if
  1785. it is in fact arpTaskInitializeAdapter. A bit hacky...
  1786. 04/30/1999 JosephJ Bug in the way we handle RmResumeTask and perhaps others..
  1787. We can't rely on the state of the task after calling the handler function,
  1788. because the lock is released in between.
  1789. 05/18/1999 JosephJ Stats gathering.
  1790. Potential apis to use:
  1791. NdisGetCurrentSystemTime returns the current system time, suitable for setting
  1792. timestamps.
  1793. KeQueryPerformanceCounter provides the finest grained running count available
  1794. in the system. KeQueryPerformanceCounter is intended for time stamping packets
  1795. or for computing performance and capacity measurements. It is not intended for
  1796. measuring elapsed time, for computing stalls or waits, or for iterations.
  1797. Use this routine sparingly, calling it as infrequently as possible. Depending
  1798. on the platform, KeQueryPerformanceCounter can disable system-wide interrupts
  1799. for a minimal interval. Consequently, calling this routine frequently or
  1800. repeatedly, as in an iteration, defeats its purpose of returning very
  1801. fine-grained, running time-stamp information. Calling this routine too
  1802. frequently can degrade I/O performance for the calling driver and for the
  1803. system as a whole.
  1804. Implementation:
  1805. pIf->stats.StatsResetTime; // Set by a call to NdisGetCurrentSystemTime.
  1806. Sends:
  1807. Pkt.WrapperReservedEx[sizeof(PVOID)] -- used for storing 4-byte timestamp.
  1808. Tasks:
  1809. Add LONGLONG timestamp field for tasks; Stats actually maintained within rm.
  1810. (Later to be moved into root object header).
  1811. sendpkts:
  1812. TotSends; -- LOGSTATS_TotSends
  1813. FastSends; LOGSTATS_FastSends
  1814. MediumSends; LOGSTATS_MediumSends
  1815. SlowSends; LOGSTATS_SlowSends
  1816. BackFills; LOGSTATS_BackFills
  1817. SendFifoCounts -- arpLogSendFifoCounts
  1818. SendChannelCounts -- TBD.
  1819. // HeaderBufUses -- see below
  1820. // HeaderBufCacheHits -- see below
  1821. sendinfo.FifoHeaderPool.stats:
  1822. TotBufAllocs -- LOGBUFSTATS_TotBufAllocs
  1823. TotCacheAllocs -- LOGBUFSTATS_TotCacheAllocs
  1824. TotAllocFails -- LOGBUFSTATS_TotAllocFails
  1825. recvpkts:
  1826. TotRecvs -- LOGBUFSTATS_TotRecvs
  1827. NoCopyRecvs -- LOGBUFSTATS_NoCopyRecvs
  1828. CopyRecvs -- LOGBUFSTATS_CopyRecvs
  1829. ResourceRecvs -- LOGBUFSTATS_ResourceRecvs
  1830. RecvFifoCounts -- LOGBUFSTATS_RecvFifoCounts
  1831. RecvChannelCounts -- TBD.
  1832. arpcache:
  1833. TotalQueries -- TBD
  1834. SuccessfulQueries -- TBD
  1835. FailedQueries -- TBD
  1836. TotalResponses -- TBD
  1837. TotalLookups -- LOGSTATS_TotalArpCacheLookups(pIF, Status);
  1838. // TraverseRatio <-- picked up from
  1839. pIF->RemoteIpGroup.HashTable.Stats
  1840. (LOWORD(Stats)/HIWORD(Stats))
  1841. calls:
  1842. TotalSendFifoMakeCalls -- LOGSTATS_TotalSendFifoMakeCalls
  1843. SuccessfulSendFifoMakeCalls -- LOGSTATS_SuccessfulSendFifoMakeCalls
  1844. FailedSendFifoMakeCalls -- LOGSTATS_FailedSendFifoMakeCalls
  1845. IncomingClosesOnSendFifos -- LOGSTATS_IncomingClosesOnSendFifos
  1846. TotalChannelMakeCalls -- LOGSTATS_TotalChannelMakeCalls
  1847. FailedChannelMakeCalls -- (TBD) LOGSTATS_SuccessfulChannelMakeCalls
  1848. SuccessfulChannelMakeCalls -- (TBD) LOGSTATS_FailedChannelMakeCalls
  1849. IncomingClosesOnChannels -- (TBD) LOGSTATS_IncomingClosesOnChannels
  1850. tasks:
  1851. TotalTasks -- TBD
  1852. CurrentTasks -- TBD
  1853. TimeCounts -- TBD
  1854. 06/03/1999 Broadcast channel support in ARP1394.
  1855. Arp1394 needs to make a call specifying special-channel number
  1856. "NIC1394_BROADCAST_CHANNEL". It must not specify the
  1857. NIC1394_VCFLAG_ALLOCATE flag.
  1858. The broadcast channel is a virtual channel maintained by the miniport for
  1859. broadcast. The miniport deals with the details of the BCM and the re-allocating
  1860. of the channel after a bus reset.
  1861. Arp1394 tries just once, during interface activation, to make a call to
  1862. the broadcast channel. It does not fail initialization if the call fails.
  1863. If we get an incoming close on this channel, arp1394 does not try to
  1864. re-make the call.
  1865. TODO: need to add eventlog entries for serious errors
  1866. like these.
  1867. TODO: perhaps keep an internal log of serious errors like these, which our
  1868. utility can dump (eventually move to WMI).
  1869. The make-call to the channel is made by the interface-activation task
  1870. (arpTaskActivateInterface) and closed by the interface-deactivation task
  1871. (arpTaskDeactivateInterface).
  1872. 06/03/1999 Address resolution protocol implementation
  1873. We start an address-resolution (AR) task for each remote-ip that needs address
  1874. resolution. pRemoteIp->pResolutionTask points to the official AR task.
  1875. The AR's task is responsible for creating and linking a pDest to the remote IP.
  1876. Note that there may be many tasks (each associated with different remote-ip
  1877. objects) running concurrently, each of which resolve to the same pDest.
  1878. The AR task goes through the following steps:
  1879. - prepare and send an arp request
  1880. -- resume-task delayed
  1881. [if we get a response that corresponds to this remote-IP,
  1882. we setup the linkage to the pDest and cancel the delayed resume-task]
  1883. -- if resume-task-delayed resumes normally (this is a timeout), we
  1884. repeat the process 3 times, then fail.
  1885. 06/08/1999 Broadcast channel implementation plan.
  1886. 1. Implement and test bc channel setup/teardown using fake makecalls.
  1887. 2. Implement and test 1st phase of arp resolution (sending out 3 requests)
  1888. by using fake send packets on the broadcast channel.
  1889. 3. Implement the remaining phases of arp resolution -- processing received
  1890. responses and requests.
  1891. 4. Perhaps test this by adding to ioctl utility ability to simulate received
  1892. packets.
  1893. 06/23/1999 Dealing with different kinds of VCs.
  1894. We need a common VC header.
  1895. typedef struct
  1896. {
  1897. PCHAR Description;
  1898. CO_SEND_COMPLETE_HANDLER CoSendCompleteHandler;
  1899. CO_STATUS_HANDLER CoStatusHandler;
  1900. CO_RECEIVE_PACKET_HANDLER CoReceivePacketHandler;
  1901. CO_AF_REGISTER_NOTIFY_HANDLER CoAfRegisterNotifyHandler;
  1902. CL_MAKE_CALL_COMPLETE_HANDLER ClMakeCallCompleteHandler;
  1903. CL_CLOSE_CALL_COMPLETE_HANDLER ClCloseCallCompleteHandler;
  1904. CL_INCOMING_CLOSE_CALL_HANDLER ClIncomingCloseCallHandler;
  1905. } ARP_STATIC_VC_INFO;
  1906. typedef struct
  1907. {
  1908. ARP_STATIC_VC_INFO pStaticInfo;
  1909. UINT
  1910. } ARP_VC_HEADER;
  1911. 06/24/1999 Implementing timeouts
  1912. We have RmResumeTaskDelayed, which uses NdisSetTimer;
  1913. We need something like RmResumeDelayedTaskNow which cancels the timer and if
  1914. the timer has not fired, resumes the task with an appropriate status.
  1915. Since responses to arp requests may come at random times or not at all,
  1916. the task should not have a stage which completes when the response is received;
  1917. or rather it should not be explicitly completing whenever a response is
  1918. received. Instead, if a response is received, the following should happen:
  1919. - Update the information in the destination object, setting the state to
  1920. be resolved.
  1921. - If a task is running, abort it
  1922. The task does the following (asynchronously)
  1923. while (state != resolved && (number of tries not exceeded))
  1924. {
  1925. send arp request packet;
  1926. wait retry-delay << this wait will be aborted if an arp response
  1927. << is received.
  1928. }
  1929. This deals with receiveing delayed or unsolicited arp responses while in the
  1930. middle of address resolution.
  1931. 06/24/1999 A note on refcounts for timeouts:
  1932. We need to make sure that in all cases, the task is around when the timer fires.
  1933. This needs to happen even when RmResumeDelayedTaskNow is called.
  1934. RmResumeDelayedTask should do the following:
  1935. if (CancelTimer succeeds)
  1936. {
  1937. Call resume task handler
  1938. }
  1939. else
  1940. {
  1941. do nothing.
  1942. }
  1943. So I don't think any explicit ref counting need be done for the tasks after all!
  1944. 06/24/1999 Dealing with broadcast/multicast addresses which may map to either
  1945. the broadcast channel or a mcap-allocated channel.
  1946. One idea is to implement the broadcast channel as a destination object.
  1947. This is a good idea, because then a lot of things will fall through.
  1948. We do need to actually establish the call, but this can be done implicitly when
  1949. we send our unsolicited arp response when the first add-ip arrives.
  1950. 06/28/1999
  1951. To implement the above scheme, we also need to do the arp-registration work,
  1952. and rip out the code we're written to maintain the explicit broadcast channel
  1953. (stuff in pIF->bccinfo).
  1954. ArpCoSendComplete -- needs to look at vctype and/or packets to decide what
  1955. to do for the broadcast channel case.
  1956. 07/01/1999 JosephJ Broadcast/Multicast "address resolution"
  1957. To maximize shared code, we treat broadcast and multicast sends similarly
  1958. to unicast sends, except that we automatically resolve them to the broadcast
  1959. channel in stead of sending out an ARP request for them.
  1960. So the first time we are asked to send to non-unicast address A, we go down
  1961. the slow send path, create a remote-IP object for it, link it to the broadcast
  1962. channel destination destination object, and go from there.
  1963. We DO need to know if this is a non-unicast address, but we only check this
  1964. if there is NO linkage to a destination object -- which will happen only on
  1965. the FIRST packet sent to that particular ip address. Subsequent packets will
  1966. go through the medium send path (look up remoteIP, send on the VC associated
  1967. with the destination object).
  1968. The test for whether an address is non-unicast is not trivial, and is borrowed
  1969. from the atmarpc code -- basically it needs to check for classD,
  1970. all-1's, subnet-broadcast (based on the subnet-masks of all the local
  1971. IP adresses registered), and network broadcast (based on the break up of address
  1972. space into classes.)
  1973. Following is an example of the list of local IP addresses registered
  1974. 0: kd> dd 0x80872628+0x4c l3
  1975. 80872674 00000002 ffffffff 00000000 <<< all 1's
  1976. 0: kd> dd 0x80856828+0x4c l3
  1977. 80856874 00000000 bbfdfea9 0000ffff <<< local IP, subnet mask 0xffff
  1978. 0: kd> dd 0x80857128+0x4c l3
  1979. 80857174 00000001 010000e0 00000000 <<< class D address 224.0.0.1
  1980. NOTE: According to Amritansh, the stack could also be run in "BSD mode", where
  1981. all-ZEROs represents the broadcast address -- even in the host-id portion
  1982. for directed broadcasts. This is why the broadcast address is passed in
  1983. as a "Add local address."
  1984. 07/02/1999 Support for enumerating all objects in a group.
  1985. Currently this is required in 4 places:
  1986. 1. ioctl.c -- looking for a specific interface
  1987. 2. ioctl.c -- looking for a unicast local-ip object
  1988. 3. ioctl.c -- reporting the arp table.
  1989. 4. ip.c -- reporting the arp table.
  1990. 5. ip.c -- determining if an ip address is non-unicast.
  1991. It would be good for the rm api's to support enumeration through all items
  1992. in a group.
  1993. PVOID
  1994. RmEnumerateObjectsInGroup(
  1995. pGroup,
  1996. pfnFunction,
  1997. pvContext,
  1998. pSR
  1999. );
  2000. Enumeration continues until the enumerator function returns false.
  2001. typedef
  2002. INT
  2003. (*PFN_RM_GROUP_ENUMERATOR) (
  2004. PRM_OBJECT_HEADER pHdr,
  2005. PVOID pvContext,
  2006. PRM_STACK_RECORD pSR
  2007. );
  2008. 07/07/1999 JosephJ
  2009. DONE:
  2010. 1. Define the common vc header structure, including the specialized
  2011. co handlers, and incorporate that into the existing code.
  2012. 2. Modify activate interface task to create the BCDO (broadcast channel
  2013. destination object) and make a call to it. Add a link between the BCDO and
  2014. the interface object.
  2015. 3. Modify the deactivate task to remove the above link.
  2016. 4. Add code to existing resolution task to hardcode the mapping from broadcast
  2017. and multicast addreses to the BCDO.
  2018. 5. Write handlers for send complete & receive to/from the BCDO channel.
  2019. 10. Write ARP packet management code (pkt queues).
  2020. 9. TEST with REAL make calls and send packets.
  2021. - as above
  2022. - verify that the bcast packets are received.
  2023. 13. Implement CancelResumeTaskDelayed.
  2024. 11. Write arp address resolution task -- originating side.
  2025. 12. Write arp request handling code.
  2026. 14. Write SendArpPktOnBCDO function.
  2027. TODO:
  2028. -------
  2029. 6. Code review the major paths
  2030. -------
  2031. 7. TEST with FAKE make calls & FAKE send packets.
  2032. - verify that bc channel is created and bcast packets are sent on the BC
  2033. channel.
  2034. - verify that the BC channel is cleaned up on net stop arp1394.
  2035. 8. TEST with REAL make calls and FAKE send packets.
  2036. - as above.
  2037. -------
  2038. -------
  2039. 15. Code review the major paths.
  2040. -------
  2041. 16. TEST with FAKE make calls & FAKE send packets.
  2042. - verify that bc channel is created and bcast packets are sent on the BC
  2043. channel.
  2044. - verify that the BC channel is cleaned up on net stop arp1394.
  2045. - verify that arp requests are being composed and sent.
  2046. 17. TEST with REAL make calls and FAKE send packets.
  2047. - as above.
  2048. 18. TEST with REAL make calls and send packets.
  2049. - plus verify that the bcast and arp-request packets are received.
  2050. - verify that arp responses are being generated and received.
  2051. - get ping to work without pre-populating the arp table.
  2052. 07/09/1999 ResumeDelayedTaskNow semantics and problems.
  2053. Is it possible for someone to call ResumeDelayedTaskNow and have it resume
  2054. 07/13/1999 Lookaside lists for protocol data.
  2055. We could use lookaside lists (NdisAllocateFromNPagedLookasideList) for protocol
  2056. packet data, but we choose to use
  2057. NdisAllocateMemoryWithTag, because we don't expect to be using a lot of these
  2058. packets.
  2059. 07/13/1999 General thoughts on fault insertion.
  2060. Either the implementation of APIs themselves should have a mechanism for fault
  2061. insertion, or there should be a machanism to add a shim that inserts faults.
  2062. Either way, it would catch many many bugs that would otherwise go undetected.
  2063. 07/13/1999 protocol context for ARP pkts:
  2064. We use the PCCommon structure defined in ip.h even for ARP packets. This
  2065. is also done in the ATM arp module (atmarpc.sys). sizeof(struct PCCommon)
  2066. The only field we actually USE however, is PCCommon.pc_owner, to distinguish
  2067. it from IP pkts on send completion.
  2068. 07/14/1999 Making sure we properly abort the resolution task.
  2069. pResolutionTask needs to have to variables:
  2070. fAbort
  2071. fTimerInitialized
  2072. if (fTimerInitialized, it's ok to called cancel timer)
  2073. if (fAbort, then the task won't do a resume).
  2074. Never mind. This is best handled WITHIN the RM API's, by appropriate use
  2075. of internal.
  2076. The semantics of ResumeDelayedTaskNow are as follows:
  2077. It will cause the abort of the task if it's currently delay-suspended OR. If it
  2078. is NOT suspended, it will cause an immediate abort the NEXT time it is
  2079. suspended. After the abort, the state is cleared so it will not cause the abort
  2080. of a subsequent suspension.
  2081. States/Flags
  2082. - DELAYED
  2083. - ABORT_DELAY
  2084. ResumeDelayedTaskNow:
  2085. lock
  2086. if (delayed)
  2087. {
  2088. clear abort-delay
  2089. clear delayed
  2090. if (CancelTimer)
  2091. {
  2092. unlock
  2093. call completion ourselves.
  2094. }
  2095. else
  2096. {
  2097. unlock
  2098. }
  2099. }
  2100. else
  2101. {
  2102. State |= abort-delay
  2103. unlock
  2104. }
  2105. ResumeDelayedTaskNow (VERSION 2)
  2106. lock
  2107. if (delayed)
  2108. {
  2109. if (CancelTimer)
  2110. {
  2111. unlock
  2112. call timeout handler ourselves.
  2113. }
  2114. else
  2115. {
  2116. unlock
  2117. }
  2118. }
  2119. else
  2120. {
  2121. State |= abort-delay
  2122. unlock
  2123. }
  2124. ResumeTaskDelayed:
  2125. lock
  2126. assert(state!=delayed)
  2127. if (abort-delay)
  2128. {
  2129. clear abort-delay
  2130. unlock
  2131. call completion ourselves.
  2132. }
  2133. else
  2134. {
  2135. init-timer
  2136. State |= delayed
  2137. unlock
  2138. set-timer
  2139. lock
  2140. if (abort-delay && delayed)
  2141. {
  2142. clear abort-delay
  2143. clear delayed
  2144. if (CancelTimer)
  2145. {
  2146. unlock
  2147. call completion ourselves
  2148. }
  2149. else
  2150. {
  2151. unlock
  2152. }
  2153. }
  2154. else
  2155. {
  2156. unlock
  2157. }
  2158. }
  2159. ResumeTaskDelayed: (VERSION 2)
  2160. lock
  2161. assert(state!=delayed)
  2162. init-timer
  2163. State |= delayed
  2164. if (abort-delay)
  2165. {
  2166. unlock
  2167. call timer handler ourselves.
  2168. }
  2169. else
  2170. {
  2171. set-timer << important to do this BEFORE unlocking!
  2172. unlock
  2173. }
  2174. TimerHandler:
  2175. lock
  2176. assert(delayed)
  2177. clear abort-delay
  2178. clear delayed
  2179. unlock
  2180. Actually resume task.
  2181. // Task delay state
  2182. //
  2183. RM_SET_STATE(pObj, RMTSKDELSTATE_MASK, RMTSKDELSTATE_DELAYED)
  2184. // Task abort state
  2185. //
  2186. RM_SET_STATE(pObj, RMTSKABORTSTATE_MASK, RMTSKABORTSTATE_ABORT_DELAY)
  2187. bp arp1394!DbgMark "dd esp+4 l1"
  2188. 007a0585
  2189. 2c48c626
  2190. 2f3b96f3
  2191. 30b6f7e2
  2192. 3be1b902
  2193. 6f31a739
  2194. c627713c
  2195. daab68c3
  2196. e4950c47
  2197. e9f37ba9
  2198. f87d7fff
  2199. arpCompleteSentPkt -- needs to deal with arp-generated pkts.
  2200. 07/15/1999 Building for win98
  2201. nd.c(140) : error C1189: #error : "Un
  2202. co.c(1796) : error C1189: #error : "Check if ARP1394_IP_PHYSADDR_LEN value is ok..."
  2203. bp arp1394!arpProcessReceivedPacket
  2204. bp arp1394!arpProcessArpPkt
  2205. bp arp1394!arpProcessReceivedPacket+294 "r ecx"
  2206. bp arp1394!arpParseArpPkt
  2207. bp arp1394!arpProcessArpRequest
  2208. bp arp1394!arpProcessArpResponse
  2209. 07/16/1999 Win98 Build plan.
  2210. Handle the unicode/ansi transition.
  2211. Test.
  2212. Stuff which needs to change:
  2213. co.c arpCallAddInterface
  2214. (atm:
  2215. adapter.c AtmArpBindAdapterHandler saves away unicode version of config string
  2216. (SystemSpecific1) in pAdapter->ConfigString.
  2217. (arpcfg.c) AtmArpCfgReadAdapterConfiguration -- uses pAdapter->ConfigString
  2218. to open and read the adapter's configuration;
  2219. AtmArpCfgReadAdapterConfiguration is called in only one place --
  2220. AtmArpCoAfRegisterNotifyHandler.
  2221. utils.c AtmArpAddInterfaceToAdapter
  2222. W2K: pInterface->IPConfigString = *pIPConfigString
  2223. W98: converted to ANSI first, but NOT saved in pInterface->IPConfigString.
  2224. Further down, specifies the converted string in the call to IP's
  2225. pIPAddInterfaceRtn.
  2226. Need to see what we dow with pInterface->IPConfigString in W2K.
  2227. arpif.c AtmArpReStartInterface -- uses it to call
  2228. AtmArpCfgOpenLISConfigurationByName and AtmArpAddInterfaceToAdapter
  2229. Another IPConfigString:
  2230. pAdapter->IPConfigString -- used to find interface
  2231. (in AtmArpPnPReconfigHandler, a config-string is passed in).
  2232. Gets it's value from the registry (arpcfg.c, AtmArpCfgReadAdapterConfiguration).
  2233. This is not W98 specific.
  2234. AtmArpCfgOpenLISConfiguration uses it to get the configuration name before
  2235. opening the registry.
  2236. In summary there are THREE strings:
  2237. pAdapter->ConfigString <- passed in adapter bind handler SS1 (W98 only:
  2238. converted from ANSI to unicode).
  2239. <- used in reg af-handler to read registry.
  2240. (pAdapter->bind.ConfigName)
  2241. pAdapter->IPConfigString <- read from registry as unicode
  2242. <- used to create an IF (or multiple for ipatmc).
  2243. (pAdapter->bind.IpConfigString)
  2244. pInterface->IPConfigString <- constructed from pAdapter->IPConfigString.
  2245. (W98: converted to ANSI before calling IP's
  2246. add-IF rtn.)
  2247. (pIF->ip.ConfigString)
  2248. 07/22/1999 JosephJ Ryan Schoff got atmarpc.sys (aka arp1394.sys) loaded under win98.
  2249. We hit a breakpoint in NDIS.SYS complaining about the NULL SendCompleteHandler.
  2250. I had set some handlers to NULL because they would never be used, and W2K NDIS
  2251. is happy with that but NDIS is not.
  2252. 07/26/1999 JosephJ A-DavHar hit a bug in arp1394 during stress where we had
  2253. launched the recv-fifo cleanup task while a make-call task was ongoing. Fixed
  2254. the recv-fifo task to wait for the makecall task to complete before doing its
  2255. thing. TODO: Need to do this for the other kinds of VCs as well (
  2256. broadcast and send-fifo VCs).
  2257. 08/03/1999 JosephJ We hit the following assert:
  2258. A13: rmVerifyObjectState:FATAL: Object 0xFF8D4828 modified without lock held!
  2259. A13: rmVerifyObjectState:To skip this assert, type "ed 0xFF8D1B74 1; g"
  2260. A13: !ASSERT( !"Object was modified without lock held!" ) C:0xFF8D4828 L:4830, rm.c
  2261. This is because pRemoteIp's state was modified without RmLockObject(pRemoteIp)
  2262. being called on it (it's safe because we had pIF's lock at that time, and pRemoteIp
  2263. shares the lock with pIF). The bug is that we're not calling
  2264. RmDbgChangeLockScope before/after change pRemoteIp's state.
  2265. Hit this again -- this time -- same cause. Temporarily disabled assert. TODO: need
  2266. to cleanup the code by adding changelockscope.
  2267. 08/19/1999 JosephJ
  2268. Added code in n134cfg.c to initialize and dump the config rom unit directory
  2269. for 1394 net devices. Used code from wdk\1394\bus\buspnp.c
  2270. 08/23/1999 JosephJ Got arp1394.sys to load in Windows Millennium, build 23459...
  2271. This is with modified mstcp.dll and nettrans.inf that recognize the new
  2272. nic upper binding "ndis1394".
  2273. But arp1394.sys is s failing initialization because
  2274. arpCfgReadAdapterConfiguration is failing, which we would expect to ALWAYS
  2275. fail (even on w2k) because it's looking for subkey ATMARPC, which doesn't exist.
  2276. Perhaps it's because arpCfgReadAdapterConfiguration calls
  2277. NdisOpenConfigurationKeyByName which on w2k returns success
  2278. (but sets *pInterfaceConfigHandle to NULL) if the key doesn't exist.
  2279. It so happens that arpGetInterfaceConfiguration, which calls
  2280. arpCfgReadAdapterConfiguration, *can* deal with this somewhat indirect
  2281. failure mechanism without returning failure, but if
  2282. arpCfgReadAdapterConfiguration *were* to return failure, it returns failure.
  2283. I'm going to change arpGetInterfaceConfiguration so that it ignores
  2284. arpCfgReadAdapterConfiguration returning failure.
  2285. 08/24/1999 JosephJ Arp1394.sys now loads and works (ping works) on Millennium.
  2286. 09/16/1999 JosephJ Alternative to RmDbgChangeLockScope
  2287. See "08/03/1999 JosephJ We hit the following assert:" entry.
  2288. Instead of RmDbgChangeLockScope, we should add "RmDbgFakeLockObject"
  2289. and "RmDbgFakeUnlockObject" -- these functions just run the verification
  2290. code but do not actually lock/unlock the object. They *do* verify that the
  2291. object is indeed locked.
  2292. 09/17/1999 JosephJ Win98/Millennium Netconfig: IPConfig value under ndi\interface.
  2293. This is Win98/Millennium specific.
  2294. pIF->ip.ConfigString is an ANSI value. It is created by reading the "IPConfig"
  2295. value under the interface's key. With proposed changes to elminiate having to
  2296. change mstcp.dll, "IPConfig" will no longer be created. It so happens that
  2297. the value of IPConfig is the same as the interface key (which is passed into
  2298. System).
  2299. 09/17/1999 JosephJ [Version 2] Support for retail debugging or RM objects
  2300. [ See 03/22/1999 note with the same title]
  2301. For now, we're going to add 4 ptrs to EVERY object. We can back off from
  2302. this strategy later. This is PURELY for retail-mode debugging purposes.
  2303. - Support the following RM dbgextension:
  2304. !rm scantree <obj addr> <pattern>
  2305. -- scans the obj at addr <obj addr> and all its children for
  2306. pattern <pattern>
  2307. !rm tree <obj addr>
  2308. -- lists the entire tree of objects, starting at oject <obj addr>
  2309. Mon 09/27/1999 JosephJ !tree implemented
  2310. Real output:
  2311. Object Tree for 0xFD015340(ArpGlobals) with parent 0x00000000(<root>):
  2312. FD015340(ArpGlobals)
  2313. |---FE404608(Adapter)
  2314. |---|---FE3F99C8(INTERFACE)
  2315. |---|---|---FE33AF68(RemoteIp)
  2316. |---|---|---FE3C9948(LocalIp)
  2317. |---|---|---FE3CD648(LocalIp)
  2318. |---|---|---FE3CD7E8(LocalIp)
  2319. |---|---|---FE3F70C8(Destination)
  2320. Tue 09/28/1999 JosephJ Millennium llipif.h
  2321. We keep a win9x copy of llipif.h checked under w98\llipif.h.
  2322. I did a windiff against the llipif.h in \\muroc\slm
  2323. (\\muroc\slmro2\proj\net\vxd\src\tcpip\h\llipif.h)
  2324. I found that the muroc version had one field extra in the LLIPBindInfo struct:
  2325. ---------- TDI\TCPIPMERGE\1394\ARP1394\W98\llipif.h next ----------
  2326. 294a295
  2327. > uint lip_pnpcap; //initial pnp capability flags.
  2328. This is a set of flags used to determine Wakeuponlan capability.
  2329. Wed 09/29/1999 JosephJ Millennium tdiinfo.h
  2330. MAX_TDI_ENTITIES 32(mill) 4096(w2k)
  2331. INVALID_ENTITY_INSTANCE -1 (w2k) (not defined in mill). We don't use it either.
  2332. ArpIpGetEList appears to be the same as the Win9x version.
  2333. Fixed the problem
  2334. Basically the bug is that we were not checking entity value and type
  2335. for Win98 -- I copied that behavior from atmarpc, but it was in fact
  2336. not compiled in in atmarpc, because DBG_QRY WAS defined for win98 (see
  2337. arpif.c AtmArpIfQueryInfo).
  2338. BUGBG: need to look at the return value of AtmArpCopyToNdisBuffer -- the
  2339. code the checks this was added RECENTLY to atmarpc.sys -- after I created
  2340. the sources for arp1394. Apparantly we could hit this in low mem situations.
  2341. Mon 10/18/1999 JosephJ Bringing down the IF when the media is "disconnected"
  2342. From: Amritansh Raghav (Exchange)
  2343. yes (line down comes to me at dpc, so i delete off a worker thread)
  2344. -----Original Message-----
  2345. From: Joseph Joy (Exchange)
  2346. So you trigger add/del based on NDIS_STATUS_WAN_LINE_UP/DOWN?
  2347. -----Original Message-----
  2348. From: Amritansh Raghav (Exchange)
  2349. actually i do use IPAddInterface an IPDelInterface to do this
  2350. remember that this can only be done at PASSIVE so NdisStatus may not be the
  2351. place to do it (of course i got this to work by asking jameel to provide a hack
  2352. whereby he doesnt raise the irql for the lineup status indication)
  2353. -----Original Message-----
  2354. From: Joseph Joy (Exchange)
  2355. Hi Amritansh,
  2356. I'd like to dynamically make the IP interface associated with a 1394 adapter
  2357. appear and disappear based on whether there are any other ip/1394 capable
  2358. devices attached.
  2359. The local ndis1394 miniport itself stays enabled regardless of whether there
  2360. are remote nodes or not. So I'd like to trigger the appearance/disappearance
  2361. based on some status indication.
  2362. I'd like ipconfig to not list the interface at all (not just list it as
  2363. "disconnected") if there are no remote nodes active.
  2364. Looks like you have a solution for wan devices -- the interface is only
  2365. listed via ipconfig if there is an active wan connection. How is this done?
  2366. Arvind tells me that wanarp doesn't call IPDelInterface.
  2367. We've decided to trigger off "disconnected" status.
  2368. On register notify: check if status is disconnected.
  2369. If disconnected: don't init interface, else: init interface.
  2370. On connect notification: if IF is going away -- queue task to re-
  2371. start based on registry config (unless adapter going away).
  2372. On disconnect notification: start delayed task to get rid of adapter.
  2373. Mon 10/18/1999 Registering local arp addresses.
  2374. Ethernet arp has the following logic
  2375. ARPAddAddr:
  2376. for local, unicast addresses it
  2377. subits an arp request
  2378. returns IP_PENDING
  2379. NOTE: When sending an arp request, we need to be careful about which
  2380. Src ip address we use -- using the one for the correct subnet!
  2381. see ip\arp.c (SendARPRequest).
  2382. CONFLICT:
  2383. If it's a response confict and we're still registering the local address,
  2384. we fail the local address by calling
  2385. SendARPRequest(Interface, *SPAddr, ARP_RESOLVING_GLOBAL,)
  2386. IPAddAddrComplete(Address, SAC, IP_DUPLICATE_ADDRESS);
  2387. (where SAC == Context2 passed to our AddAddress routine).
  2388. Wed 11/03/1999 JosephJ RM: factoring out common functionality for load/unload
  2389. Rewriting adapter's arpTaskInitialize/ShutdownAdapter to be similar to
  2390. the interface's in the sense that there is a primary and secondary task,
  2391. and the primary task is the one responsible for (a) waiting for other
  2392. primary tasks to complete and (b) running the "compensating" transaction if the
  2393. the actual activate-adapter task fails. Also the task is written to minimize
  2394. the adapter-specific code -- with the view towards of eventually having
  2395. a generic RM-supplied task handler to do this for any object.
  2396. arpTaskInitialize/ShutdownAdapter are also written to emulate the flattening
  2397. of message types -- they handle start, pend-completes and end in a single
  2398. case statement which supports fallthrough.
  2399. TODO: consider adding pPrimaryTask and pSecondaryTask to the object header,
  2400. and adding Init/Shutdown (aka load/unload) and activate/deactivate handlers
  2401. to the object's static info. This will be required to move to
  2402. common load/unload handling.
  2403. ALSO: look at arp[Set|Clear][Primary|Secondary]IfTask in util.c -- these
  2404. could be generalized.
  2405. Wed 11/03/1999 JosephJ RM: Generalizing load/unload to arbitrary tasks
  2406. The general idea of (a) and (b) can be applied to other (user defined)
  2407. operations on the object, not just init/shutdown. Think about how RM can
  2408. provide standard "caretaker" tasks which will do (a) and (b) -- letting
  2409. the user-defined tasks focus on pure functionality, not queuing and cleanup
  2410. on failure -- the latter is a bit analogous to exception handling in the
  2411. synchronous world.
  2412. Wed 11/03/1999 JosephJ RM: More thoughts on state validation
  2413. Add the concept of a state validation function which gets called to validate
  2414. state transitions -- at the point the object is unlocked. The function is
  2415. given the old and new states (the rm object dword state variable).
  2416. Wed 11/03/1999 JosephJ RM: Validate parent type
  2417. Allow an object's static info to specify the allowed parent type -- this is
  2418. important because much code assumes that a parent is of a particular type.
  2419. E:\nt\public\tools
  2420. signcode -v %_NTBINDIR%\public\tools\driver.pvk -spc %_NTBINDIR%\public\tools\driver.spc -n "Microsoft Windows 2000 Test Signature" -i "http://ntbld" -t http://timestamp.verisign.com/scripts/timstamp.dll filetosign
  2421. chktrust win2k filename
  2422. --Scott
  2423. Fri 11/05/1999 JosephJ Why ICS wasn't binding to nic1394.h
  2424. Needed to add ndis1394 to the lower binding in setup\inf\usa\icsharep.inx
  2425. Fri 11/05/1999 JosephJ Debugging the "autonet address" problem.
  2426. The problem: We weren't getting an autonet address, and DHCP wasn't working.
  2427. From Scott Holden:
  2428. set a bp on RequestDHCPAddr (This is in VIP)
  2429. If it hits this breakpoint, then we are going to DHCP.
  2430. If it goes to DHCP, see if it hits VIP_Set_Addr or VIP_Set_Addr_Ex.
  2431. I set and found out that it was being called, but eventually it was failing
  2432. because arp1394 was failing a QueryInfo because it was not in the IF_PS_INITED
  2433. state (because the interface's init task was still running). Setting
  2434. the check in QueryInfo to take EITHER PS_INITED or AS_ACTIVATING made it
  2435. work.
  2436. Fri 11/05/1999 JosephJ Re-wrote adapter init/shutdown code
  2437. It's now a two-level scheme similar to what the interface uses --
  2438. init/shutdown and activate/deactivate.
  2439. Thu 11/11/1999 JosephJ Deferred interface init until adapter is "connected"
  2440. Modified arpTaskInitInterface (co.c) so that it will check if the
  2441. adapter is connected before proceeding to make the call to the broadcast
  2442. VC and (and subsequently adding the IF). It currently simply waits for 5
  2443. seconds before each attempt to check the connect state (it doesn't hook
  2444. into the connect notification -- we should do that). It also needs to
  2445. switch to passive before calling NdisRequest (which is actually a macro
  2446. which ends up calling NdisCoRequest in the context of a work item) -- because
  2447. we Block until the request completes asnc. So it's a lot of overhead just
  2448. to get the connect status which would be eliminated if we hooked into
  2449. the connect status notification. On the plus side: the modifications to
  2450. enable this delay-until-connect functionalty is very localized -- score one
  2451. for the RM Tasks!
  2452. Thu 11/11/1999 JosephJ RM: Finer granularity of tmpref end lock cheking
  2453. We should add support for checking that there are no outstanding
  2454. tmprefs and locks for *sub* trees of the call tree -- by allocating
  2455. stack variables that save the value of the lock and tmpref on entry.
  2456. Thu 11/11/1999 JosephJ RM: More flexible display of object logs
  2457. It would be nice to be able to display the integrated logs for an
  2458. object and it's sub-object (optionally upto a certain level).
  2459. We need to efficiently scan the global log looking for all entries
  2460. which meet this criterion. How do we do this?
  2461. One way is to build up
  2462. a hierarchical naming scheme for objects -- so we just do a prefix match
  2463. to decide if the object is a descendent of the particular top-level object
  2464. whose logs we are displaying.
  2465. All log entries will need to have the fully-qualified name of the object that
  2466. created the log.
  2467. A simpler scheme is simply to walk the parent list and display it if one of
  2468. the ancestors is the top-level object -- probably this will suffice for now.
  2469. TODO: we do need a way to keep logs available for objects that have gone away
  2470. -- how to do this? And what are the implications for the above hierarchical
  2471. display scheme?
  2472. Sat 11/13/1999 JosephJ Propery fill out arp sspd and maxrec
  2473. I was using constant values. Now I pick them up from the adapter info.
  2474. 11/16/1999 JosephJ MCAP Details
  2475. Receive side:
  2476. * Single multi-channel VC
  2477. * 64-byte TTL array for each channel.
  2478. * Incoming MCAP advertisement:
  2479. - go through recv mcast addresses -- If we're intersted in it,
  2480. add entry to channel.
  2481. * New MCAST group to receive:
  2482. - send out MCAP request 3 times and/or until resolved.
  2483. * Timer:
  2484. - Check TTL -- delete channel if required.
  2485. array[] of (TTL, NodeID) Unknown NodeID == FF (after bus reset).
  2486. 64-bit bitmap of channels currently used
  2487. pMultiRecvDest
  2488. - Vc
  2489. - Array of (TTL, NodeID)
  2490. - Bitmap
  2491. - pChangeChannelsTask
  2492. To Do:
  2493. 1. Mcap pkt parsing and generation code.
  2494. 2. Task to create multi-channel recv VC.
  2495. 3. Fake multi-channel VC handler.
  2496. 4. Add recv mcast-address: Task to send out MCAP requests
  2497. 5. Timer code: check TTL for mcast; check arp table -- timer stops
  2498. if no activity.
  2499. 6. Make ipfwadm generate fake MCAP recv packets.
  2500. http://www.ietf.org/internet-drafts/draft-ietf-ip1394-ipv4-19.txt
  2501. 11/18/1999 JosephJ Target_ip_address in arp response
  2502. From Sony's Kaz Honda November 18, 1999:
  2503. > So in ARP responses, the target_IP_address should be ignored. Regardless, we
  2504. > fill it with the target_IP_address
  2505. > of the ARP request (not the destination IP address). I don't think we're
  2506. > doing anything wrong here.
  2507. Hmm... Year, you're right. You're doing anything wrong literally.
  2508. But for the driver like ours which emulates Ethernet, 1394ARP is
  2509. transformed into EtherARP and the driver must fill target_IP_address
  2510. in EtherARP. So filling target_IP_address with the destination IP
  2511. address is more helpful.
  2512. So I now specify dest ip addr in the target_IP_address for arp responses.
  2513. 11/18/1999 JosephJ Ethernet emulation for ICS on Win98
  2514. 1. Create Ethernet VC on init IF.
  2515. -- send/recv handlers
  2516. --
  2517. 2. Add support for in fake calls.
  2518. VOID
  2519. NdisCopyFromPacketToPacket(
  2520. IN PNDIS_PACKET Destination,
  2521. IN UINT DestinationOffset,
  2522. IN UINT BytesToCopy,
  2523. IN PNDIS_PACKET Source,
  2524. IN UINT SourceOffset,
  2525. OUT PUINT BytesCopied
  2526. );
  2527. bp arp1394!arpIcsForwardPacket
  2528. bp nic1394!NicMpSendPackets
  2529. bp arp1394!arpndreceivepacket
  2530. bp arp1394!arpndsendcomplete
  2531. bp arp1394!arpIcsTranslatePkt
  2532. pTask=0x812f16e8; &OpType=0x812f17bc(0) &Delay=0x812f17b8
  2533. 01/28/2000 JosephJ MCAP revisited
  2534. For now, we'll implement both send & receive side, and use regular channels,
  2535. instead of multi-channel receive because of the complications of implementing
  2536. multichannel receive in NIC.
  2537. typedef struct
  2538. {
  2539. // Channel number.
  2540. //
  2541. UINT Channel;
  2542. // IP multicast group address bound to this channel.
  2543. //
  2544. IP_ADDRESS IpAddress;
  2545. // Absolute time at which this mapping will expire.
  2546. //
  2547. LARGE_INTEGER ExpieryTime;
  2548. // TBD
  2549. //
  2550. UINT Flags;
  2551. // NodeID of owner of this channel.
  2552. //
  2553. UINT NodeId;
  2554. } MCAP_CHANNEL_INFO;
  2555. MCAP_CHANNEL_INFO McapInfoArray[NUM_CHANNELS];
  2556. arpUpdateMcapInfo(pIF, pMcapPkt);
  2557. ---------------------------------------
  2558. Receive side:
  2559. Every 10 seconds, we do the following:
  2560. Check our list of local multicst addresses -- if any of them are in our mcap
  2561. database, initiate calls to them.
  2562. If they are pointing to obsolete channels., we teardown calls from them.
  2563. This process only goes on as long as there are (a) local mcast ip addresses
  2564. and (b) received advertise msgs.
  2565. Send side:
  2566. Check channel db -- if address is assigned a channel, make call to it.
  2567. We're going to create CHANNEL "Destinations" for both send & receive.
  2568. We'll thus be getting packets on channels even if we aren't
  2569. interested in them. That's ok for now; Later we'll add the ioctl support
  2570. for starting/stopping sends/receives.
  2571. So...
  2572. Destinations can be created if we're interested in either sending or receiving.
  2573. Periodic Task:
  2574. It's period varies depending on activity.
  2575. Can be woken up even if it's sleeping for a long time.
  2576. It does the following:
  2577. 1. Checks for ageing of pRemoteIPs
  2578. 2. Checks channel map and pDests, making sure that pDests are shut down if
  2579. uninteresting.
  2580. 3. Creates new pDests
  2581. ARP WORK ITEMS
  2582. 1. Age out entries
  2583. 2. Detect conflicts in local IP addresses.
  2584. 3. Display only unicast addresses in ipconfig.
  2585. 4. Don't queue packets to be sent out waiting for arp resolution -- only keep one
  2586. packet.
  2587. 5. Request an other FIFO address if ther one we asked for is already taken
  2588. (or ask nic1394 to allocate one for us).
  2589. 6. Remove "FATAL object locked w/o ..."
  2590. 7. Hook CONNECT/DISCONNECT notifications, and bring down stack (add some
  2591. damping).
  2592. DEBUGGING SUPPORT
  2593. 1. Collect address-resolution time statistics.
  2594. 2. OID to get and report NIC-specific stats via IPFWADM.EXE
  2595. x3. Option to make copies of packets on send and receive.
  2596. 4. Simple memory alloc wrappers.
  2597. 5. Get a13kd to work!
  2598. x6. Keep track of reentrancy
  2599. x7. MILL: make sure we call back to tcpip at passive.
  2600. IPFWADM modifications
  2601. Display address properly
  2602. ARP_COPY_RECV_PKTS
  2603. ARP_COPY_SEND_PKTS
  2604. ARP_COPY_PKTS
  2605. 02/05/2000 Fixed bug dealing with failure of const buffer allocation.
  2606. If arpSendIpPkt can't allocate a const buffer, we call arpCompleteSentPkt
  2607. with special return value NDIS_STATUS_NOT_RESETTABLE so that it knows
  2608. not to try to remove the const buffer. Of course, we'd break if the
  2609. miniport sompletes a send with this status. We have an assert to catch that.
  2610. 1. Change dest to include other params, change compare, "virtual channel"
  2611. 2. Re-write IntF/DeintIF to use msg normallzation
  2612. 3. Incorporate creation/deletion of maintenance task
  2613. 4. Maintainance task:
  2614. go through LIP list
  2615. for each LIP
  2616. go through channel list
  2617. if you find matching address
  2618. find recv channel
  2619. if found link?
  2620. go through RIP list
  2621. for each RIP send VC
  2622. if !marked dirty
  2623. mark dirty
  2624. if linked to channel pdest
  2625. check if channel is still mapped to group
  2626. if not, unlink.
  2627. if required initiate link to new pdest (possibly channel)
  2628. else
  2629. //expired
  2630. unlink from pdest and get rid of it
  2631. 02/10/2000 RM API thoughts -- reducing stack depth
  2632. See earlier references to this problem:
  2633. 03/13/1999 JosephJ New RM APIs RmResumeTaskAsync and RmResumeTaskDelayed
  2634. 03/25/1999 JosephJ IPDelInterface should be called at PASSIVE!
  2635. We can keep a list of tasks that need to be resumed in the stack record,
  2636. and resume those tasks in the context of the first rm api call.
  2637. Pseudo code:
  2638. RmResumeTask:
  2639. {
  2640. SET_RESUME_PARAM(pTask, Status);
  2641. QUEUE_RESUME_TASK(pTask, pSR);
  2642. if (MUST_QUEUE_RESUMETASK(pSR))
  2643. {
  2644. return; // RETURN
  2645. }
  2646. SET_MUST_QUEUE_RESUMETASK(pSR);
  2647. while (resume-task queue not empty)
  2648. {
  2649. extract head of queue
  2650. //
  2651. // Code from current version of RmResumeTask goes here...
  2652. // NOTE: the queue could get added to while processing this.
  2653. //
  2654. }
  2655. }
  2656. 02/11/2000 JosephJ When calling Mill IPAddInterface, it expects
  2657. the pConfigString unicode strings passed to it to be
  2658. null terminated. We were hit by this because apparently we just
  2659. happened to be null terminated until Mill build 2467.
  2660. 02/13/2000 JosephJ
  2661. ipfwadm additions
  2662. -send -ref <name>
  2663. -receive -ref <name>
  2664. -businfo
  2665. ipfwadm.ini
  2666. [Packets]
  2667. arp1 =
  2668. [Names]
  2669. <GUID> = "friendly name"
  2670. BUSINFO
  2671. 0 1 2 3 4 5 6
  2672. 0123456789012345678901234567890123456789012345678901234567890123
  2673. Channelmap = 0000000000000000000000000000000000000000000000000000000000000000
  2674. Generation = 0x1209 BusReset: 546 seconds ago
  2675. GUID NodeID MaxRec MaxSpeed MaxSpeedTo Handle State
  2676. *1234900900098990 01 0998 00999 00098 98909890 ACTIVE
  2677. IP1394-4 01 0998 00999 00098 98909890 ACTIVE
  2678. bp arpTaskIfMaintenance
  2679. bp arp1394!arpTaskIfMaintenance
  2680. bp arp1394!arpStartIfMaintenanceTask
  2681. bp arp1394!arpTryStopIfMaintenanceTask
  2682. bp arp1394!arpMaintainOneRemoteIp
  2683. bp arp1394!arpMaintainOneLocalIp
  2684. bp arp1394!arpDoMcapDbMaintenance
  2685. bp arp1394!arpUpdateLocalIpDest
  2686. bp arp1394!arpUpdateRemoteIpDest
  2687. bp arp1394!arpDeinitRemoteIp
  2688. bp arp1394!arpDeinitDestination
  2689. bp arp1394!arpIoctlRecvPacket
  2690. bp arp1394!arpIoctlSendPacket
  2691. bp arp1394!arpIoctlGetBusInfo
  2692. bp arp1394!arpProcessMcapPkt
  2693. 02/16/2000 JosephJ RM APIs observation
  2694. Don't write code after "SuspendTask/PendTask" -- it may not get executed
  2695. until after the task has been resumed -- this is counter intuitive.
  2696. For example:
  2697. we were setting pIF->pBroadcastDest to a pDest which was returned
  2698. after calling RmPendTaskOnOtherTask -- well the code to
  2699. set pIF->pBroadcastDest was not actually executed until the task
  2700. was complete -- the task completed in the context of the call
  2701. to RmPendTaskOnOtherTask itself! One more reason to implement
  2702. the resume-task-at-top-level semantings. (see 02/10/2000 entry).
  2703. 03/28/2000 JosephJ Outstanding RM work items.
  2704. 03/07/1999 JosephJ Registering root objects with RM
  2705. 03/09/1999 JosephJ Consider making init functions fail etc if associated object is
  2706. 03/09/1999 Special allocator for unload-related tasks
  2707. 08/15/00 - Route Cache Entries.
  2708. When the arp module is passed a Route Cache Entry, then it should
  2709. validate its contents because the contents could point to
  2710. another destination.
  2711. 11/15/00 - Only applicable to bridge mode -
  2712. The bridge sends STA packets to detect loops. These packets have a
  2713. unique EtherType. Arp1394 now acccepts this EtherType and propogates it
  2714. over the wire as part of the Link Layer (IP1394 Encapsulation) header.
  2715. The receiving arp1394 recognises the STA EtherType and
  2716. constructs a new Ethernet Header for the Packet as it is being translated
  2717. into Ethernet.
  2718. In bridge mode - The Remote Ip structure has an Ethernet Destination. This
  2719. causes problems when the pRemoteIp is used to construct an Arp Packet.
  2720. Therefore the actual Ip Address should be stored in pRemoteIp->IpAddress,
  2721. however all RemoteIp Lookups are done on the basis of the pRemoteIp->Key
  2722. 12/14/00 - A deadlock was uncovered in RmLookupObjectInGroup. To fix it, the function
  2723. can no longer guarantee the caller that the object will be created
  2724. and locked in the same operation. The Group lock will not be held
  2725. in conjunction with the Object Lock.