vsLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:23k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* vsLib.c - virtual stack management library */
  2. /* Copyright 2000 - 2001 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 02a,17jul01,ann  adding virtualStackNameGet/Set routines
  7. 01z,11jul01,jpf  Added a lot of minor refinements and virtualStackNumGet
  8. 01y,16apr01,jpf  Fixing this file to work with vs
  9. 01x,29mar01,spm  file creation: copied from version 01w of tor2_0.open_stack
  10.                  branch (wpwr VOB) for unified code base; converted memory
  11.                  allocation for protection domain restrictions
  12. 01w,21jul00,gnn  fixed it not to build when VIRTUAL_STACK is off
  13. 01v,23jun00,spm  used new routine for ARP initialization (from proxy ARP merge)
  14. 01u,12jun00,ta   add vsexec Shell command
  15. 01t,08jun00,ead  moved ARP initialization to arpInit in arpLib.c
  16. 01s,07jun00,ead  fixed a bug in virtualStackCreate that didn't check for the
  17.                  stack name
  18. 01r,07jun00,ead  modifed vsMakeStack to return a STATUS result
  19. 01q,26may00,ead  added ipMaxUnits argument to virtualStackInit()
  20. 01p,25may00,pul  adding ffInit() to virtualStackInit()
  21. 01o,22may00,ead  modifed vsMakeStack
  22. 01n,22may00,ead  added llinfo_arp initialization in virtualStackInit
  23.                  created the vsMakeStack function
  24. 01m,19may00,cn   changed all pName buffers to strings.
  25. 01l,17may00,cn   fixed bug in virtualStackNameTaskIdSet () and
  26.                  virtualStackIdGet ().
  27. 01k,05may00,ann  adding some initializations for m2 libraries
  28. 01j,05may00,gnn  added virtualStackShow which shows ALL virtual stacks
  29. 01i,04may00,spm  fixed initialization for UDP and show routines
  30. 01h,01may00,ann  adding some initializations for sockets and UDP
  31. 01g,26apr00,spm  updated startup instructions; added routing storage handling
  32. 01f,26apr00,gnn  fixed strlen/strcpy counting bug
  33. 01e,25apr00,spm  separated initialization and creation of virtual stacks
  34. 01d,25apr00,gnn  added clearing of each vsTbl entry as it's created
  35.                  added netLibInit() to initialize protocols
  36.                  added domain handling code
  37.                  fixed netPool handling code
  38. 01c,24apr00,gnn  added ifnet list handling
  39. 01b,23apr00,gnn  Added code to start up parts of the stack (splSemInit and
  40.                  mbinit) to virtualStackCreate.
  41. 01a,09mar00,gnn  written.
  42. */
  43.  
  44. /*
  45. DESCRIPTION
  46. This module implements the framework for Virtual TCP/IP Stacks.  Each stack is
  47. represented by a BSD_GLOBAL_DATA structure defined in
  48. target/h/netinet/vsData.h.  Please see that file for information on particular
  49. elements of that data structure.
  50. The system is an array of pointers to these structures stored in vsTbl and
  51. indexed by an integer from 0 to VSID_MAX.  There is a special stack, referred
  52. to as the management stack, which is defined as VS_MGMT_STACK.  This is
  53. defined in target/h/netinet/vsLib.h.
  54. For tasks calling into the stack we provide a current Virtual Stack
  55. number concept via a task variable called myTaskNum.  This variable can be
  56. gotten or set via a set of routines in this module.  Routines called in the
  57. context of a task (though NEVER tNetTask) it is possible to reference elements
  58. of the stack's virtual stack like this:
  59. .CS
  60. vsTbl[myTaskNum]->stackGlobalYouWantToLookAt
  61. .CE
  62. INCLUDE FILES: 
  63. SEE ALSO: taskVarLib
  64. */
  65. /*
  66.  * This huge ifdef means that the file gets run through the compiler but is
  67.  * empty in the case where we're building the stack without VIRTUAL_STACK
  68.  * support.
  69.  */
  70. #ifdef VIRTUAL_STACK
  71. /* includes */
  72. #include "vxWorks.h"
  73. #include "semLib.h"
  74. #include "logLib.h"
  75. #include "sysLib.h"
  76. #include "stdio.h"
  77. #include "stdlib.h"
  78. #include "arpLib.h"
  79. #include "hostLib.h"
  80. #include "usrConfig.h"
  81. #include "taskLib.h"
  82. #include "taskVarLib.h"
  83. #include "netinet/vsLib.h"
  84. #include "netinet/vsData.h"
  85. #include "memPartLib.h"
  86. #include "errnoLib.h"
  87. /* defines */
  88. /* globals */
  89. BSD_GLOBAL_DATA* vsTbl[VSID_MAX];
  90. int myStackNum; /* Task local stack number. */
  91. SEM_ID vsTblLock;
  92. /* locals */
  93. /* forward declarations */
  94. /*******************************************************************************
  95. *
  96. * virtualStackLibInit - initialize the Virtual Stack system
  97. *
  98. * This routine initializes all the global data required by the virtual stack
  99. * system.
  100. *
  101. * RETURNS: OK or ERROR if any resources are unavailable.
  102. *
  103. */
  104. STATUS virtualStackLibInit
  105.     (
  106.     )
  107.     {
  108.     int count;
  109.     /*
  110.      * Create a semaphore to protect our table.
  111.      */
  112.     vsTblLock = semBCreate (SEM_Q_PRIORITY, SEM_FULL);
  113.     if (vsTblLock == NULL)
  114.         return (ERROR);
  115.     
  116.     for (count = 0; count < VSID_MAX; count++)
  117.         {
  118.         vsTbl[count] = NULL;
  119.         }
  120.     return (OK);
  121.     }
  122. /*******************************************************************************
  123. *
  124. * virtualStackCreate - creates an instance of a virtual stack
  125. *
  126. * This routine creates an instance of a Virtual Stack and returns a pointer
  127. * to the VSID on successful completion.  Once this routine returns the
  128. * desired initialization sequence may be called to start the appropriate
  129. * protocols and initialize the network data structures.
  130. *
  131. * The <pName> argument supplies an optional name for the network stack.
  132. * If none is provided, the stack index (i.e.  0 1 2 ...) is assigned.
  133. *
  134. * RETURNS: OK or ERROR. If ERROR is returned the <pVID> contents are 
  135. * not valid.
  136. *
  137. */
  138. STATUS virtualStackCreate
  139.     (
  140.     char* pName,  /* Unique stack name, or NULL for default */
  141.     VSID* pVID  /* Buffer for storing virtual stack identifier */
  142.     )
  143.     {
  144.     int vsIndex, i;
  145.     char tempName[VS_NAME_MAX + 1];
  146.     
  147.     /* Lock out access until creation is complete or error is returned. */
  148.     semTake (vsTblLock, WAIT_FOREVER);
  149.     /* Find the first empty slot. */
  150.     for (vsIndex = 0; vsIndex < VSID_MAX; vsIndex++)
  151.         {
  152.         if (vsTbl[vsIndex] == NULL)
  153.             break; /* Hey, we found one! */
  154.         }
  155.     if (vsIndex == VSID_MAX)
  156.         {
  157.         semGive (vsTblLock);
  158.         return (ERROR);
  159.         }
  160.     /*
  161.      * If no name is passed simply make the name the
  162.      * VS number.
  163.      */
  164.     if (pName == NULL)
  165.         sprintf (tempName, "%d", vsIndex);
  166.     else
  167.         strncpy (tempName, pName, min(VS_NAME_MAX, (strlen(pName) + 1)));
  168.     /* null-terminate it, just in case... */
  169.     tempName[VS_NAME_MAX] = EOS;
  170.     /* Check that a stack with the same name doesn't already exist */
  171.     for (i = 0; i < VSID_MAX; i++)
  172.         {
  173.         if (vsTbl[i] == NULL)  /* empty slot */
  174.             continue;
  175.         if (strcmp (vsTbl[i]->pName, tempName) == 0)
  176.             {
  177.             semGive (vsTblLock);
  178.             return (ERROR);
  179.             }
  180.         }
  181.     /* Allocate our global structure.  */
  182.     vsTbl[vsIndex] = (BSD_GLOBAL_DATA *) KHEAP_ALLOC ((sizeof(BSD_GLOBAL_DATA)));
  183.     *pVID = vsTbl[vsIndex]; 
  184.     if (vsTbl[vsIndex] == NULL)
  185.         {
  186.         semGive (vsTblLock);
  187.         return (ERROR);
  188.         }
  189.     /* Clear out the structure to NULL */
  190.     bzero ((char *)*pVID, sizeof (BSD_GLOBAL_DATA));
  191.     /* If no name is passed simply make the name the VS number. */
  192.     vsTbl[vsIndex]->pName = (char *)&vsTbl[vsIndex]->name;
  193.     bcopy (tempName, vsTbl[vsIndex]->pName, sizeof(tempName));
  194.     semGive (vsTblLock);
  195.     /*
  196.      * Set the virtual stack number task variable.
  197.      * This allows the initialization code to execute unchanged.
  198.      */
  199.     virtualStackNumTaskIdSet (vsIndex);
  200.     return (OK);
  201.     }
  202. /*******************************************************************************
  203. *
  204. * virtualStackInit - initialize a virtual stack
  205. *
  206. * This routine initializes various data structures within the stack.
  207. * Call this function only after calling virtualStackCreate (). Once
  208. * virtualStackInit () has been executed, network protocols init functions
  209. * can then be called to finish off the virtual stack initialization
  210. * process.
  211. *
  212. * RETURNS: OK, or ERROR if initialization fails.
  213. */
  214. STATUS virtualStackInit
  215.     (
  216.     VSID vsId,   /* Stack identifier from virtualStackCreate() routine */
  217.     int  maxUnits /* maximum number of device to be attached to IP */
  218.     )
  219.     {
  220.     int count;
  221.     int vsIndex;
  222.     if (!vsId)
  223. {
  224. return (ERROR);
  225. }
  226.      /* Verify stack identifier. Exit if not found. */
  227.     if (virtualStackNumGet (vsId, &vsIndex) == ERROR)
  228. return (ERROR);
  229.     /* Set the task variable and initialize the virtual stack. */
  230.     virtualStackNumTaskIdSet (vsIndex);
  231.      /* Allocate the ipDrvCtrl array based on the given maxUnits */
  232.     ipMaxUnits = maxUnits ? maxUnits : 1;
  233.     ipDrvCtrl = (IP_DRV_CTRL *)KHEAP_ALLOC(ipMaxUnits * sizeof(IP_DRV_CTRL));
  234.     if ( ipDrvCtrl == (IP_DRV_CTRL *) NULL )
  235.        return (ERROR);
  236.     bzero ((char *)ipDrvCtrl,ipMaxUnits * sizeof(IP_DRV_CTRL));
  237.     ipDrvCount = 0;
  238.     ipDrvIndex = 0;
  239.     /*
  240.      * Network buffer initialization: Reset pointers to NULL before
  241.      * calling mbinit() routine to force each stack to create separate
  242.      * memory pools.
  243.      */
  244.     mClBlkConfig.memArea = NULL;
  245.     for (count = 0; count < clDescTblNumEnt; count++)
  246.         clDescTbl[count].memArea = NULL;
  247.     sysMclBlkConfig.memArea = NULL;
  248.     for (count = 0; count < sysClDescTblNumEnt; count++)
  249.         sysClDescTbl[count].memArea = NULL;
  250.     pM2IfRoot    = NULL;
  251.     pM2IfRootPtr = &pM2IfRoot;
  252.     /* Make sure that the list is empty on the first call. */
  253.     _ifnet = NULL;
  254.                                        
  255.     /*
  256.      * This code performs the same function as the static initialization
  257.      * in the (no longer compiled) in_proto.c module. Since we don't get
  258.      * auto-initialization from the compiler we have to do the work here.
  259.      */
  260.     
  261.     inetdomain.dom_family = AF_INET;
  262.     inetdomain.dom_name = KHEAP_ALLOC (strlen("internet") + 1);
  263.     strcpy (inetdomain.dom_name, "internet");
  264.     inetdomain.dom_init = 0;
  265.     inetdomain.dom_externalize = 0;
  266.     inetdomain.dom_dispose = 0;
  267.     inetdomain.dom_protosw = inetsw;
  268.     inetdomain.dom_protoswNPROTOSW =
  269.         &inetsw[sizeof(inetsw)/sizeof(inetsw[0])];
  270.     inetdomain.dom_next = NULL;
  271.     inetdomain.dom_rtattach = rn_inithead;
  272.     inetdomain.dom_rtoffset = 27;
  273.     inetdomain.dom_maxrtkey = sizeof(struct sockaddr_in);
  274.     /* Set up for the protocol initialization. */
  275.     bzero ((caddr_t)&inetsw, sizeof(inetsw));
  276.     _protoSwIndex = 0;
  277.     sb_max = SB_MAX;
  278.     /* Set up for domain calls. */
  279.     domains = NULL;
  280.     raw_sendspace = RAWSNDQ;
  281.     raw_recvspace = RAWRCVQ;
  282.     route_proto.sp_family = PF_ROUTE;
  283.     return (OK);
  284.     }
  285. /*******************************************************************************
  286. *
  287. * virtualStackDelete - delete a virtual TCP/IP stack
  288. *
  289. * This routine deletes the virtual stack referenced by the VSID passed to it.
  290. *
  291. * RETURNS: OK or ERROR if the VSID passed to the call was in some way invalid
  292. *
  293. */
  294. STATUS virtualStackDelete
  295.     (
  296.     VSID vsid  /* VID returned by virtualStackCreate */
  297.     )
  298.     {
  299.     int vsIndex;
  300.     
  301.     semTake (vsTblLock, WAIT_FOREVER);
  302.     
  303.     for (vsIndex = 0; vsIndex < VSID_MAX; vsIndex++)
  304.         if (vsTbl[vsIndex] == vsid)
  305.             break; /* Hey, we found it! */
  306.     /* Check that we did find it. */
  307.     if (vsIndex == VSID_MAX)
  308.         {
  309.         semGive (vsTblLock);
  310.         return (ERROR);
  311.         }
  312.     /* Free the structure. */
  313.     KHEAP_FREE (vsTbl[vsIndex]);
  314.     /* Let's be extra paranoid. */
  315.     vsTbl[vsIndex] = NULL;
  316.     
  317.     semGive (vsTblLock);
  318.     return (OK);
  319.     }
  320. /*******************************************************************************
  321. *
  322. * virtualStackIdGet - return the VSID named in pName
  323. *
  324. * This routine returns a VSID in the pointer passed to it in pVSID if a stack
  325. * with pName is found in the Virtual Stack Table.
  326. *
  327. * RETURNS: OK or ERROR if the stack named in pName was not found
  328. *
  329. */
  330. STATUS virtualStackIdGet
  331.     (
  332.     char* pName,  /* Name that was used in virtualStackCreate */
  333.     VSID* pVSID
  334.     )
  335.     {
  336.     int vsIndex;
  337.     semTake (vsTblLock, WAIT_FOREVER);
  338.     
  339.     for (vsIndex = 0; vsIndex < VSID_MAX; vsIndex++)
  340.         if (!strncmp (vsTbl[vsIndex]->pName, pName, 
  341.       min (strlen (pName), VS_NAME_MAX)))
  342.             break; /* Hey, we found it! */
  343.     /* Check that we did find it. */
  344.     if (vsIndex == VSID_MAX)
  345.         {
  346.         semGive(vsTblLock);
  347.         return (ERROR);
  348.         }
  349.     *pVSID = vsTbl[vsIndex];
  350.     semGive (vsTblLock);
  351.     return (OK);
  352.     }
  353. /*******************************************************************************
  354. *
  355. * virtualStackNameGet - return the name given the stack id
  356. *
  357. * This routine returns the stack name in the pointer passed to it in pVSName 
  358. * if a stack with vsid is found in the Virtual Stack Table. This routine
  359. * assumes that the caller has allocated the buffer area for the name.
  360. *
  361. * RETURNS: OK or ERROR if the stack id was not found
  362. *
  363. */
  364. STATUS virtualStackNameGet
  365.     (
  366.     char *    pName,        /* Buffer for the stack name */
  367.     int       vsid
  368.     )
  369.     {
  370.     int vsIndex;
  371.     semTake (vsTblLock, WAIT_FOREVER);
  372.     if ( (vsid < 0) || (vsid > VSID_MAX) )
  373.         return (ERROR);
  374.     strcpy (pName, vsTbl[vsid]->pName);
  375.     semGive (vsTblLock);
  376.     return (OK);
  377.     }
  378. /*******************************************************************************
  379. *
  380. * virtualStackInfo - print out some information about a Virtual Stack
  381. *
  382. * This routine takes the VSID in vsid and prints some information on
  383. * the console about it.
  384. *
  385. * RETURNS: OK or ERROR if the VSID was somehow invalid
  386. *
  387. */
  388. void virtualStackInfo
  389.     (
  390.     VSID vsid
  391.     )
  392.     {
  393.     int vsIndex;
  394.     
  395.     if (vsid == NULL)
  396.         return;
  397.     semTake (vsTblLock, WAIT_FOREVER);
  398.     
  399.     for (vsIndex = 0; vsIndex < VSID_MAX; vsIndex++)
  400.         if (vsTbl[vsIndex] == vsid)
  401.             break; /* Hey, we found it! */
  402.     /* Check that we did find it. */
  403.     if (vsIndex == VSID_MAX)
  404.         {
  405.         semGive(vsTblLock);
  406.         return;
  407.         }
  408.     printf ("Index: %d tName: %sn", vsIndex,
  409.            vsTbl[vsIndex]->pName);
  410.     semGive(vsTblLock);
  411.     }
  412. /*******************************************************************************
  413. *
  414. * virtualStackNumGet - fetches the virtual stack number 
  415. *
  416. * This functions returns a valid stack number in <num> if it returns an OK.
  417. *
  418. * RETURNS: OK --- means that <num> points to a valid stack number;
  419. *    ERROR --- <num> is not valid and/or VSID is invalid;
  420. */
  421. STATUS virtualStackNumGet
  422.     (
  423.     VSID vsid,
  424.     int *num
  425.     )
  426.     {
  427.     
  428.     if ((vsid == NULL) && (num == NULL))
  429.         return (ERROR);
  430.     semTake (vsTblLock, WAIT_FOREVER);
  431.     
  432.     for (*num = 0; (*num < VSID_MAX) && (vsTbl[*num] != vsid); (*num)++);
  433.     semGive(vsTblLock);
  434.     if ( vsTbl[*num] != vsid )
  435. return (ERROR);
  436.     return OK;
  437.     }
  438. /******************************************************************************
  439. *
  440. * virtualStackShow - print out the list of Virtual Stacks
  441. *
  442. * This routine goes through the list of Virtual Stacks and calls
  443. * virtualStackInfo on each.
  444. *
  445. * RETURNS N/A
  446. *
  447. */
  448. void virtualStackShow ()
  449.     {
  450.     int vsIndex;
  451.     
  452.     for (vsIndex = 0; vsIndex < VSID_MAX; vsIndex++)
  453.         virtualStackInfo(vsTbl[vsIndex]);
  454.     }
  455. /*******************************************************************************
  456. *
  457. * virtualStackNameTaskIdSet - set the task variable myTaskNum by name
  458. *
  459. * This routine takes a stack name in pName and will set the task variable
  460. * myTaskNum to the appropriate index.
  461. *
  462. * RETURNS OK or ERROR if the stack named in pName is not found
  463. *
  464. * WARNING
  465. * This routine is NOT to be called in the context of tNetTask.
  466. *
  467. */
  468. STATUS virtualStackNameTaskIdSet
  469.     (
  470.     char* pName /* Name that was used in virtualStackCreate */
  471.     )
  472.     {
  473.     int vsIndex;
  474.     semTake(vsTblLock, WAIT_FOREVER);
  475.     
  476.     for (vsIndex = 0; vsIndex < VSID_MAX; vsIndex++)
  477.         if (!strncmp (vsTbl[vsIndex]->pName, pName, 
  478.       min (strlen (pName), VS_NAME_MAX)))
  479.             break; /* Hey, we found it! */
  480.     semGive (vsTblLock);
  481.     if (vsIndex < VSID_MAX)
  482.         return (virtualStackNumTaskIdSet (vsIndex));
  483.     return (ERROR);
  484.     }
  485. /*******************************************************************************
  486. *
  487. * virtualStackNumTaskIdSet - set the task variable myTaskNum by index
  488. *
  489. * This routine takes a stack index in vsNum and will set the task variable
  490. * myTaskNum to the appropriate index.
  491. *
  492. * RETURNS OK or ERROR if the stack number in vsNum is invalid
  493. *
  494. * WARNING
  495. * This routine is NOT to be called in the context of tNetTask.
  496. *
  497. */
  498. STATUS virtualStackNumTaskIdSet
  499.     (
  500.     int vsNum
  501.     )
  502.     {
  503.     /*
  504.      * If we this task does not have the task variable then
  505.      * create it as part of this task.
  506.      */
  507.     if (taskVarGet(0, (int *) &myStackNum) == ERROR)
  508. {
  509. if (errnoGet () == S_taskLib_TASK_VAR_NOT_FOUND) 
  510.     errnoSet (0); /* Resets the error caused by taskVarGet */
  511.         taskVarAdd (0, (int *) &myStackNum);
  512. }
  513.     if (vsNum > VSID_MAX)
  514.         return (ERROR);
  515.     if (vsTbl[vsNum] == NULL)
  516.         return (ERROR);
  517.     myStackNum = vsNum;
  518.     return (OK);
  519.     }
  520. /*******************************************************************************
  521.  *
  522.  * virtualStackNameSet - Set the stack name, given the stack id
  523.  *
  524.  * This routine sets the name of the stack identified by vsid to the
  525.  * contents of pName. Doing so will overwrite the name provided to this
  526.  * stack when it was created.
  527.  *
  528.  * RETURNS: OK or ERROR is the stack id was not found.
  529.  *
  530.  * This routine is not to be called in the context of tNetTask.
  531.  */
  532. STATUS virtualStackNameSet
  533.     (
  534.     char   *pName,        /* Name to be set */
  535.     int     vsid          /* Stack id */
  536.     )
  537.     {
  538.     semTake (vsTblLock, WAIT_FOREVER);
  539.     if ( (vsid < 0) || (vsid > VSID_MAX) )
  540.         return (ERROR);
  541.     strcpy (vsTbl[vsid]->pName, pName);
  542.     semGive (vsTblLock);
  543.     return (OK);
  544.     }
  545. /*******************************************************************************
  546. *
  547. * virtualStackIdCheck - check to see if myStackNum is set in this task
  548. *
  549. * This routine checks to see if myStackNum is set in this task.  If it is not
  550. * set then it is added to the task's context and set to the VS_MGMT_STACK.
  551. *
  552. * RETURNS OK or ERROR
  553. *
  554. * WARNING
  555. * This routine is not to be called in the context of tNetTask
  556. *
  557. */
  558. STATUS virtualStackIdCheck
  559.     (
  560.     )
  561.     {
  562.     if (taskVarGet(0, (int *)&myStackNum) == ERROR)
  563.         {
  564.         taskVarAdd(0, (int *)&myStackNum);
  565.         myStackNum = VS_MGMT_STACK;
  566.         }
  567.     return (OK);
  568.     }
  569. int numTestTasks;
  570. SEM_ID virtualStackTestSem;
  571. /*******************************************************************************
  572. *
  573. * virtualStackTestDummy - dummy routine called to check the myTaskNum variable
  574. *
  575. * This routine is called by the test harness in this module to test the
  576. * functionality of setting task variables for stack numbers.
  577. *
  578. * NOMANUAL
  579. *
  580. */
  581. void virtualStackTestDummy
  582.     (
  583.     vsNum
  584.     )
  585.     {
  586.     numTestTasks++;
  587.     
  588.     taskDelay (vsNum * sysClkRateGet());
  589.     printf ("Attempting to set myself to Stack %dn", vsNum);
  590.     
  591.     if (virtualStackNumTaskIdSet(vsNum) == ERROR)
  592.         {
  593.         printf ("Task for stack %d failed.n", vsNum);
  594.         return;
  595.         }
  596.     printf ("Task %d has myStackNum of %dn", vsNum, myStackNum);
  597.     printf ("Task %d has stack info of...n", vsNum);
  598.     virtualStackInfo (vsTbl[myStackNum]);
  599.     numTestTasks--;
  600.     
  601.     if (numTestTasks == 0)
  602.         semGive(virtualStackTestSem);
  603.     }
  604. /*******************************************************************************
  605. *
  606. * virtualStackTest - test the virtual stack library
  607. *
  608. * This routine tests the virtual stack library by creating VSID_MAX stacks
  609. * and then calling the virtualStackInfo command on each.  Once this passes
  610. * we spawn VSID_MAX seperate tasks which each attempt to set their myTaskNum
  611. * Task Variable to the stack number they will inhabit (passed as the only
  612. * argument to the test).  When the last task exits it releases a semaphore
  613. * which the test is pending on.  Cleanup is then done.
  614. *
  615. * NOMANUAL
  616. *
  617. */
  618. void virtualStackTest
  619.     (
  620.     )
  621.     {
  622.     int count;
  623.     VSID myStacks[VSID_MAX];
  624.     
  625.     printf ("Starting Virtual Stack Library Test...n");
  626.     for (count = 0; count < VSID_MAX; count++)
  627.         {
  628.         printf ("Creating stack %dn", count);
  629.         myStacks[count] = NULL;
  630.         virtualStackCreate(NULL, &myStacks[count]);
  631.         }
  632.     printf ("Creating complete, checking for failures...n");
  633.     
  634.     for (count = 0; count < VSID_MAX; count++)
  635.         {
  636.         printf ("Checking stack %dn", count);
  637.         if (myStacks[count] == NULL)
  638.             {
  639.             printf ("Stack creation on %d failedn", count);
  640.             goto cleanup;
  641.             }
  642.         }        
  643.     printf ("Stacks 0 through %d created.n", count);
  644.     printf ("Getting stack information...n");
  645.     for (count = 0; count < VSID_MAX; count++)
  646.         {
  647.         virtualStackInfo (myStacks[count]);
  648.         }        
  649.     printf ("Checking task variable madness...n");
  650.     
  651.     virtualStackTestSem = semBCreate (SEM_Q_FIFO, SEM_EMPTY);
  652.     /*
  653.      * Set the number to 0, then let them count them up
  654.      * and down and release the semaphore.
  655.      */
  656.     numTestTasks = 0;
  657.     for (count = 0; count < VSID_MAX; count++)
  658.         {
  659.         taskSpawn (NULL, 255, 0, 20000, (FUNCPTR)virtualStackTestDummy,
  660.                    count, 2, 3, 4, 5, 6, 7 , 8 , 9, 10);
  661.         }        
  662.     /* Wait here for all the sub tasks to end. */
  663.     semTake (virtualStackTestSem, WAIT_FOREVER);
  664.     
  665.     printf ("Done testing...n");
  666.     
  667. cleanup:
  668.     printf ("Cleaning up...n");
  669.     for (count = 0; count < VSID_MAX; count++)
  670.         {
  671.         if (myStacks[count] != NULL)
  672.             virtualStackDelete (myStacks[count]);
  673.         }
  674.     semDelete(virtualStackTestSem);
  675.     }
  676. /***************************************************************************
  677. *
  678. * vsMakeStack - create and initialize a virtual stack
  679. * This function takes a stack name and creates a new virtual stack
  680. * and initializes it.
  681. *
  682. * This function has been replaced by usrVirtualStackCreate () in
  683. * target/config/comps/src/net/usrVirtualStack.c
  684. *
  685. * RETURNS: OK or ERROR
  686. */
  687. STATUS vsMakeStack
  688.     (
  689.     char * vsName,    /* name of the stack */
  690.     int    maxUnits   /* max number of devices attached to IP */
  691.     )
  692.     {
  693.     int oldStackNum = myStackNum;
  694.     VSID vsNum;
  695.     if (vsName == NULL) return ERROR;
  696.     if (virtualStackCreate(vsName, &vsNum) == ERROR)
  697.         return ERROR;
  698.     if (virtualStackInit(vsNum, maxUnits) == ERROR)
  699.         return ERROR;
  700.     myStackNum = oldStackNum;
  701.     return OK;
  702.     }
  703. /***************************************************************************
  704. *
  705. * vsexec - call a function given by a pointer argument, using a specified virtual stack
  706. *
  707. * This function is most useful when calling a function from the (target or wind) 
  708. * shell. It is the only way to specify a stack other than 0 from the windshell.
  709. * When spawning a task, it is a convenient way to let the spawned function for
  710. * a different stack than 0.
  711. * Example: sp vse, 1, rdisc - spawns a new task for rdisc in the context of
  712. * router stack 1.
  713. *
  714. * RETURNS: return status from calling command
  715. */
  716. int vsexec
  717.     (
  718.     int stackNum, /* the stack number to use */
  719.     int (*f)(), /* function to call */
  720.     int   par1, /* parameters to function */
  721.     int   par2,
  722.     int   par3,
  723.     int   par4,
  724.     int   par5,
  725.     int   par6,
  726.     int   par7,
  727.     int   par8,
  728.     int   par9,
  729.     int   par10
  730.     )
  731.     {
  732.     if (0 == f){
  733.      printf("no function givenn");
  734. return -1;
  735.     }
  736.     if (virtualStackNumTaskIdSet(stackNum) == ERROR){
  737.      printf("error setting myStackNumn");
  738. return -1;
  739.     }
  740.     return f(par1, par2, par3, par4, par5, par6, par7, par8, par9, par10);
  741.     }
  742. #endif /* VIRTUAL_STACK */