Azinix

nmTcl.c

Go to the documentation of this file.
00001 /** \file    nmTcl.c
00002 \brief Routines needed to interface with Tcl
00003 */
00004 
00005 
00006 #include "nm.h"
00007 #include "evl.h"
00008 
00009 /*---------------------------------------------------------------------------*/
00010 /* Variable declarations                                                     */
00011 /*---------------------------------------------------------------------------*/
00012 
00013 /**AutomaticStart*************************************************************/
00014 
00015 /*---------------------------------------------------------------------------*/
00016 /* Static function prototypes                                                */
00017 /*---------------------------------------------------------------------------*/
00018 
00019 static void registerTclCommands (Tcl_Interp * interp, Nm_TclCD_t * cd);
00020 static int tclEvlMgrPrintRules (ClientData cd, Tcl_Interp * interp,
00021                    int objc, Tcl_Obj * const objv[]);
00022 static int tclEvlMgrRegisterUcode (ClientData cd, Tcl_Interp * interp,
00023                    int objc, Tcl_Obj * const objv[]);
00024 static int tclEvlRoute (ClientData cd, Tcl_Interp * interp, int objc,
00025             Tcl_Obj * const objv[]);
00026 static int tclEvlBuildManagerFromText (ClientData cd , Tcl_Interp * interp,
00027                        int objc, Tcl_Obj * const objv[]);
00028 static int tclEvlBuildManagerFromFile (ClientData cd , Tcl_Interp * interp,
00029                        int objc, Tcl_Obj * const objv[]);
00030 static int tclStopProfiler (ClientData cd , Tcl_Interp * interp, int objc,
00031                 Tcl_Obj * const objv[]);
00032 static int tclCreatePktFromText (ClientData cd , Tcl_Interp * interp,
00033                  int objc, Tcl_Obj * const objv[]);
00034 static int tclCreatePktArrayFromText (ClientData cd , Tcl_Interp * interp,
00035                       int objc, Tcl_Obj * const objv[]);
00036 static int tclEvlDoTclActions (ClientData cd , Tcl_Interp * interp,
00037                    int objc, Tcl_Obj * const objv[]);
00038 static int tclEvlComputeRuleSetForEth (ClientData cd, Tcl_Interp * interp,
00039                        int objc, Tcl_Obj * const objv[]);
00040 static int tclEvlComputeRuleSetForEthSTRING (ClientData cd ,
00041                          Tcl_Interp * interp, int objc,
00042                          Tcl_Obj * const objv[]);
00043 static char *computeStringFromIpAddress (u_int32_t aNumIp);
00044 static int pktReadIpInfo (ClientData cd , Tcl_Interp * interp, int objc,
00045               Tcl_Obj * const objv[]);
00046 static int pktReadIpFlags (ClientData cd , Tcl_Interp * interp, int objc,
00047                Tcl_Obj * const objv[]);
00048 static int pktReadTcpFlags (ClientData cd , Tcl_Interp * interp, int objc,
00049                 Tcl_Obj * const objv[]);
00050 static int tclTestC (ClientData cd , Tcl_Interp * interp, int objc,
00051              Tcl_Obj * const objv[]);
00052 static int tclTestTk (ClientData cd , Tcl_Interp * interp, int objc,
00053              Tcl_Obj * const objv[]);
00054 // static int tclTestCplusplus (ClientData cd , Tcl_Interp * interp, int objc,
00055 //           Tcl_Obj * const objv[]);
00056 static int tclTestParser (ClientData cd , Tcl_Interp * interp, int objc,
00057               Tcl_Obj * const objv[]);
00058 static int tclGetFileAsText (ClientData cd , Tcl_Interp * interp, int objc,
00059                  Tcl_Obj * const objv[]);
00060 static int tclBufferWritePkts (ClientData cd , Tcl_Interp * interp,
00061                    int objc , Tcl_Obj * const objv[]);
00062 static int tclWritePkts (ClientData cd , Tcl_Interp * interp, int objc ,
00063              Tcl_Obj * const objv[]);
00064 static int tclTxPkt (ClientData cd , Tcl_Interp * interp, int objc ,
00065              Tcl_Obj * const objv[]);
00066 static int tclInjectPkts (ClientData cd , Tcl_Interp * interp,
00067               int objc , Tcl_Obj * const objv[]);
00068 static Pkt_TfcMode_t *readTfcModeParams (Tcl_Interp * interp);
00069 static int tclTestTclAction (ClientData cd , Tcl_Interp * interp,
00070                  int objc , Tcl_Obj * const objv[]);
00071 static int tclStTestPerf (ClientData cd , Tcl_Interp * interp, int objc ,
00072               Tcl_Obj * const objv[]);
00073 static int tclStTest (ClientData cd , Tcl_Interp * interp, int objc ,
00074               Tcl_Obj * const objv[]);
00075 static int tclCompressTestPerf (ClientData cd , Tcl_Interp * interp,
00076                 int objc , Tcl_Obj * const objv[]);
00077 static int tclCompressTestReduction (ClientData cd , Tcl_Interp * interp,
00078                      int objc , Tcl_Obj * const objv[]);
00079 static int tclArrayTest (ClientData cd , Tcl_Interp * interp, int objc ,
00080              Tcl_Obj * const objv[]);
00081 static int tclEvlMgrInsertPktIntoInputBuffer (ClientData cd ,
00082                           Tcl_Interp * interp,
00083                           int objc ,
00084                           Tcl_Obj * const objv[]);
00085 static double computeRate (int size, int numPackets, util_timing_t diffTime);
00086 
00087 /**AutomaticEnd***************************************************************/
00088 
00089 
00090 /**
00091   * \brief Maps tcl values (strings) to C pointers
00092   *
00093   *     This table is needed because tcl operates on strings,
00094   * and when we want to return a pointer, it gets confused.
00095   * So we simply return a string that is the pointer in text
00096   * via sprintf( a, "%p", ptr ). When we need to pointer we
00097   * do a look-up on the passed argument.
00098   *
00099   *
00100   */
00101 
00102 static st_table *tclToC = NIL (st_table);
00103 
00104 
00105 /**
00106   * \brief If we want to use narya with a tcl script,
00107   * we call this function to register the commands exported
00108   *     from C, initialize the tclToC table, and then invoke the
00109   * script.
00110   */
00111 
00112 int
00113 Nm_Tcl (Tcl_Interp * interp, Nm_TclCD_t * cd)
00114 {
00115   registerTclCommands (interp, cd);
00116 
00117   /// \todo Figure out a more meaninful way of having an init file
00118   sourceTclrc (interp);
00119 
00120 /* 
00121 From http://www.cs.ucla.edu/classes/cs217/ns-allinone-2.1b4/tcl-debug-1.9/INSTALL
00122 1) The absolute simplest way is add the following line at some point
00123 in your initialization.  (It always returns TCL_OK.)
00124 
00125     Tcldbg_Init(interp);
00126 
00127 This will add a "debug" command to your interpreter.  (Inside your
00128 application, "debug 1" will start the interpreter.  "debug 0" will
00129 stop it.  When the debugger prompts for a command, type "h" for help.)
00130 
00131 In the same file, add the following directive before the Dbg_On call:
00132 
00133     #include "tcldbg.h"
00134 
00135 Add the libtcldebug.a to your link line.  Re-Make your application.
00136 
00137 Print the document tcl-debug.ps to get the complete instructions on
00138 how to hook the debugger into any Tcl program.  This describes other
00139 options such as invoking the debugger on ^C, as well as the debugger
00140 commands themselves.
00141 
00142 */
00143 
00144   // Tcldbg_Init (interp);
00145 
00146   return TCL_OK;
00147 }
00148 
00149 
00150 /**
00151   * \brief Source an init file called .tclrc.
00152   *
00153   * Look in local directory only.
00154   */
00155 
00156 int
00157 sourceTclrc (Tcl_Interp * interp)
00158 {
00159   return Tcl_EvalFile (interp, ".tclrc");
00160 }
00161 
00162 
00163 /**
00164   * \brief Register all the commands exported to tcl
00165   */
00166 
00167 static void
00168 registerTclCommands (Tcl_Interp * interp, Nm_TclCD_t * cd)
00169 {
00170   tclToC = Hash_InitTable ( ( int(*)() ) strcmp,  ( int(*)() ) st_strhash);
00171   array_t *cmdNames = array_alloc (char *, 0);
00172   array_t *cmdFunctions = array_alloc (Tcl_ObjCmdProc *, 0);
00173 
00174   array_insert_last (char *, cmdNames, "testact");
00175   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, tclTestTclAction);
00176 
00177   array_insert_last (char *, cmdNames, "test_tk");
00178   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, tclTestTk );
00179 
00180   array_insert_last (char *, cmdNames, "testC1");
00181   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, tclTestC );
00182 
00183   array_insert_last (char *, cmdNames, "testC2");
00184   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, tclTestC );
00185 
00186   array_insert_last (char *, cmdNames, "testC3");
00187   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, tclTestC );
00188 
00189   array_insert_last (char *, cmdNames, "testParser");
00190   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, tclTestParser );
00191 
00192   array_insert_last (char *, cmdNames, "getFileAsText");
00193   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, tclGetFileAsText );
00194 
00195   array_insert_last (char *, cmdNames, "evlRoute");
00196   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, tclEvlRoute );
00197 
00198   array_insert_last (char *, cmdNames, "evlBuildManagerFromText");
00199   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions,
00200              tclEvlBuildManagerFromText);
00201 
00202   array_insert_last (char *, cmdNames, "testEvlBuildManagerFromFile");
00203   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions,
00204              tclEvlBuildManagerFromFile);
00205 
00206   array_insert_last (char *, cmdNames, "evlBuildManagerFromFile");
00207   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions,
00208              tclEvlBuildManagerFromFile);
00209 
00210   array_insert_last (char *, cmdNames, "evlComputeRuleSetForEth");
00211   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions,
00212              tclEvlComputeRuleSetForEth);
00213 
00214   array_insert_last (char *, cmdNames, "evlComputeRuleSetForEthSTRING");
00215   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions,
00216              tclEvlComputeRuleSetForEthSTRING);
00217 
00218   array_insert_last (char *, cmdNames, "createPktFromText");
00219   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, tclCreatePktFromText);
00220 
00221   array_insert_last (char *, cmdNames, "createPktArrayFromText");
00222   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions,
00223              tclCreatePktArrayFromText);
00224 
00225   array_insert_last (char *, cmdNames, "evlDoTclActions");
00226   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, tclEvlDoTclActions);
00227 
00228   array_insert_last (char *, cmdNames, "pktReadSrcIp");
00229   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, pktReadIpInfo);
00230 
00231   array_insert_last (char *, cmdNames, "pktReadContent");
00232   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, pktReadIpInfo);
00233 
00234   array_insert_last (char *, cmdNames, "pktReadDestIp");
00235   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, pktReadIpInfo);
00236 
00237   array_insert_last (char *, cmdNames, "pktReadTtl");
00238   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, pktReadIpInfo);
00239 
00240   array_insert_last (char *, cmdNames, "pktReadOffset");
00241   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, pktReadIpInfo);
00242 
00243   array_insert_last (char *, cmdNames, "pktReadLength");
00244   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, pktReadIpInfo);
00245 
00246   array_insert_last (char *, cmdNames, "pktReadIpFlags");
00247   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, pktReadIpFlags);
00248 
00249   array_insert_last (char *, cmdNames, "pktReadTcpDestPort");
00250   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, pktReadTcpInfo);
00251 
00252   array_insert_last (char *, cmdNames, "pktReadTcpSrcPort");
00253   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, pktReadTcpInfo);
00254 
00255   array_insert_last (char *, cmdNames, "pktReadTcpSeqNum");
00256   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, pktReadTcpInfo);
00257 
00258   array_insert_last (char *, cmdNames, "pktReadTcpAckNum");
00259   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, pktReadTcpInfo);
00260 
00261   array_insert_last (char *, cmdNames, "pktReadTcpFlags");
00262   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, pktReadTcpFlags);
00263 
00264   array_insert_last (char *, cmdNames, "checkHardware");
00265   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, Perf_CheckHardware);
00266 
00267   array_insert_last (char *, cmdNames, "timePerf");
00268   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, Perf_TimePerf);
00269 
00270   array_insert_last (char *, cmdNames, "timePerf2");
00271   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, Perf_TimePerf2);
00272 
00273   array_insert_last (char *, cmdNames, "spacePerf");
00274   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, Perf_SpacePerf);
00275 
00276   array_insert_last (char *, cmdNames, "injectPkts");
00277   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, tclInjectPkts);
00278 
00279   array_insert_last (char *, cmdNames, "txPkt");
00280   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, tclTxPkt);
00281 
00282   array_insert_last (char *, cmdNames, "writePkts");
00283   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, tclWritePkts);
00284 
00285   array_insert_last (char *, cmdNames, "bufferWritePkts");
00286   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, tclBufferWritePkts);
00287 
00288   array_insert_last (char *, cmdNames, "timingCheck");
00289   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, Perf_CheckTimingCode);
00290 
00291   array_insert_last (char *, cmdNames, "compTestPerf");
00292   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, tclCompressTestPerf);
00293 
00294   array_insert_last (char *, cmdNames, "compTestReduction");
00295   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions,
00296              tclCompressTestReduction);
00297 
00298   array_insert_last (char *, cmdNames, "evlMgrRegisterUcode");
00299   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, tclEvlMgrRegisterUcode);
00300 
00301   // alias evlMgrRegisterUcode to register_c-ext 
00302   array_insert_last (char *, cmdNames, "register_c-ext");
00303   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, tclEvlMgrRegisterUcode);
00304 
00305   array_insert_last (char *, cmdNames, "evlMgrPrintRules");
00306   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, tclEvlMgrPrintRules);
00307 
00308   array_insert_last (char *, cmdNames, "evlMgrInsertPktIntoInputBuffer");
00309   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions,
00310              tclEvlMgrInsertPktIntoInputBuffer);
00311 
00312   array_insert_last (char *, cmdNames, "array_test");
00313   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, tclArrayTest);
00314 
00315   array_insert_last (char *, cmdNames, "st_test_perf");
00316   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, tclStTestPerf);
00317 
00318   array_insert_last (char *, cmdNames, "st_test");
00319   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, tclStTest);
00320 
00321   array_insert_last (char *, cmdNames, "stop_profiler");
00322   array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, tclStopProfiler);
00323 
00324   // array_insert_last (char *, cmdNames, "test_cpp");
00325   // array_insert_last (Tcl_ObjCmdProc *, cmdFunctions, tclTestCplusplus);
00326 
00327   int i;
00328   for (i = 0; i < array_n (cmdNames); i++)
00329     {
00330       char *cmdName = array_fetch (char *, cmdNames, i);
00331       Tcl_ObjCmdProc *cmdFunc =
00332     array_fetch (Tcl_ObjCmdProc *, cmdFunctions, i);
00333       Tcl_CreateObjCommand (interp, cmdName, cmdFunc, cd,
00334                 NIL (Tcl_CmdDeleteProc));
00335     }
00336 }
00337 
00338 
00339 /**
00340   *     \brief Print rules associated with manager
00341   *
00342   */
00343 
00344 static int
00345 tclEvlMgrPrintRules (ClientData cd,
00346             Tcl_Interp * interp,
00347             int objc, Tcl_Obj * const objv[])
00348 {
00349   assert (objc == 2);
00350 
00351   Evl_Manager_t *mgr =
00352     (Evl_Manager_t *) Nm_TclCDReadPtrFromObj (interp, (Nm_TclCD_t *) cd, objv[1]);
00353 
00354   int i;
00355   for ( i = 0 ; i < mgr->numAllRules; i++ ) {
00356     char *aRule = array_fetch( char *, mgr->rawRules, i );
00357     printf("Rule %d: %s\n", i, aRule );
00358   }
00359   return TCL_OK;
00360 
00361 }
00362 
00363 /**
00364   *     \brief Register a new function with given name
00365   *
00366   * Command is evlMgrRegisterUcode $mgr "functionName" "/home/adnan/pathToLib"
00367   */
00368 
00369 static int
00370 tclEvlMgrRegisterUcode (ClientData cd,
00371             Tcl_Interp * interp,
00372             int objc, Tcl_Obj * const objv[])
00373 {
00374   assert (objc == 4);
00375 
00376   Evl_Manager_t *mgr =
00377     (Evl_Manager_t *) Nm_TclCDReadPtrFromObj (interp, (Nm_TclCD_t *) cd, objv[1]);
00378   char *ucodeName = strdup (objv[2]->bytes);
00379   char *ucodeLibrary = strdup (objv[3]->bytes);
00380 
00381   Os_DynamicallyLinkFunction (mgr->ucodeNameToFunction, ucodeName,
00382                   ucodeLibrary);
00383 
00384   return TCL_OK;
00385 
00386 }
00387 
00388 
00389 /**
00390   *     \brief Tcl code that checks performance of Narya on synthetic traffic.
00391   */
00392 
00393 static int
00394 tclEvlRoute (ClientData cd,
00395          Tcl_Interp * interp, int objc, Tcl_Obj * const objv[])
00396 {
00397   int iBufSize = 2;
00398   Nm_TclGetIntVar (interp, "iBufSize", &iBufSize);
00399 
00400   int ppCacheSize = 2;
00401   Nm_TclGetIntVar (interp, "ppCacheSize", &ppCacheSize);
00402 
00403   int oBufSize = 2;
00404   Nm_TclGetIntVar (interp, "oBufSize", &oBufSize);
00405 
00406   int actionBufSize = 2;
00407   Nm_TclGetIntVar (interp, "actionBufSize", &actionBufSize);
00408 
00409   int numIterations = 1;
00410   Nm_TclGetIntVar (interp, "numIterations", &numIterations);
00411 
00412   int maxNumPktsToRead = 1;
00413   Nm_TclGetIntVar (interp, "maxNumPktsToRead", &maxNumPktsToRead);
00414 
00415   char *basicSliceString = "0.001";
00416   Nm_TclGetStringVar (interp, "basicSlice", &basicSliceString);
00417   double basicSlice;
00418   sscanf (basicSliceString, "%lf", &basicSlice);
00419 
00420   int getPacketsWeight = 1;
00421   Nm_TclGetIntVar (interp, "getPacketsWeight", &getPacketsWeight);
00422 
00423   int computeActionsWeight = 1;
00424   Nm_TclGetIntVar (interp, "computeActionsWeight", &computeActionsWeight);
00425 
00426   int performActionsWeight = 1;
00427   Nm_TclGetIntVar (interp, "performActionsWeight", &performActionsWeight);
00428 
00429   int queuingWeight = 1;
00430   Nm_TclGetIntVar (interp, "queuingWeight", &queuingWeight);
00431 
00432   int writePacketsWeight = 1;
00433   Nm_TclGetIntVar (interp, "writePacketWeight", &writePacketsWeight);
00434 
00435   int recordPktsWritten = 0;
00436   Nm_TclGetIntVar (interp, "recordPktsWritten", &recordPktsWritten);
00437 
00438   int recordStats = 0;
00439   Nm_TclGetIntVar (interp, "recordStats", &recordStats);
00440   Evl_BridgeStats_t *stats;
00441   Evl_BridgeStats_t **statsPtr = NIL (Evl_BridgeStats_t *);
00442   if (recordStats)
00443     {
00444       statsPtr = &stats;
00445     }
00446 
00447   assert (objc >= 2);       // pktArray is optional, used only in synthetic mode
00448 
00449   Evl_Manager_t *mgr =
00450     (Evl_Manager_t *) Nm_TclCDReadPtrFromObj (interp, (Nm_TclCD_t *) cd, objv[1]);
00451   array_t *pktArray = NIL (array_t);
00452   int useSynthetic = 0;
00453   array_t *ackSeqNumArray = NIL (array_t);
00454   if (objc == 3)
00455     {
00456       // two arguments -> must be synthetic case
00457       pktArray = (array_t *) Nm_TclCDReadPtrFromObj (interp, (Nm_TclCD_t *) cd, objv[2]);
00458       useSynthetic = 1;
00459       if (recordPktsWritten)
00460     {
00461       ackSeqNumArray = array_alloc (Pkt_EthernetHdr_t *, 0);
00462     }
00463     }
00464 
00465   array_t *inArray = array_alloc (char *, 0);
00466   array_t *outArray = array_alloc (char *, 0);
00467   if (!useSynthetic)
00468     {
00469       Nm_TclGetArrayVar (interp, "ineth", inArray);
00470       Nm_TclGetArrayVar (interp, "outeth", outArray);
00471     }
00472 
00473 
00474   Evl_Route (mgr, pktArray, iBufSize, ppCacheSize, oBufSize,
00475          actionBufSize, maxNumPktsToRead,
00476          numIterations, useSynthetic, inArray, outArray,
00477          basicSlice, getPacketsWeight, computeActionsWeight,
00478          performActionsWeight, queuingWeight, writePacketsWeight,
00479          ackSeqNumArray, statsPtr);
00480 
00481   Tcl_Obj *resultObj = Tcl_NewStringObj ("", -1);
00482   if (statsPtr != NIL (Evl_BridgeStats_t *))
00483     {
00484       char statsString[1000];
00485       sprintf (statsString,
00486            "Start time\t\t= %f\n"
00487            "Finish time\t\t= %f\n"
00488            "Num entered\t\t= %d\n"
00489            "Num exited\t\t= %d\n"
00490            "Bytes written\t\t= %d\n"
00491            "Num Drop: FullRuleCacheArray\t= %d\n"
00492            "Num Drop: FullActionBuf\t\t= %d\n"
00493            "Num Drop: FullObuf\t\t= %d\n"
00494            "Num Drop: FullQueue\t\t= %d\n"
00495            "Num Drop: Action\t\t= %d\n"
00496            "Num Drop: OverRate\t\t= %d\n"
00497            "Num Drop: OverFlowRate\t\t= %d\n",
00498            util_timing_secs (stats->startTime),
00499            util_timing_secs (stats->finishTime),
00500            stats->numEntered,
00501            stats->numExited,
00502            stats->bytesWritten,
00503            stats->numDroppedFullRuleCacheArray,
00504            stats->numDroppedFullActionBuf,
00505            stats->numDroppedFullObuf,
00506            stats->numDroppedFullQueue,
00507            stats->numDroppedBecauseOfAction,
00508            stats->numDroppedOverRate, stats->numDroppedOverFlowRate);
00509       // printf("all stats:\n%s\n", statsString );
00510       char rateString[100];
00511       double delta =
00512     util_timing_secs (stats->lastPktWritten) -
00513     util_timing_secs (stats->firstPktRead);
00514       double rate = (8.0 * (double) stats->bytesWritten) / delta;
00515       sprintf (rateString, "%.1f", rate);
00516       char *memEffResult = strdup (rateString);
00517       Tcl_SetStringObj (resultObj, memEffResult, -1);
00518     }
00519   else if (ackSeqNumArray != NIL (array_t))
00520     {
00521       // estimate 10 bytes for each int id plus bytes for space
00522       char *seqTxt = (char *) malloc (1 + (array_n (ackSeqNumArray)) * 12);
00523       seqTxt[0] = '\0';     // in case there are no applicable rules
00524       char *tmp = seqTxt;
00525       int i;
00526       for (i = 0; i < array_n (ackSeqNumArray); i++)
00527     {
00528       Pkt_EthernetHdr_t *aPkt =
00529         array_fetch (Pkt_EthernetHdr_t *, ackSeqNumArray, i);
00530       if (Pkt_EthernetReadL3Type (aPkt) != Pkt_L3ProtIp_c)
00531         {
00532           // need this because we may be creating a compressed packet, which isnt ip
00533           continue;
00534         }
00535       Pkt_TcpHdr_t *aTcpPkt = Pkt_EthernetExtractTcp (aPkt);
00536       sprintf (tmp, "%d%s",
00537            aTcpPkt->ackNum,
00538            ((i == (array_n (ackSeqNumArray) - 1)) ? "" : ","));
00539       tmp += strlen (tmp);
00540     }
00541       array_free (ackSeqNumArray);
00542       char *memEffResult = strdup (seqTxt);
00543       free (seqTxt);
00544       Tcl_SetStringObj (resultObj, memEffResult, -1);
00545     }
00546   else
00547     {
00548       Tcl_SetStringObj (resultObj, "", -1);
00549     }
00550   Tcl_SetObjResult (interp, resultObj);
00551 
00552   return TCL_OK;
00553 }
00554 
00555 
00556 /**
00557   * \brief Tcl code that builds a manager from a set of rules described in text
00558   */
00559 
00560 static int
00561 tclEvlBuildManagerFromText (ClientData cd ,
00562                 Tcl_Interp * interp,
00563                 int objc, Tcl_Obj * const objv[])
00564 {
00565   assert (objc == 2);
00566 
00567   char *mgrText = Tcl_GetStringFromObj (objv[1], NIL (int));
00568   Evl_Manager_t *result = Evl_BuildManager (mgrText, interp, cd);
00569 
00570   Nm_TclResult (interp, (Nm_TclCD_t *) cd, result);
00571 
00572   return TCL_OK;
00573 }
00574 
00575 
00576 /**
00577   * \brief Tcl code that builds a manager from a set of rules described in a file
00578   */
00579 
00580 static int
00581 tclEvlBuildManagerFromFile (ClientData cd ,
00582                 Tcl_Interp * interp,
00583                 int objc, Tcl_Obj * const objv[])
00584 {
00585   assert (objc == 2);
00586 
00587   char *fileName = Tcl_GetStringFromObj (objv[1], NIL (int));
00588   FILE *ruleFile = fopen (fileName, "r");
00589   if (ruleFile == NIL (FILE))
00590     {
00591       printf
00592     ("Error, could not open file %s, returning without building manager from file\n",
00593      fileName);
00594       return TCL_OK;
00595     }
00596   char *ruleFileInText = util_file_to_string (ruleFile);
00597   fclose (ruleFile);
00598 
00599   Evl_Manager_t *result = Evl_BuildManager (ruleFileInText, interp, cd);
00600 
00601   char *cmdName = Tcl_GetStringFromObj (objv[0], NIL (int));
00602   if (util_strequal (cmdName, "evlBuildManagerFromFile"))
00603     {
00604       Nm_TclResult (interp, cd, result);
00605     }
00606   else
00607     {
00608       assert (util_strequal (cmdName, "testEvlBuildManagerFromFile"));
00609       Tcl_Obj *resultObj = Tcl_GetObjResult (interp);
00610       Tcl_SetIntObj (resultObj, 0);
00611     }
00612 
00613   return TCL_OK;
00614 }
00615 
00616 
00617 /**
00618   * \brief Code to take a raw pointer and set it as the result of a tcl command
00619   */
00620 
00621 void
00622 Nm_TclResult (Tcl_Interp * interp, ClientData cd, void *ptr)
00623 {
00624   int resultId = Nm_TclCDStorePtr ((Nm_TclCD_t *) cd, ptr);
00625   Tcl_Obj *resultObj = Tcl_GetObjResult (interp);
00626   Tcl_SetIntObj (resultObj, resultId);
00627 }
00628 
00629 
00630 /**
00631   * \brief Build a packet from the given text string
00632   */
00633 
00634 static int
00635 tclCreatePktFromText (ClientData cd ,
00636               Tcl_Interp * interp, int objc, Tcl_Obj * const objv[])
00637 {
00638   assert (objc == 2);
00639   char *pktText = Tcl_GetStringFromObj (objv[1], NIL (int));
00640   Pkt_EthernetHdr_t *result = Pkt_CreatePktFromString (pktText);
00641 
00642   Nm_TclResult (interp, (Nm_TclCD_t *) cd, (void *) result);
00643 
00644   return TCL_OK;
00645 }
00646 
00647 
00648 /**
00649   * \brief Build a packet from the given text string
00650   */
00651 
00652 static int
00653 tclCreatePktArrayFromText (ClientData cd ,
00654                Tcl_Interp * interp,
00655                int objc, Tcl_Obj * const objv[])
00656 {
00657   assert (objc == 2);
00658 
00659   array_t *result = array_alloc (Pkt_EthernetHdr_t *, 0);
00660 
00661   int numPkts;
00662   Tcl_Obj **objArray;
00663   Tcl_ListObjGetElements (interp, objv[1], &numPkts, &objArray);
00664 
00665   int i;
00666   for (i = 0; i < numPkts; i++)
00667     {
00668       Tcl_Obj *pktObj;
00669       int code  = Tcl_ListObjIndex (interp, objv[1], i, &pktObj);
00670       char *pktText = Tcl_GetStringFromObj (pktObj, NIL (int));
00671       Pkt_EthernetHdr_t *pkt = Pkt_CreatePktFromString (pktText);
00672       array_insert_last (Pkt_EthernetHdr_t *, result, pkt);
00673     }
00674 
00675   Nm_TclResult (interp, (Nm_TclCD_t *) cd, (void *) result);
00676 
00677   return TCL_OK;
00678 }
00679 
00680 
00681 /**
00682   * \brief Perform tcl actions on a given packet - pass in
00683   *     a manager and an array of rules.
00684   */
00685 
00686 static int
00687 tclEvlDoTclActions (ClientData cd ,
00688             Tcl_Interp * interp, int objc, Tcl_Obj * const objv[])
00689 {
00690   assert (objc == 4);
00691 
00692   Evl_Manager_t *mgr =
00693     (Evl_Manager_t *) Nm_TclCDReadPtrFromObj (interp, (Nm_TclCD_t *) cd, objv[1]);
00694   array_t *applicableRules =
00695     (array_t *) Nm_TclCDReadPtrFromObj (interp, (Nm_TclCD_t *) cd, objv[2]);
00696   Pkt_EthernetHdr_t *pkt =
00697     (Pkt_EthernetHdr_t *) Nm_TclCDReadPtrFromObj (interp, (Nm_TclCD_t *) cd, objv[3]);
00698 
00699   Tcl_Obj *listPtr = Tcl_NewListObj (0, (Tcl_Obj **) NULL);
00700 
00701   char *tmp = (char *) malloc (2048 * mgr->numAllRules);    // AA: need better estimate
00702   tmp[0] = '\0';
00703   int i;
00704   for (i = 0; i < array_n (applicableRules); i++)
00705     {
00706       int ruleId = array_fetch (int, applicableRules, i);
00707       Rlp_Action_t *action =
00708     array_fetch (Rlp_Action_t *, mgr->actionArray, ruleId);
00709       if (action->type != Rlp_ActionUscript_c)
00710     {
00711       continue;
00712     }
00713       char *tclRuleString = action->uscript;
00714       sprintf (tmp, "%s", tclRuleString);
00715       Tcl_Obj *tmpObjv[2];
00716       Tcl_Obj *tmpPtr = Tcl_NewStringObj (strdup (tmp), -1);
00717       tmpObjv[0] = tmpPtr;
00718       int resultId = Nm_TclCDStorePtr ((Nm_TclCD_t *) cd, pkt);
00719       tmpObjv[1] = Tcl_NewIntObj (resultId);
00720       Tcl_EvalObjv (interp, 2, tmpObjv, 0);
00721       Tcl_ListObjAppendElement (interp, listPtr, tmpPtr);
00722     }
00723   array_free (applicableRules);
00724 
00725   Tcl_SetObjResult (interp, listPtr);
00726 
00727   return TCL_OK;
00728 }
00729 
00730 
00731 /**
00732   * \brief Compute rules applicable to a given packet.
00733   *
00734   * Pass in a manager and a pkt, get back an id to an array of integers, indexing
00735   * the manager rules that were applicable.
00736   */
00737 
00738 static int
00739 tclEvlComputeRuleSetForEth (ClientData cd,
00740                 Tcl_Interp * interp,
00741                 int objc, Tcl_Obj * const objv[])
00742 {
00743   assert (objc == 3);
00744 
00745   Evl_Manager_t *mgr =
00746     (Evl_Manager_t *) Nm_TclCDReadPtrFromObj (interp, (Nm_TclCD_t *) cd, objv[1]);
00747   Pkt_EthernetHdr_t *pkt =
00748     (Pkt_EthernetHdr_t *) Nm_TclCDReadPtrFromObj (interp, (Nm_TclCD_t *) cd, objv[2]);
00749   array_t *applicableRules = array_alloc (int, 0);
00750   Pkt_ProcessPkt_t pp;
00751   pp.pkt = pkt;
00752   pp.applicableRules = applicableRules;
00753   Evl_ComputeRuleSetForEth (&pp, mgr);
00754 
00755   array_t *result = array_dup (applicableRules);
00756   Nm_TclResult (interp, (Nm_TclCD_t *) cd, (void *) result);
00757 
00758   return TCL_OK;
00759 }
00760 
00761 
00762 /**
00763   * \brief Compute rules applicable to a given packet 
00764   *
00765   * Pass in a manager and a pkt, get back a string of integers, indexing
00766   * the manager rules that were applicable.
00767   */
00768 
00769 static int
00770 tclEvlComputeRuleSetForEthSTRING (ClientData cd ,
00771                   Tcl_Interp * interp,
00772                   int objc, Tcl_Obj * const objv[])
00773 {
00774   assert (objc == 3);
00775 
00776   Evl_Manager_t *mgr =
00777     (Evl_Manager_t *) Nm_TclCDReadPtrFromObj (interp, (Nm_TclCD_t *) cd, objv[1]);
00778   Pkt_EthernetHdr_t *pkt =
00779     (Pkt_EthernetHdr_t *) Nm_TclCDReadPtrFromObj (interp, (Nm_TclCD_t *) cd, objv[2]);
00780 
00781   array_t *applicableRules = array_alloc (int, 0);
00782   Pkt_ProcessPkt_t pp;
00783   pp.pkt = pkt;
00784   pp.applicableRules = applicableRules;
00785   pp.inIf = NIL (Pkt_LibPcap_t);
00786   Evl_ComputeRuleSetForEth (&pp, mgr);
00787 
00788   char *result = (char *) malloc (mgr->numAllRules * 12);   // estimate 10 bytes for each int id plus bytes for space
00789   result[0] = '\0';     // in case there are no applicable rules
00790   char *tmp = result;
00791   int i;
00792   for (i = 0; i < array_n (applicableRules); i++)
00793     {
00794       int ruleid = array_fetch (int, applicableRules, i);
00795       sprintf (tmp, "%d%s", ruleid,
00796            ((i == (array_n (applicableRules) - 1)) ? "" : ","));
00797       tmp += strlen (tmp);
00798     }
00799   array_free (applicableRules);
00800   char *memEffResult = strdup (result);
00801   free (result);
00802 
00803   Tcl_Obj *resultObj = Tcl_GetObjResult (interp);
00804   Tcl_SetStringObj (resultObj, memEffResult, -1);
00805 
00806   return TCL_OK;
00807 }
00808 
00809 
00810 /**
00811   * \brief Code encapsulating getting a string var from Tcl environment
00812   */
00813 
00814 int
00815 Nm_TclGetStringVar (Tcl_Interp * interp, char *tclVarName, char **result)
00816 {
00817   const char *tmp = Tcl_GetVar (interp, tclVarName, 0);
00818   if (tmp != NIL (char))
00819     {
00820       *result = strdup (tmp);
00821       return true;
00822     }
00823   return false;
00824 }
00825 
00826 
00827 /**
00828   * \brief Code encapsulating getting a double var from Tcl environment
00829   */
00830 
00831 int
00832 Nm_TclGetDoubleVar (Tcl_Interp * interp, char *tclVarName, double *result)
00833 {
00834   const char *tmp = Tcl_GetVar (interp, tclVarName, 0);
00835   double tmpDouble;
00836   if (tmp != NIL (char))
00837     {
00838       sscanf (tmp, "%lf", &tmpDouble);
00839       *result = tmpDouble;
00840       return true;
00841     }
00842   return false;
00843 }
00844 
00845 
00846 /**
00847   * \brief Code encapsulating getting an array var from Tcl environment
00848   */
00849 
00850 int
00851 Nm_TclGetArrayVar (Tcl_Interp * interp, char *tclVarName, array_t * result)
00852 {
00853   const char *tmp = Tcl_GetVar (interp, tclVarName, 0);
00854   int listArgc;
00855   const char **listArgv;
00856   if (Tcl_SplitList (interp, tmp, &listArgc, &listArgv) != TCL_OK)
00857     {
00858       return false;
00859     }
00860   int i;
00861   for (i = 0; i < listArgc; i++)
00862     {
00863       printf ("%s\n", listArgv[i]);
00864       char *dupName = strdup (listArgv[i]);
00865       array_insert_last (char *, result, dupName);
00866     }
00867   return true;
00868 
00869 }
00870 
00871 
00872 /**
00873   * \brief Code encapsulating getting an int var from Tcl environment
00874   */
00875 
00876 int
00877 Nm_TclGetIntVar (Tcl_Interp * interp, char *tclVarName, int *result)
00878 {
00879   const char *tmp = Tcl_GetVar (interp, tclVarName, 0);
00880   if (tmp != NIL (char))
00881     {
00882       *result = atoi (tmp);
00883       return true;
00884     }
00885   return false;
00886 }
00887 
00888 
00889 /**
00890   * \brief Allocate a client data structure
00891   */
00892 
00893 Nm_TclCD_t *
00894 Nm_TclCDInit ()
00895 {
00896   Nm_TclCD_t *result = (Nm_TclCD_t *) malloc (sizeof (Nm_TclCD_t));
00897   result->idToPtr = array_alloc (char *, 0);
00898   result->freeIds = array_alloc (int, 0);
00899 
00900   return result;
00901 }
00902 
00903 
00904 /**
00905   * \brief Store a pointer in the CD structure.  Return the
00906   * int id of this pointer.
00907   */
00908 
00909 int
00910 Nm_TclCDStorePtr (Nm_TclCD_t * cd, void *ptr)
00911 {
00912   int result;
00913   int index;
00914 
00915   if (array_n (cd->freeIds) == 0)
00916     {
00917       result = array_n (cd->idToPtr) + Nm_TclNumRetCodes_c;
00918       array_insert_last (void *, cd->idToPtr, ptr);
00919     }
00920   else
00921     {
00922       index = array_delete_last (int, cd->freeIds);
00923       array_insert (void *, cd->idToPtr, index, ptr);
00924       result = index + Nm_TclNumRetCodes_c;
00925     }
00926   return result;
00927 }
00928 
00929 
00930 /**
00931   * \brief Read a pointer from the CD structure from obj argument.
00932   */
00933 
00934 void *
00935 Nm_TclCDReadPtrFromObj (Tcl_Interp * interp,
00936             Nm_TclCD_t * cd, Tcl_Obj * const obj)
00937 {
00938   int id;
00939   assert (TCL_OK == Tcl_GetIntFromObj (interp, obj, &id));
00940   return Nm_TclCDReadPtr (cd, id);
00941 }
00942 
00943 
00944 /**
00945   * \brief Read a pointer from the CD structure.
00946   */
00947 
00948 void *
00949 Nm_TclCDReadPtr (Nm_TclCD_t * cd, int id)
00950 {
00951   int index = id - Nm_TclNumRetCodes_c;
00952   void *result = array_fetch (void *, cd->idToPtr, index);
00953   return result;
00954 }
00955 
00956 
00957 /**
00958   * \brief Return an id to the pool of available ids
00959   */
00960 
00961 void
00962 Nm_TclCDReuseId (Nm_TclCD_t * cd, int id)
00963 {
00964   int index = id - Nm_TclNumRetCodes_c;
00965   array_insert_last (int, cd->freeIds, index);
00966 }
00967 
00968 
00969 /**
00970   * \brief Compute the string equivalent of an ip address
00971   */
00972 
00973 static char *
00974 computeStringFromIpAddress (u_int32_t aNumIp)
00975 {
00976   char tmpbuf[40];
00977 
00978   u_int32_t mask = 0377;    // start with 0 means octal
00979 
00980   u_int32_t a1;
00981   u_int32_t a2;
00982   u_int32_t a3;
00983   u_int32_t a4;
00984 
00985   a1 = aNumIp & mask;
00986   a2 = (aNumIp >> 8) & mask;
00987   a3 = (aNumIp >> 16) & mask;
00988   a4 = (aNumIp >> 24) & mask;
00989   sprintf (tmpbuf, "%u.%u.%u.%u", a4, a3, a2, a1);
00990 
00991   return strdup (tmpbuf);
00992 }
00993 
00994 
00995 /**
00996   * \brief Get a tcl string for various numerical values in the ip pkt
00997   */
00998 
00999 static int
01000 pktReadIpInfo (ClientData cd ,
01001            Tcl_Interp * interp, int objc, Tcl_Obj * const objv[])
01002 {
01003   assert (objc == 2);
01004 
01005   Pkt_EthernetHdr_t *pkt =
01006     (Pkt_EthernetHdr_t *) Nm_TclCDReadPtrFromObj (interp, (Nm_TclCD_t *) cd, objv[1]);
01007   Pkt_IpHdr_t *ipPkt = Pkt_EthernetExtractIp (pkt);
01008   u_int32_t result;
01009   u_int16_t length;
01010   char tmpbuf[2000];
01011   char *cmdName = Tcl_GetStringFromObj (objv[0], NIL (int));
01012   int computeIpAddressFlag = false;
01013   int getContent = false;
01014   char *resultString;
01015 
01016   if (util_strequal (cmdName, "pktReadSrcIp"))
01017     {
01018       result = ipPkt->sourceIp;
01019       computeIpAddressFlag = true;
01020     }
01021   else if (util_strequal (cmdName, "pktReadDestIp"))
01022     {
01023       result = ipPkt->destIp;
01024       computeIpAddressFlag = true;
01025     }
01026   else if (util_strequal (cmdName, "pktReadOffset"))
01027     {
01028       result = ipPkt->offset;
01029       assert (result < 65536);
01030     }
01031   else if (util_strequal (cmdName, "pktReadTtl"))
01032     {
01033       result = ipPkt->TTL;
01034       assert (result < 256);
01035     }
01036   else if (util_strequal (cmdName, "pktReadLength"))
01037     {
01038       result = ipPkt->length;
01039       assert (result < 65526);
01040     }
01041   else if (util_strequal (cmdName, "pktReadContent"))
01042     {
01043       getContent = true;
01044       // length = ntohs( ipPkt->length );
01045       length = ipPkt->length;
01046       assert (length < 65526);
01047       resultString = (char *) malloc (length + 1);
01048       memcpy (resultString, ipPkt, length);
01049       unsigned int i;
01050       for (i = 0; i < length; i++)
01051     {
01052       if (!isprint (resultString[i]))
01053         {
01054           resultString[i] = '.';
01055         }
01056     }
01057       resultString[length] = '\0';
01058     }
01059   else
01060     {
01061       assert (0);
01062     }
01063 
01064   if (!(getContent))
01065     {
01066       if (!computeIpAddressFlag)
01067     {
01068       sprintf (tmpbuf, "%u", result);
01069       resultString = strdup (tmpbuf);
01070     }
01071       else
01072     {
01073       resultString = computeStringFromIpAddress (result);
01074     }
01075     }
01076 
01077   Tcl_Obj *resultObj = Tcl_GetObjResult (interp);
01078   Tcl_SetStringObj (resultObj, resultString, -1);
01079 
01080   return TCL_OK;
01081 }
01082 
01083 
01084 /**
01085   * \brief Get tcl string representation of the packet ipflags
01086   */
01087 
01088 static int
01089 pktReadIpFlags (ClientData cd ,
01090         Tcl_Interp * interp, int objc, Tcl_Obj * const objv[])
01091 {
01092   assert (objc == 2);
01093 
01094   Pkt_EthernetHdr_t *pkt =
01095     (Pkt_EthernetHdr_t *) Nm_TclCDReadPtrFromObj (interp, (Nm_TclCD_t *) cd, objv[1]);
01096   Pkt_IpHdr_t *ipPkt  = Pkt_EthernetExtractIp (pkt);
01097   char tmpbuf[64];
01098 
01099   // u_int16_t  RB:1,
01100   //            DF:1,
01101   //            MF:1,
01102   //            offset:13;
01103   sprintf (tmpbuf, "RB:%d; DF:%d; MF:%d; offset:%d;", ipPkt->RB, ipPkt->DF,
01104        ipPkt->MF, ipPkt->offset);
01105 
01106   char *resultString = strdup (tmpbuf);
01107   Tcl_Obj *resultObj = Tcl_GetObjResult (interp);
01108   Tcl_SetStringObj (resultObj, resultString, -1);
01109 
01110   return TCL_OK;
01111 }
01112 
01113 
01114 /**
01115   * \brief Return information in tcl string form for the tcp packet
01116   */
01117 
01118 int
01119 pktReadTcpInfo (ClientData cd ,
01120         Tcl_Interp * interp, int objc, Tcl_Obj * const objv[])
01121 {
01122   assert (objc == 2);
01123   char *cmdName = Tcl_GetStringFromObj (objv[0], NIL (int));
01124 
01125   Pkt_EthernetHdr_t *pkt =
01126     (Pkt_EthernetHdr_t *) Nm_TclCDReadPtrFromObj (interp, (Nm_TclCD_t *) cd, objv[1]);
01127   Pkt_TcpHdr_t *tcpPkt = Pkt_EthernetExtractTcp (pkt);
01128   u_int32_t result;
01129 
01130   if (util_strequal (cmdName, "pktReadTcpDestPort"))
01131     {
01132       result = tcpPkt->destPort;
01133       assert (result < 65536);
01134     }
01135   else if (util_strequal (cmdName, "pktReadTcpSrcPort"))
01136     {
01137       result = tcpPkt->srcPort;
01138       assert (result < 65536);
01139     }
01140   else if (util_strequal (cmdName, "pktReadTcpSeqNum"))
01141     {
01142       result = tcpPkt->seqNum;
01143     }
01144   else if (util_strequal (cmdName, "pktReadTcpAckNum"))
01145     {
01146       result = tcpPkt->ackNum;
01147     }
01148   else
01149     {
01150       assert (0);
01151     }
01152   char tmpbuf[40];
01153   sprintf (tmpbuf, "%u", result);
01154 
01155   char *resultString = strdup (tmpbuf);
01156   Tcl_Obj *resultObj = Tcl_GetObjResult (interp);
01157   Tcl_SetStringObj (resultObj, resultString, -1);
01158 
01159   return TCL_OK;
01160 }
01161 
01162 
01163 /**
01164   * \brief Get tcl string representation of the tcp flags
01165   */
01166 
01167 static int
01168 pktReadTcpFlags (ClientData cd ,
01169          Tcl_Interp * interp, int objc, Tcl_Obj * const objv[])
01170 {
01171   assert (objc == 2);
01172 
01173   Pkt_EthernetHdr_t *pkt =
01174     (Pkt_EthernetHdr_t *) Nm_TclCDReadPtrFromObj (interp, (Nm_TclCD_t *) cd, objv[1]);
01175   Pkt_TcpHdr_t *tcp = Pkt_EthernetExtractTcp (pkt);
01176   char tmpbuf[100];
01177 
01178   // fin,syn,rst,psh,ack,urg,ece,cwr
01179   sprintf (tmpbuf, "%s%s%s%s%s%s%s%s",
01180        (tcp->fin ? "fin," : "!fin,"),
01181        (tcp->syn ? "syn," : "!syn,"),
01182        (tcp->rst ? "rst," : "!rst,"),
01183        (tcp->psh ? "psh," : "!psh,"),
01184        (tcp->ack ? "ack," : "!ack,"),
01185        (tcp->urg ? "urg," : "!urg,"),
01186        (tcp->ece ? "ece," : "!ece,"), (tcp->cwr ? "cwr," : "!cwr"));
01187 
01188   char *resultString = strdup (tmpbuf);
01189   Tcl_Obj *resultObj = Tcl_GetObjResult (interp);
01190   Tcl_SetStringObj (resultObj, resultString, -1);
01191 
01192   return TCL_OK;
01193 }
01194 
01195 
01196 /**
01197   * \brief Some code to understand ways in which to execute tcl code from C
01198   */
01199 
01200 static int
01201 tclTestC (ClientData cd ,
01202       Tcl_Interp * interp, int objc, Tcl_Obj * const objv[])
01203 {
01204   int count = 1000;
01205   char *cmdName = Tcl_GetStringFromObj (objv[0], NIL (int));
01206   if (objc == 3)
01207     {
01208       assert (TCL_OK == Tcl_GetIntFromObj (interp, objv[2], &count));
01209     }
01210   int i;
01211 
01212   if (util_strequal (cmdName, "testC1"))
01213     {
01214       for (i = 0; i < count; i++)
01215     {
01216       Tcl_EvalObjEx (interp, objv[1], 0);
01217     }
01218     }
01219   else if (util_strequal (cmdName, "testC2"))
01220     {
01221       for (i = 0; i < count; i++)
01222     {
01223       char *cmdString = Tcl_GetString (objv[1]);
01224       Tcl_Eval (interp, cmdString);
01225     }
01226     }
01227   else if (util_strequal (cmdName, "testC3"))
01228     {
01229       char *cmdString = Tcl_GetString (objv[1]);
01230       int cmdStringLength = strlen (cmdString);
01231       for (i = 0; i < count; i++)
01232     {
01233       Tcl_EvalEx (interp, cmdString, cmdStringLength, 0);
01234     }
01235     }
01236   else
01237     {
01238       printf ("Error in tclTestC\n");
01239       assert (0);
01240     }
01241 
01242   return TCL_OK;
01243 }
01244 
01245 
01246 /**
01247   * \brief Code that calls Rlp_ParseFile on the given file.
01248   * Used for testing the parser
01249   */
01250 
01251 static int
01252 tclTestParser (ClientData cd ,
01253            Tcl_Interp * interp, int objc, Tcl_Obj * const objv[])
01254 {
01255   assert (objc == 2);
01256 
01257   char *fileName = Tcl_GetStringFromObj (objv[1], NIL (int));
01258   FILE *ruleFile = fopen (fileName, "r");
01259   if (ruleFile == NIL (FILE))
01260     {
01261       printf
01262     ("Error, could not open file %s, returning without testing parser\n",
01263      fileName);
01264       return TCL_OK;
01265     }
01266   char *ruleFileInText = util_file_to_string (ruleFile);
01267   array_t *result  = util_process_file (ruleFileInText);
01268   free (ruleFileInText);
01269   fclose (ruleFile);
01270 
01271   // we set the result to 0 which indicates that the 
01272   // function completed, we don't care about actual return codes
01273   Tcl_Obj *resultObj = Tcl_GetObjResult (interp);
01274   Tcl_SetIntObj (resultObj, 0);
01275 
01276   return TCL_OK;
01277 }
01278 
01279 
01280 /**
01281   * \brief Code that gets a test string that is the entire contents of a file.
01282   * File must be ascii, i.e., no NULLs in the file.
01283   */
01284 
01285 static int
01286 tclGetFileAsText (ClientData cd ,
01287           Tcl_Interp * interp, int objc, Tcl_Obj * const objv[])
01288 {
01289   assert (objc == 2);
01290 
01291   char *fileName = Tcl_GetStringFromObj (objv[1], NIL (int));
01292   FILE *ruleFile = fopen (fileName, "r");
01293   if (ruleFile == NIL (FILE))
01294     {
01295       printf
01296     ("Error, could not open file %s, returning without generating string\n",
01297      fileName);
01298       return TCL_OK;
01299     }
01300   char *ruleFileInText = util_file_to_string (ruleFile);
01301   fclose (ruleFile);
01302 
01303   Tcl_Obj *resultObj = Tcl_GetObjResult (interp);
01304   Tcl_SetStringObj (resultObj, ruleFileInText, strlen (ruleFileInText));
01305 
01306   return TCL_OK;
01307 }
01308 
01309 
01310 /**
01311   * \brief Code for testing sys call speed
01312   */
01313 
01314 static int
01315 tclBufferWritePkts (ClientData cd ,
01316             Tcl_Interp * interp,
01317             int objc , Tcl_Obj * const objv[])
01318 {
01319   int numPackets = 1;
01320   Nm_TclGetIntVar (interp, "numPackets", &numPackets);
01321 
01322   char *fileName = "/dev/null";
01323   Nm_TclGetStringVar (interp, "fileName", &fileName);
01324   // int destFile = creat( fileName, 0755 );
01325   FILE *destFile = fopen (fileName, "w");
01326 
01327   int i;
01328   int aPktLength = 64;
01329   char aPkt[64];
01330   // printf("About to write %d pkts to %s\n", numPackets, fileName );
01331   for (i = 0; i < numPackets; i++)
01332     {
01333       int numWritten = fwrite (aPkt, 4, aPktLength, destFile);
01334       if (numWritten != aPktLength)
01335     {
01336       printf ("Unsucc write: numWritten = %d, aPktLength = %d\n",
01337           numWritten, aPktLength);
01338     }
01339     }
01340 
01341   return TCL_OK;
01342 }
01343 
01344 
01345 /**
01346   * \brief Code for testing sys call speed
01347   */
01348 
01349 static int
01350 tclWritePkts (ClientData cd ,
01351           Tcl_Interp * interp, int objc , Tcl_Obj * const objv[])
01352 {
01353   int numPackets = 1;
01354   Nm_TclGetIntVar (interp, "numpkt", &numPackets);
01355 
01356   char *fileName = "/dev/null";
01357   Nm_TclGetStringVar (interp, "fileName", &fileName);
01358   // int destFile = creat( fileName, 0755 );
01359   int destFile = open (fileName, O_RDWR, 0);
01360   if (destFile == -1)
01361     {
01362       destFile = creat (fileName, 0755);
01363     }
01364   if (destFile == -1)
01365     {
01366       printf ("Could not open or create file %s\n", fileName);
01367     }
01368 
01369   int i;
01370   array_t *timeStamps = util_time_stamp_init (numPackets + 1);
01371 
01372   int aPktLength = 64;
01373   char aPkt[64];
01374   printf ("About to write %d pkts to %s\n", numPackets, fileName);
01375   util_time_stamp_set (timeStamps, 0);
01376   for (i = 0; i < numPackets; i++)
01377     {
01378       int numWritten = write (destFile, aPkt, aPktLength);
01379       util_time_stamp_set (timeStamps, (i + 1));
01380       if (numWritten != aPktLength)
01381     {
01382       printf
01383         ("Unsucc write: numWritten = %d, aPktLength = %d, destFile = %d\n",
01384          numWritten, aPktLength, destFile);
01385     }
01386     }
01387   util_time_stamp_print (timeStamps);
01388   array_free (timeStamps);
01389 
01390   return TCL_OK;
01391 }
01392 
01393 
01394 /**
01395   * \brief Code for injecting crafted packets 
01396   */
01397 
01398 static int
01399 tclTxPkt (ClientData cd ,
01400       Tcl_Interp * interp, int objc , Tcl_Obj * const objv[])
01401 {
01402   char *ifName = "eth1";
01403   Nm_TclGetStringVar (interp, "ifname", &ifName);
01404   static Pkt_LibNet_t *alibnet;
01405 
01406   if (alibnet == NIL (Pkt_LibNet_t))
01407     {
01408       alibnet = Pkt_InitLibNet (ifName);
01409     }
01410   else
01411     {
01412       if (util_strequal (ifName, alibnet->interfaceName))
01413     {
01414       // keep it
01415     }
01416       else
01417     {
01418       // update it
01419       Pkt_LibNetFinish (alibnet);
01420       alibnet = Pkt_InitLibNet (ifName);
01421     }
01422     }
01423 
01424   Pkt_EthernetHdr_t *pkt =
01425     (Pkt_EthernetHdr_t *) Nm_TclCDReadPtrFromObj (interp, (Nm_TclCD_t *) cd, objv[1]);
01426   int aPktLength = Pkt_EthernetPktHdrReadLength (pkt);
01427   Pkt_HTON (pkt);
01428   Pkt_EthPktWrite (pkt, aPktLength, alibnet);
01429   Pkt_NTOH (pkt);
01430 
01431   return TCL_OK;
01432 }
01433 
01434 
01435 /**
01436   * \brief Code for testing packet injection speeds
01437   */
01438 
01439 static int
01440 tclInjectPkts (ClientData cd ,
01441            Tcl_Interp * interp, int objc , Tcl_Obj * const objv[])
01442 {
01443 
01444   int index;
01445 
01446   int numPackets = 21;
01447   Nm_TclGetIntVar (interp, "numpkt", &numPackets);
01448 
01449   char *ifName = "eth1";
01450   Nm_TclGetStringVar (interp, "ifname", &ifName);
01451 
01452   int printTimeStamps = 0;
01453   Nm_TclGetIntVar (interp, "ts", &printTimeStamps);
01454 
01455   double rate;
01456   double rateLimit = 0.0;
01457   Nm_TclGetDoubleVar (interp, "ratelimit", &rateLimit);
01458 
01459   Pkt_TfcMode_t *tfcMode = readTfcModeParams (interp);
01460   Pkt_LibNet_t *alibnet = Pkt_InitLibNet (ifName);
01461 
01462   array_t *pktArray =
01463     Pkt_SeedRandEthPktArray (Pkt_HostByteOrder_c, tfcMode->numSeeds, tfcMode);
01464 
01465   int i;
01466   printf ("Writing %d pkts\n", numPackets);
01467   util_timing_t startTime;
01468   util_timing_t finishTime;
01469 
01470   array_t *timeStamps;
01471 
01472   if (printTimeStamps)
01473     {
01474       timeStamps = util_time_stamp_init (numPackets + 1);
01475     }
01476 
01477   if (printTimeStamps)
01478     {
01479       util_time_stamp_set (timeStamps, 0);
01480     }
01481 
01482   util_timing_set (&startTime);
01483   util_timing_t pauseTime = util_timing_pair (tfcMode->pktGap);
01484 
01485   util_timing_t difftime;
01486 
01487   Pkt_EthernetHdr_t *aPkt = Pkt_CreateRandEthPkt (pktArray);
01488   Pkt_IpHdr_t *ipPkt = Pkt_EthernetExtractIp (aPkt);
01489   int ipPktLength = ipPkt->length;
01490   int aPktLength = ipPktLength + sizeof (Pkt_EthernetHdr_t);
01491 
01492   int count = 0;
01493   int bytesTx;
01494   while (1)
01495     {
01496       int bytesTx = Pkt_EthPktWrite (aPkt, aPktLength, alibnet);
01497       if (bytesTx != 0)
01498     {
01499       count++;
01500       if (count >= numPackets)
01501         {
01502           break;
01503         }
01504     }
01505       util_timing_pause (pauseTime);
01506       if (printTimeStamps)
01507     {
01508       util_time_stamp_set (timeStamps, (count + 1));
01509     }
01510       if (rateLimit != 0.0)
01511     {
01512       while (1)
01513         {
01514           util_timing_set (&finishTime);
01515           util_timing_t difftime =
01516         util_timing_diff (finishTime, startTime);
01517           rate = computeRate (tfcMode->size, count, difftime);
01518           if (rate < rateLimit)
01519         {
01520           break;
01521         }
01522         }
01523     }
01524     }
01525   util_timing_set (&finishTime);
01526   difftime = util_timing_diff (finishTime, startTime);
01527 
01528   rate = computeRate (tfcMode->size, numPackets, difftime);
01529 
01530   double kbits =
01531     (8.0 * (7 + 1 + 6 + 6 + 2 + (MAX (46, (40 + tfcMode->size))) + 12) *
01532      (((double) numPackets) / 1000.0));
01533   double difftimeDouble = util_timing_secs (difftime);
01534   printf ("Transmitted %d payload byte L4 packets: %.0f kbits "
01535       "(incl preamble,sfd,fcs,frame-gap) "
01536       "in %.2f seconds, rate = %.0f Mbps, %.4f Kpps\n",
01537       (tfcMode->size), kbits, difftimeDouble, rate,
01538       (0.001 * (double) numPackets) / difftimeDouble);
01539 
01540   if (printTimeStamps)
01541     {
01542       util_time_stamp_print (timeStamps);
01543       array_free (timeStamps);
01544     }
01545 
01546   Pkt_LibNetFinish (alibnet);
01547 
01548   return TCL_OK;
01549 }
01550 
01551 
01552 /**
01553   * \brief Create the basic parameters for the call to Pkt_CreateRandEthPkt
01554   *
01555   */
01556 
01557 static Pkt_TfcMode_t *
01558 readTfcModeParams (Tcl_Interp * interp)
01559 {
01560   int size = 10;
01561   Nm_TclGetIntVar (interp, "pktsize", &size);
01562 
01563   Pkt_TfcMode_t *tfcMode = (Pkt_TfcMode_t *) malloc (sizeof (Pkt_TfcMode_t));
01564   tfcMode->size = size;
01565 
01566   char Nm_EvgaSrcMac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa };
01567   char Nm_EvgaDestMac[] = { 0x00, 0x15, 0x17, 0x20, 0xE1, 0x80 };
01568 
01569   /// \todo add function to read these directly from shell
01570   tfcMode->srcMac = Nm_EvgaSrcMac;
01571   tfcMode->destMac = Nm_EvgaDestMac;
01572 
01573   int numSeeds = 1;
01574   Nm_TclGetIntVar (interp, "numSeeds", &numSeeds);
01575   tfcMode->numSeeds = numSeeds;
01576 
01577   double delay = 0.0;
01578   Nm_TclGetDoubleVar (interp, "pktgap", &delay);
01579   tfcMode->pktGap = delay * 0.000001;   // pktgap is given in usec
01580 
01581   return tfcMode;
01582 }
01583 
01584 
01585 /**
01586   *     \brief  Perform action desired by user.
01587   *
01588   *     Action is a tcl function which takes a single parameter, specifically
01589   *     a pointer to a packet (well the int id that we're using in place of the pointer).
01590   */
01591 
01592 static int
01593 tclTestTclAction (ClientData cd ,
01594           Tcl_Interp * interp,
01595           int objc , Tcl_Obj * const objv[])
01596 {
01597 
01598   const int numArgsToTclFunction = 2;
01599   Tcl_Obj *tmpObjv[numArgsToTclFunction];
01600 
01601   char *procedure = "dummy";
01602   Tcl_Obj *tmpPtr = Tcl_NewStringObj (strdup (procedure), -1);
01603   tmpObjv[0] = tmpPtr;
01604 
01605   char *dummyarg = "dummyarg";
01606   tmpObjv[1] = Tcl_NewStringObj (strdup (dummyarg), -1);
01607 
01608   // two arguments, in the array of Tcl_Obj *s : one is the function's name, the
01609   // other is the "pointer" to the packet
01610   int code = Tcl_EvalObjv (interp, numArgsToTclFunction, tmpObjv, 0);
01611   return code;
01612 
01613 }
01614 
01615 
01616 /**
01617   * \brief Perform performance test of compress code
01618   *
01619   */
01620 
01621 static int
01622 tclCompressTestPerf (ClientData cd ,
01623              Tcl_Interp * interp,
01624              int objc , Tcl_Obj * const objv[])
01625 {
01626   int len = 1000000;
01627   Nm_TclGetIntVar (interp, "length", &len);
01628   int count = 10;
01629   Nm_TclGetIntVar (interp, "count", &count);
01630   int srcLen = len;
01631   int destLen = 2 * len;
01632   char *src = (char *) malloc (srcLen);
01633   char *dest = (char *) malloc (destLen);
01634 
01635   util_timing_t startTime;
01636   util_timing_t finishTime;
01637 
01638   int i;
01639   util_timing_set (&startTime);
01640   for (i = 0; i < count; i++)
01641     {
01642       /// \todo removed because of linker issues
01643       /// compress( dest, & destLen, src, srcLen );
01644     }
01645   util_timing_set (&finishTime);
01646   util_timing_t difftime = util_timing_diff (finishTime, startTime);
01647   double difftimeDouble = util_timing_secs (difftime);
01648   double rate = len * count / (difftimeDouble * 1000.0);
01649   printf ("compress %d iters, %d bytes per iter: rate %.4f MBytes/sec\n",
01650       count, len,
01651       ((double) count * (double) len) / (1000000.0 * difftimeDouble));
01652   fflush (stdout);
01653 
01654   return TCL_OK;
01655 }
01656 
01657 
01658 /**
01659   * \brief Perform compression of compress code
01660   *
01661   * \ingroup doc \b compTestReduction Perform a check of the amount
01662   * of data compression the underlying lzo compression library implements.
01663   *
01664   */
01665 
01666 static int
01667 tclCompressTestReduction (ClientData cd ,
01668               Tcl_Interp * interp,
01669               int objc , Tcl_Obj * const objv[])
01670 {
01671   char *fileName = "a.txt";
01672   Nm_TclGetStringVar (interp, "filename", &fileName);
01673   int blockSize = 1000;
01674   Nm_TclGetIntVar (interp, "blocksize", &blockSize);
01675 
01676   int destLen = 2 * blockSize;
01677   char *dest = (char *) malloc (destLen);
01678 
01679   FILE *f = fopen (fileName, "r");
01680   if (f == NIL (FILE))
01681     {
01682       printf ("Could not open file %s\n", fileName);
01683       return TCL_OK;
01684     }
01685 
01686   char *text = util_file_to_string (f);
01687   int textLength = strlen (text);
01688   int i;
01689   int numBlocks = textLength / blockSize;
01690   textLength = numBlocks * blockSize;   // make an integer number of blocks
01691 
01692   int totalCompressedBytes = 0;
01693   for (i = 0; i < numBlocks; i++)
01694     {
01695       // compress( dest, & destLen, text + blockSize * i, blockSize );
01696       totalCompressedBytes += (destLen > blockSize) ? blockSize : destLen;
01697     }
01698 
01699   int fullFileLength = 2 * textLength;
01700   char *fullFile = (char *) malloc (2 * textLength);
01701   // compress( fullFile, & fullFileLength, text, textLength );
01702 
01703   printf ("For file %s, using %d sized blocks:\n"
01704       "\tTotal length = %d\n"
01705       "\tCompressed flat = %d\n"
01706       "\tCompressed segments = %d)\n",
01707       fileName, blockSize, textLength, fullFileLength,
01708       totalCompressedBytes);
01709   return TCL_OK;
01710 }
01711 
01712 
01713 /**
01714   * \brief \b array_test Run tests on array package
01715   *
01716   * \ingroup com 
01717   *
01718   */
01719 
01720 static int
01721 tclArrayTest (ClientData cd ,
01722           Tcl_Interp * interp, int objc , Tcl_Obj * const objv[])
01723 {
01724   Array_Test ();
01725   return TCL_OK;
01726 }
01727 
01728 
01729 /**
01730   * \brief Take a packet crafed with tcl, and insert it into the 
01731   * managers input buffer.  Used to create tcl actions that 
01732   * generate packets.
01733   */
01734 
01735 static int
01736 tclEvlMgrInsertPktIntoInputBuffer (ClientData cd ,
01737                    Tcl_Interp * interp,
01738                    int objc , Tcl_Obj * const objv[])
01739 {
01740   assert (objc == 3);
01741   Tcl_Obj *mgrObj = objv[1];
01742   Tcl_Obj *pktObj = objv[2];
01743 
01744   Evl_Manager_t *mgr = (Evl_Manager_t *) Nm_TclCDReadPtrFromObj (interp, (Nm_TclCD_t *) cd, mgrObj);
01745   Pkt_EthernetHdr_t *pkt = (Pkt_EthernetHdr_t *) Nm_TclCDReadPtrFromObj (interp, (Nm_TclCD_t *) cd, pktObj);
01746   Evl_Bridge_t *bridge = mgr->bridge;
01747 
01748   Evl_BridgeInsertPktInIbuf (bridge, pkt);
01749   return TCL_OK;
01750 }
01751 
01752 
01753 /**
01754   * \brief
01755   */
01756 
01757 static double
01758 computeRate (int size, int numPackets, util_timing_t diffTime)
01759 {
01760   double kbits = (8.0 * (7 + 1 + 6 + 6 + 2 + (MAX (46, (40 + size))) + 12) *
01761           (((double) numPackets) / 1000.0));
01762   double difftimeDouble = util_timing_secs (diffTime);
01763   double rate = kbits / (difftimeDouble * 1000.0);
01764 
01765   return rate;
01766 }
01767 
01768 
01769 /**
01770   * \brief End profiler
01771   *
01772   */
01773 
01774 static int
01775 tclStopProfiler (ClientData cd ,
01776          Tcl_Interp * interp, int objc , Tcl_Obj * const objv[])
01777 {
01778   // ProfilerStop ();
01779 
01780   return TCL_OK;
01781 }
01782 
01783 /** \brief Perform test of st code */
01784 
01785 static int
01786 tclStTest(ClientData cd ,
01787        Tcl_Interp * interp, int objc , Tcl_Obj * const objv[])
01788 {
01789   Hash_Test();
01790 
01791   return TCL_OK;
01792 }
01793 
01794 /** \brief Perform test of st code performance */
01795 
01796 static int
01797 tclStTestPerf (ClientData cd ,
01798        Tcl_Interp * interp, int objc , Tcl_Obj * const objv[])
01799 {
01800   int numIter = 10;
01801   Nm_TclGetIntVar (interp, "num", &numIter);
01802   char *aString = (char *) malloc (100);
01803   int i;
01804   for (i = 0; i < 99; i++)
01805     {
01806       aString[i] = 'x';
01807     }
01808   aString[5] = '\0';
01809 
01810   util_timing_t startTime;
01811   util_timing_t finishTime;
01812   util_timing_t difftime;
01813   double difftimeDouble;
01814 
01815   st_table *stringTable = Hash_InitTable ( ( int(*)() ) strcmp,  ( int(*)() ) st_strhash);
01816   util_timing_set (&startTime);
01817   for (i = 0; i < numIter; i++)
01818     {
01819       *(int *) (aString + 1) = i + 1;
01820       Hash_Insert (stringTable, aString, 0);
01821     }
01822   util_timing_set (&finishTime);
01823   difftime = util_timing_diff (finishTime, startTime);
01824   difftimeDouble = util_timing_secs (difftime);
01825   printf ("Time to insert foo %d times is %f => %f iter per sec\n",
01826       numIter, difftimeDouble, (numIter / difftimeDouble));
01827 
01828   util_timing_set (&startTime);
01829   for (i = 0; i < numIter; i++)
01830     {
01831       // *(int *) (aString + 1 )= i + 1;
01832       Hash_Lookup (stringTable, aString, 0);
01833     }
01834   util_timing_set (&finishTime);
01835   difftime = util_timing_diff (finishTime, startTime);
01836   difftimeDouble = util_timing_secs (difftime);
01837   printf ("Time to lookup foo %d times is %f => %f iter per sec\n",
01838       numIter, difftimeDouble, (numIter / difftimeDouble));
01839   return TCL_OK;
01840 }
01841 
01842 /** \brief For tk testing
01843 
01844 */
01845 
01846 
01847 static int *dummy( Tcl_Interp *interp ) {
01848   return TCL_OK;
01849 }
01850 
01851 /** \brief Trivial tk call
01852 
01853 */
01854 
01855 static int
01856 tclTestTk (ClientData cd ,
01857        Tcl_Interp * interp, int objc , Tcl_Obj * const objv[])
01858 {
01859   // char *screenName = "daisy:0";
01860   // char *appName = "azinix tk";
01861   // char *className = "Azinix";
01862   // Tk_Window tkwin = Tk_CreateMainWindow( interp, screenName, appName, className );
01863   // Tk_CreateWindow( interp, NULL, "Azinix", "daisy:4" );
01864   return TCL_OK;
01865 
01866   //AA int tkwinCode = Tk_Init( interp );
01867   //AA if ( tkwinCode == TCL_OK ) {
01868   //AA   printf("Tk_Init succ\n");
01869   //AA }
01870   //AA else {
01871   //AA   printf("Tk_Init unsucc\n");
01872   //AA }
01873 
01874   //AA // three arguments, in the array of Tcl_Obj *s : one is the function's name, the
01875   //AA // next is the "pointer" to the manager, then a pointer to the pkt
01876   //AA const int numArgsToTclFunction = 1;
01877   //AA Tcl_Obj *tmpObjv[numArgsToTclFunction];
01878   //AA char *tclRuleString = "wm title . \"hi!\"\n"
01879   //AA              "button .hello -text \"Hello World!\" -command exit\n"
01880   //AA              "pack .hello\n";
01881   //AA Tcl_Obj *tmpPtr = Tcl_NewStringObj (strdup (tclRuleString), -1);
01882   //AA tmpObjv[0] = tmpPtr;
01883 
01884   //AA int retCode = Tcl_EvalObjv ( interp, 1, tmpObjv, TCL_EVAL_GLOBAL);
01885  
01886 
01887   //AA // Tk_Main( 1, argv, dummy );
01888 
01889   //AA return TCL_OK;
01890 }
01891 
01892 /** \brief Small function to test C++ linkage
01893 
01894 */
01895 
01896 // class Point_t {
01897 //   public: int x;
01898 //        int y;
01899 //    void print() { printf("x is %d, y is %d\n", x, y ); }
01900 //    void print( char *s ) { printf("%s: x is %d, y is %d\n", s, x, y ); }
01901 // };
01902 
01903 // #include "/nfs/narya/pf/STLport-5.1.4/stlport/vector"
01904 // #include <iostream>
01905 // #include <vector>
01906 // #include <string>
01907 // using namespace std;
01908 // 
01909 // static int tclTestCplusplus( ClientData cd ,
01910 //      Tcl_Interp * interp, 
01911 //      int objc , 
01912 //      Tcl_Obj * const objv[]  )
01913 // {
01914 // 
01915 //   Point_t aPoint;
01916 //   aPoint.x = 1;
01917 //   aPoint.y = 2;
01918 //   aPoint.print();
01919 //   aPoint.print("a mesg");
01920 // 
01921 //   vector<int> av;
01922 //   av.push_back(1);
01923 //   printf("av[0] is %d\n", av[0] );
01924 // 
01925 //   return TCL_OK;
01926 // }
01927 
01928 /*
01929 #include <qt3/qapplication.h>
01930 #include <qt3/qpushbutton.h>
01931 
01932 int main_qt( int argc, char **argv )
01933 {
01934     QApplication a( argc, argv );
01935 
01936     QPushButton hello( "Hello world!", 0 );
01937     hello.resize( 100, 30 );
01938 
01939     a.setMainWidget( &hello );
01940     hello.show();
01941     return a.exec();
01942 }
01943 
01944 static int tclTestQt( ClientData cd ,
01945         Tcl_Interp * interp, 
01946         int objc , 
01947         Tcl_Obj * const objv[]  )
01948 {
01949   main_qt( 1, NIL( char *) );
01950   return TCL_OK;
01951 }
01952 */