[Tinyos-2-commits] [tinyos-main] r5724 committed - linkbench: add a general purpose link layer benchmarking application

tinyos-main at googlecode.com tinyos-main at googlecode.com
Tue Sep 6 00:36:05 PDT 2011


Revision: 5724
Author:   mmaroti
Date:     Tue Sep  6 00:34:50 2011
Log:      linkbench: add a general purpose link layer benchmarking  
application
http://code.google.com/p/tinyos-main/source/detail?r=5724

Added:
  /trunk/apps/tests/LinkBench
  /trunk/apps/tests/LinkBench/BenchmarkAppC.nc
  /trunk/apps/tests/LinkBench/BenchmarkAppP.nc
  /trunk/apps/tests/LinkBench/BenchmarkCore.h
  /trunk/apps/tests/LinkBench/BenchmarkCore.nc
  /trunk/apps/tests/LinkBench/BenchmarkCoreC.nc
  /trunk/apps/tests/LinkBench/BenchmarkCoreP.nc
  /trunk/apps/tests/LinkBench/Benchmarks.h
  /trunk/apps/tests/LinkBench/Makefile
  /trunk/apps/tests/LinkBench/Makefile.Pdetect
  /trunk/apps/tests/LinkBench/Messages.h
  /trunk/apps/tests/LinkBench/README
  /trunk/apps/tests/LinkBench/StandardBenchmarks.h
  /trunk/apps/tests/LinkBench/UserdefinedBenchmarks.h
  /trunk/apps/tests/LinkBench/codeprofile
  /trunk/apps/tests/LinkBench/codeprofile/CodeProfile.nc
  /trunk/apps/tests/LinkBench/codeprofile/CodeProfileC.nc
  /trunk/apps/tests/LinkBench/codeprofile/CodeProfileP.nc
  /trunk/apps/tests/LinkBench/javasrc
  /trunk/apps/tests/LinkBench/javasrc/benchmark
  /trunk/apps/tests/LinkBench/javasrc/benchmark/cli
  /trunk/apps/tests/LinkBench/javasrc/benchmark/cli/BenchmarkCli.java
  /trunk/apps/tests/LinkBench/javasrc/benchmark/common
  /trunk/apps/tests/LinkBench/javasrc/benchmark/common/BenchmarkBatch.java
  /trunk/apps/tests/LinkBench/javasrc/benchmark/common/BenchmarkCommons.java
   
/trunk/apps/tests/LinkBench/javasrc/benchmark/common/BenchmarkController.java
  /trunk/apps/tests/LinkBench/javasrc/benchmark/common/BenchmarkResult.java
  /trunk/apps/tests/LinkBench/javasrc/benchmark/common/MacParser.java
  /trunk/apps/tests/LinkBench/javasrc/benchmark/common/TimerParser.java
  /trunk/apps/tests/LinkBench/javasrc/build.xml
  /trunk/apps/tests/LinkBench/javasrc/dist-addon
  /trunk/apps/tests/LinkBench/javasrc/dist-addon/README.TXT
  /trunk/apps/tests/LinkBench/javasrc/dist-addon/assets
  /trunk/apps/tests/LinkBench/javasrc/dist-addon/assets/benchmark.css
  /trunk/apps/tests/LinkBench/javasrc/dist-addon/assets/benchmark.xsl
  /trunk/apps/tests/LinkBench/javasrc/dist-addon/batchfiles
  /trunk/apps/tests/LinkBench/javasrc/dist-addon/batchfiles/batch_all.yml
   
/trunk/apps/tests/LinkBench/javasrc/dist-addon/batchfiles/batch_collisions.yml
   
/trunk/apps/tests/LinkBench/javasrc/dist-addon/batchfiles/batch_forwarding.yml
  /trunk/apps/tests/LinkBench/javasrc/dist-addon/batchfiles/batch_lpl.yml
   
/trunk/apps/tests/LinkBench/javasrc/dist-addon/batchfiles/batch_throughputs.yml
  /trunk/apps/tests/LinkBench/javasrc/dist-addon/batchfiles/generate_batch.sh
   
/trunk/apps/tests/LinkBench/javasrc/dist-addon/batchfiles/sample_batch_config.yml
  /trunk/apps/tests/LinkBench/javasrc/dist-addon/batchfiles/tos_metric.yml
  /trunk/apps/tests/LinkBench/javasrc/dist-addon/lib
  /trunk/apps/tests/LinkBench/javasrc/dist-addon/lib/commons-cli-1.2.jar
  /trunk/apps/tests/LinkBench/javasrc/dist-addon/lib/snakeyaml-1.7.jar
  /trunk/apps/tests/LinkBench/javasrc/dist-addon/linkbench.sh
  /trunk/apps/tests/LinkBench/javasrc/dist-addon/tos_metric.sh
  /trunk/apps/tests/LinkBench/scripts
  /trunk/apps/tests/LinkBench/scripts/make-tossim-network.py
  /trunk/apps/tests/LinkBench/scripts/meyer-short.txt
  /trunk/apps/tests/LinkBench/scripts/minstall.sh
  /trunk/apps/tests/LinkBench/scripts/mstats.awk
  /trunk/apps/tests/LinkBench/scripts/mstats.sh

=======================================
--- /dev/null
+++ /trunk/apps/tests/LinkBench/BenchmarkAppC.nc	Tue Sep  6 00:34:50 2011
@@ -0,0 +1,83 @@
+/*
+* Copyright (c) 2010, University of Szeged
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* - Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* - Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* - Neither the name of University of Szeged nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+* OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Author: Krisztian Veress
+*         veresskrisztian at gmail.com
+*/
+
+#include "Messages.h"
+
+configuration BenchmarkAppC {}
+
+implementation {
+  components MainC;
+  Comm.Boot -> MainC.Boot;
+
+  components BenchmarkCoreC as Core;
+  components BenchmarkAppP as Comm;
+  Comm.BenchmarkCore -> Core;
+  Comm.CoreControl -> Core;
+  Comm.CoreInit -> Core;
+
+  components LedsC;
+  Comm.Leds -> LedsC;
+
+#ifdef TOSSIM
+
+  components SerialActiveMessageC as Medium;
+
+  components new SerialAMReceiverC(AM_CTRLMSG_T)      as RxCtrl;
+  components new SerialAMReceiverC(AM_SETUPMSG_T)     as RxSetup;
+
+  components new SerialAMSenderC(AM_SYNCMSG_T)        as TxSync;
+  components new SerialAMSenderC(AM_DATAMSG_T)        as TxData;
+
+#else
+
+  components ActiveMessageC as Medium;
+
+  components new AMReceiverC(AM_CTRLMSG_T)    	      as RxCtrl;
+  components new AMReceiverC(AM_SETUPMSG_T)    	      as RxSetup;
+
+  components new DirectAMSenderC(AM_SYNCMSG_T)        as TxSync;
+  components new DirectAMSenderC(AM_DATAMSG_T)        as TxData;
+
+#endif
+
+  Comm.RxCtrl -> RxCtrl;
+  Comm.RxSetup -> RxSetup;
+
+  Comm.TxSync -> TxSync;
+  Comm.TxData -> TxData;
+
+  Comm.Control -> Medium;
+  Comm.Packet -> Medium;
+}
=======================================
--- /dev/null
+++ /trunk/apps/tests/LinkBench/BenchmarkAppP.nc	Tue Sep  6 00:34:50 2011
@@ -0,0 +1,187 @@
+/*
+* Copyright (c) 2010, University of Szeged
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* - Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* - Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* - Neither the name of University of Szeged nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+* OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Author: Krisztian Veress
+*         veresskrisztian at gmail.com
+*/
+
+module BenchmarkAppP @safe() {
+
+  uses {
+    interface Boot;
+
+    interface Receive as RxCtrl;
+    interface Receive as RxSetup;
+
+    interface AMSend  as TxSync;
+    interface AMSend  as TxData;
+
+    interface SplitControl as Control;
+    interface BenchmarkCore;
+    interface StdControl as CoreControl;
+    interface Init as CoreInit;
+
+    interface Packet;
+    interface Leds;
+  }
+
+}
+
+implementation {
+
+  bool core_configured, core_finished;
+  uint8_t resp_request, resp_idx;
+  message_t bpkt;
+
+  event void Boot.booted() {
+    call Control.start();
+  }
+
+  event void Control.startDone(error_t error) {
+    if (error != SUCCESS)
+      call Control.start();
+    else {
+      call CoreInit.init();
+      core_configured = core_finished = FALSE;
+    }
+  }
+
+  event void Control.stopDone(error_t error) {
+    call Control.start();
+  }
+
+  task void sendData() {
+    datamsg_t* msg = (datamsg_t*)(call  
Packet.getPayload(&bpkt,sizeof(datamsg_t)));
+    call Packet.clear(&bpkt);
+    if ( resp_request == CTRL_STAT_REQ && core_finished ) {
+
+      msg->type = DATA_STAT_OK;
+      msg->data_idx = resp_idx;
+      msg->payload.stat = *(call BenchmarkCore.getStat(resp_idx));
+      call TxData.send(AM_BROADCAST_ADDR, &bpkt, sizeof(datamsg_t));
+
+    // RESPONSE profile information
+    } else if ( resp_request == CTRL_PROFILE_REQ && core_finished ) {
+
+      msg->type = DATA_PROFILE_OK;
+      msg->data_idx = resp_idx;
+      msg->payload.profile = *(call BenchmarkCore.getProfile());
+      call TxData.send(AM_BROADCAST_ADDR, &bpkt, sizeof(datamsg_t));
+    }
+
+  }
+
+  task void sendSync() {
+    syncmsg_t* msg = (syncmsg_t*)(call  
Packet.getPayload(&bpkt,sizeof(syncmsg_t)));
+    call Packet.clear(&bpkt);
+    // RESPONSE the setup acknowledgement if applicable
+    if ( resp_request == CTRL_SETUP_SYN && core_configured ) {
+
+      msg->type = SYNC_SETUP_ACK;
+      msg->edgecnt = call BenchmarkCore.getEdgeCount();
+      msg->maxmoteid = call BenchmarkCore.getMaxMoteId();
+      dbg("Benchmark","sendSync sending... %d\n",TOS_NODE_ID);
+      call TxSync.send(AM_BROADCAST_ADDR, &bpkt, sizeof(syncmsg_t));
+    }
+  }
+
+  event void TxSync.sendDone(message_t* bufPtr, error_t error) { }
+  event void TxData.sendDone(message_t* bufPtr, error_t error) { }
+
+  event message_t* RxSetup.receive(message_t* bufPtr, void* payload,  
uint8_t len) {
+    setupmsg_t*  msg   = (setupmsg_t*)payload;
+    dbg("Benchmark","RxSetup.receive SETUP%d\n",TOS_NODE_ID);
+    call BenchmarkCore.setup(msg->config);
+    return bufPtr;
+  }
+
+  event message_t* RxCtrl.receive(message_t* bufPtr, void* payload,  
uint8_t len) {
+    ctrlmsg_t*  msg   = (ctrlmsg_t*)payload;
+    switch ( msg->type ) {
+
+      case CTRL_RESET :
+          dbg("Benchmark","RxCtrl.receive RESET %d\n",TOS_NODE_ID);
+          call BenchmarkCore.reset();
+          call Control.stop();
+          break;
+
+      case CTRL_SETUP_SYN :
+          dbg("Benchmark","RxCtrl.receive SETUP_SYN %d\n",TOS_NODE_ID);
+          if( core_configured ) {
+            resp_request = msg->type;
+            post sendSync();
+          }
+          break;
+
+      case CTRL_START :
+          dbg("Benchmark","RxCtrl.receive START %d\n",TOS_NODE_ID);
+          if( core_configured ) {
+            dbg("Benchmark"," ---- START CORE%d\n",TOS_NODE_ID);
+            call CoreControl.start();
+          }
+          break;
+
+      case CTRL_STAT_REQ:
+          dbg("Benchmark","RxCtrl.receive STAT_REQ %d\n",TOS_NODE_ID);
+          if ( core_finished ) {
+            dbg("Benchmark","------- CORE FINISHED\n");
+            resp_request = msg->type;
+            resp_idx = msg->data_req_idx;
+            post sendData();
+          } else
+            dbg("Benchmark","------- CORE NOT FINISHED\n");
+          break;
+      case CTRL_PROFILE_REQ:
+          dbg("Benchmark","RxCtrl.receive PROFILE_REQ %d\n",TOS_NODE_ID);
+          if ( core_finished ) {
+            resp_request = msg->type;
+            resp_idx = msg->data_req_idx;
+            post sendData();
+          }
+          break;
+      default:
+          break;
+    }
+    return bufPtr;
+  }
+
+  event void BenchmarkCore.finished() {
+    core_finished = TRUE;
+  }
+
+  event void BenchmarkCore.setupDone() {
+    core_configured = TRUE;
+  }
+
+  event void BenchmarkCore.resetDone() {
+    core_configured = core_finished = FALSE;
+  }
+}
=======================================
--- /dev/null
+++ /trunk/apps/tests/LinkBench/BenchmarkCore.h	Tue Sep  6 00:34:50 2011
@@ -0,0 +1,192 @@
+/*
+* Copyright (c) 2010, University of Szeged
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* - Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* - Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* - Neither the name of University of Szeged nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+* OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Author: Krisztian Veress
+*         veresskrisztian at gmail.com
+*/
+
+#ifndef BENCHMARK_CORE_H
+#define BENCHMARK_CORE_H
+
+#if MAX_EDGE_COUNT <= 8
+  typedef uint8_t pending_t;
+#elif MAX_EDGE_COUNT <= 16
+  typedef uint16_t pending_t;
+#elif MAX_EDGE_COUNT <= 32
+  typedef uint32_t pending_t;
+#elif MAX_EDGE_COUNT <= 64
+  typedef uint64_t pending_t;
+#else
+  #error "MAX_EDGE_COUNT is set too high! The current limit is 64!"
+#endif
+typedef pending_t edgeaddr_t;
+
+enum {
+	MAX_TIMER_COUNT	= 4,
+
+  // Policy flags
+  GLOBAL_USE_ACK           = 1<<0,
+  GLOBAL_USE_BCAST         = 1<<1,
+
+  GLOBAL_USE_MAC_LPL       = 1<<2,
+  GLOBAL_USE_MAC_PLINK     = 1<<3,
+
+  // Sending flags
+  SEND_ON_REQ     = 0,
+  SEND_ON_INIT    = 1,
+  SEND_ON_TIMER   = 2,
+
+  STOP_ON_ACK     = 1<<0,
+  STOP_ON_TIMER   = 1<<1,
+
+  NEED_ACK = 1,
+
+  INFINITE = 0,
+};
+
+typedef struct flag_t {
+  uint8_t       start_trigger : 3; // When to start sending messages
+  uint8_t       stop_trigger  : 2; // When to stop an infinite sending loop
+  uint8_t       need_ack      : 1; // ACK is needed?
+  uint8_t       inf_loop_on   : 1; // Whether an infinite sending loop is  
active
+  uint8_t       reserved      : 1; // Reserved for future expansion
+} flag_t;
+
+typedef struct timerset_t {
+  uint8_t       start;
+  uint8_t       stop;
+} timerset_t;
+
+typedef struct num_t {
+  uint8_t       send_num;         // How many messages to transmit in  
general
+  uint8_t       left_num;         // How many messages are left to transmit
+} num_t;
+
+// Base types for message counting / message sequence values
+#ifdef USE_32_BITS
+typedef uint32_t    seq_base_t;
+typedef nx_uint32_t nx_seq_base_t;
+#else
+typedef uint16_t    seq_base_t;
+typedef nx_uint16_t nx_seq_base_t;
+#endif
+
+typedef struct edge_t {
+  uint16_t      sender;           // Sender end of the edge
+  uint16_t      receiver;         // Receiver end of the edge
+  timerset_t    timers;           // Timers associated to this edge
+  flag_t        policy;           // Sending policies, settings, triggers
+  num_t         nums;             // Message counters
+  edgeaddr_t    reply_on;         // The edge bitmask used when sending on  
reception
+  seq_base_t    nextmsgid;        // The message id to send (on send  
side)/consecutive to receive (on receive side)
+} edge_t;
+
+// Stats type
+typedef nx_struct stat_t {
+  nx_seq_base_t    triggerCount;
+  nx_seq_base_t    backlogCount;
+  nx_seq_base_t    resendCount;
+
+  nx_seq_base_t    sendCount;
+  nx_seq_base_t    sendSuccessCount;
+  nx_seq_base_t    sendFailCount;
+
+  nx_seq_base_t    sendDoneCount;
+  nx_seq_base_t    sendDoneSuccessCount;
+  nx_seq_base_t    sendDoneFailCount;
+
+  nx_seq_base_t    wasAckedCount;
+  nx_seq_base_t    notAckedCount;
+
+  nx_seq_base_t    receiveCount;
+  nx_seq_base_t    consecutiveCount;
+  nx_seq_base_t    duplicateCount;
+  nx_seq_base_t    forwardCount;
+  nx_seq_base_t    missedCount;
+  nx_seq_base_t    wrongCount;
+
+  nx_uint8_t       remainedCount;
+} stat_t;
+
+typedef nx_struct profile_t {
+
+  nx_int32_t  min_atomic;
+  nx_int32_t  min_interrupt;
+  nx_int32_t  min_latency;
+
+  nx_int32_t  max_atomic;
+  nx_int32_t  max_interrupt;
+  nx_int32_t  max_latency;
+
+  nx_uint32_t  rtx_time;
+  nx_uint32_t  rstart_count;
+  nx_uint32_t  rx_bytes;
+  nx_uint32_t  tx_bytes;
+  nx_uint32_t  rx_msgs;
+
+  nx_uint16_t   debug;
+} profile_t;
+
+typedef nx_struct timersetup_t {
+  nx_uint8_t    isoneshot;
+  nx_uint32_t   delay;
+  nx_uint32_t   period_msec;
+} timersetup_t;
+
+// Where the MAC settings are located in the mac_setup_t type?
+enum {
+  // Extend the size of this struct if necessary for new MAC-s.
+  MAC_SETUP_LENGTH = 2,
+
+  LPL_WAKEUP_OFFSET = 0,
+
+  PLINK_RETRIES_OFFSET = 0,
+  PLINK_DELAY_OFFSET = 1
+};
+
+typedef nx_uint16_t mac_setup_t[MAC_SETUP_LENGTH];
+
+// Basic setup type
+typedef nx_struct setup_t {
+  nx_uint8_t    problem_idx;      // The problem we should test
+
+  nx_uint32_t   pre_run_msec;
+  nx_uint32_t   runtime_msec;     // How long should we run the test?
+  nx_uint32_t   post_run_msec;
+
+  nx_uint8_t    flags;            // Global flags ( such as BCAST, ACK,  
LPL, PLINK )
+  timersetup_t  timers[MAX_TIMER_COUNT];
+
+  // Mac protocol-specific settings
+  mac_setup_t   mac_setup;
+} setup_t;
+
+#endif
=======================================
--- /dev/null
+++ /trunk/apps/tests/LinkBench/BenchmarkCore.nc	Tue Sep  6 00:34:50 2011
@@ -0,0 +1,81 @@
+/*
+* Copyright (c) 2010, University of Szeged
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* - Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* - Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* - Neither the name of University of Szeged nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+* OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Author: Krisztian Veress
+*         veresskrisztian at gmail.com
+*/
+
+#include "BenchmarkCore.h"
+
+interface BenchmarkCore {
+
+  /**
+   * Requests a statistics indexed by 'index'
+   * @return the stat
+   */
+  command stat_t* getStat(uint16_t idx);
+
+  /**
+   * Requests the profile information
+   * @return the mote stat structure
+   */
+  command profile_t* getProfile();
+
+  /**
+   * Requests the current edge count
+   * @return the edge count of the current problem
+   */
+  command uint8_t getEdgeCount();
+
+  /**
+   * Requests the maximal mote id present in the current benchmark
+   * @return the maximal mote id
+   */
+  command uint8_t getMaxMoteId();
+
+
+  /** Configures the benchmark core with 'conf' */
+  command void setup(setup_t conf);
+
+  /** Indicates the successfull configuration of the benchmark */
+  event void setupDone();
+
+  /** Resets the benchmarking core component */
+  command void reset();
+
+  /** Indicates the finish of the reset operation */
+  event void resetDone();
+
+  /** Indicates the finish of the benchmark */
+  event void finished();
+
+
+}
=======================================
--- /dev/null
+++ /trunk/apps/tests/LinkBench/BenchmarkCoreC.nc	Tue Sep  6 00:34:50 2011
@@ -0,0 +1,119 @@
+/*
+* Copyright (c) 2010, University of Szeged
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* - Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* - Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* - Neither the name of University of Szeged nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+* OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Author: Krisztian Veress
+*         veresskrisztian at gmail.com
+*/
+
+#include "Messages.h"
+
+configuration BenchmarkCoreC {
+
+  provides {
+    interface StdControl;
+    interface BenchmarkCore;
+    interface Init;
+  }
+
+}
+
+implementation {
+
+  components BenchmarkCoreP as Core;
+
+  components new DirectAMSenderC(AM_TESTMSG_T)	    as TxTest;
+  components new AMReceiverC(AM_TESTMSG_T)    	    as RxTest;
+  Core.RxTest -> RxTest;
+  Core.TxTest -> TxTest;
+
+  components ActiveMessageC;
+  Core.Packet -> ActiveMessageC;
+  Core.Ack -> ActiveMessageC;
+
+#ifdef LOW_POWER_LISTENING
+  #if defined(RADIO_RF230) || defined(RADIO_CC1000) ||  
defined(RADIO_CC2420) || defined(RADIO_CC2520) || defined(RADIO_CC2420X) ||  
defined(RADIO_RFA1)
+    Core.LowPowerListening -> ActiveMessageC;
+  #else
+    #error " * NO PLATFORM SUPPORT FOR LOW POWER LISTENING LAYER *"
+  #endif
+#endif
+
+#ifdef PACKET_LINK
+  #if defined(RADIO_CC2420)
+    components CC2420ActiveMessageC;
+    Core.PacketLink -> CC2420ActiveMessageC;
+  #elif defined(RADIO_RF230) || defined(RADIO_CC2520) ||  
defined(RADIO_CC2420X)
+    Core.PacketLink -> ActiveMessageC;
+  #else
+    #error " * NO PLATFORM SUPPORT FOR PACKET LINK LAYER *"
+  #endif
+#endif
+
+#ifdef TRAFFIC_MONITOR
+  #if defined(RADIO_RF230)
+    components RF230RadioC;
+    Core.TrafficMonitor -> RF230RadioC;
+
+  #elif defined(RADIO_CC2420X)
+    components CC2420XRadioC;
+    Core.TrafficMonitor -> CC2420XRadioC;
+
+  #elif defined(RADIO_CC2420)
+    components CC2420ActiveMessageC;
+    Core.TrafficMonitor -> CC2420ActiveMessageC;
+
+  #endif
+#endif
+
+  components new TimerMilliC() as Timer;
+  Core.TestTimer -> Timer;
+
+  components LedsC;
+  Core.Leds -> LedsC;
+
+  components new VirtualizeTimerC(TMilli,MAX_TIMER_COUNT) as TTimer;
+  components new TimerMilliC() as TTimerFrom;
+  TTimer.TimerFrom -> TTimerFrom;
+  Core.TriggerTimer -> TTimer;
+
+  components RandomMlcgC;
+  Core.Random -> RandomMlcgC;
+  Core.RandomInit -> RandomMlcgC;
+
+  components CodeProfileC;
+  Core.CodeProfile -> CodeProfileC;
+  Core.CodeProfileControl -> CodeProfileC;
+
+  StdControl = Core;
+  BenchmarkCore = Core;
+  Init = Core;
+
+}
=======================================
--- /dev/null
+++ /trunk/apps/tests/LinkBench/BenchmarkCoreP.nc	Tue Sep  6 00:34:50 2011
@@ -0,0 +1,727 @@
+/*
+* Copyright (c) 2010, University of Szeged
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* - Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* - Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* - Neither the name of University of Szeged nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+* OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Author: Krisztian Veress
+*         veresskrisztian at gmail.com
+*/
+
+#define  _DEBUG_MODE_
+
+#include "BenchmarkCore.h"
+#include "Benchmarks.h"
+
+#define SET_STATE(s) atomic { call Leds.set(s); state = s; }
+
+#if defined(_DEBUG_MODE_)
+  #define _ASSERT_(cond) if(!(cond || profile.debug)){ profile.debug =  
__LINE__; }
+#else
+  #define str(s) s
+  #define _ASSERT_(cond) str()
+#endif
+
+module BenchmarkCoreP @safe() {
+
+  provides {
+    interface Init;
+    interface StdControl as Test;
+    interface BenchmarkCore;
+  }
+
+  uses {
+    interface Receive as RxTest;
+    interface AMSend  as TxTest;
+
+    interface Timer<TMilli> as TestTimer;
+    interface Timer<TMilli> as TriggerTimer[uint8_t id];
+
+    interface Packet;
+    interface AMPacket;
+    interface PacketAcknowledgements as Ack;
+
+#ifdef LOW_POWER_LISTENING
+    interface LowPowerListening;
+#endif
+
+#ifdef PACKET_LINK
+    interface PacketLink;
+#endif
+
+#ifdef TRAFFIC_MONITOR
+    interface TrafficMonitor;
+#endif
+
+    interface CodeProfile;
+    interface StdControl as CodeProfileControl;
+
+    interface Leds;
+
+    interface Random;
+    interface Init as RandomInit;
+  }
+
+}
+
+implementation {
+
+  enum {
+    // Mote states
+    STATE_INVALID     = 0x0,
+    STATE_IDLE        = 0x1,
+    STATE_CONFIGURED  = 0x2,
+    STATE_PRE_RUN     = 0x3,
+    STATE_RUNNING     = 0x4,
+    STATE_POST_RUN    = 0x5,
+    STATE_FINISHED    = 0x6,
+
+    // Sendlock states
+    UNLOCKED          = 0,
+    LOCKED            = 1,
+
+  };
+
+
+  uint8_t     state, sendlock;
+  setup_t     config;
+  message_t   pkt;
+
+  edge_t*     problem;
+  uint8_t     c_edge_cnt,c_maxmoteid;
+
+  stat_t      stats[MAX_EDGE_COUNT];
+  profile_t   profile;
+
+  // pre-computed values for faster operation
+  pending_t   tickMask_start[MAX_TIMER_COUNT];
+  pending_t   tickMask_stop [MAX_TIMER_COUNT];
+  pending_t   outgoing_edges;
+
+  // Bitmask specifying edges with pending send requests
+  pending_t pending;
+
+  // Last edge index on which we have sent message
+  uint8_t  eidx = 0xFF;
+
+  task void sendPending();
+
+  /** CLEAN THE STATE MACHINE VARIABLES **/
+  void cleanstate() {
+
+    SET_STATE( STATE_INVALID )
+
+    // Disassociate the problem
+    problem = (edge_t*)NULL;
+    c_edge_cnt = c_maxmoteid = 0;
+    outgoing_edges = 0;
+
+    // Clear configuration values
+    memset(&config,0,sizeof(setup_t));
+    memset(stats,0,sizeof(stat_t)*MAX_EDGE_COUNT);
+    memset(&profile,0,sizeof(profile_t));
+
+    memset(tickMask_start,0,sizeof(pending_t)*MAX_TIMER_COUNT);
+    memset(tickMask_stop,0,sizeof(pending_t)*MAX_TIMER_COUNT);
+
+    pending = 0x0;
+    eidx = 0xFF;
+    sendlock = UNLOCKED;
+
+    call Packet.clear(&pkt);
+    call Ack.noAck(&pkt);
+
+    SET_STATE( STATE_IDLE )
+  }
+
+  /** START THE NEEDED TRIGGERING TIMERS **/
+  void startTimers() {
+    uint8_t i;
+    uint32_t now;
+
+    for(i = 0; i< MAX_TIMER_COUNT; ++i) {
+    	// If the current timer is unused, do not start it
+    	if ( tickMask_start[i] == 0 && tickMask_stop[i] == 0 )
+    		continue;
+
+      now = call TriggerTimer.getNow[0]();
+      if ( config.timers[i].isoneshot )
+        call TriggerTimer.startOneShotAt[i](
+          now + config.timers[i].delay, config.timers[i].period_msec);
+      else
+        call TriggerTimer.startPeriodicAt[i](
+          now + config.timers[i].delay, config.timers[i].period_msec);
+    }
+  }
+
+  /** STOP THE TRIGGERING TIMERS **/
+  void stopTimers() {
+    uint8_t i;
+    for(i = 0; i< MAX_TIMER_COUNT; ++i)
+      call TriggerTimer.stop[i]();
+  }
+
+  /** INITIALIZE THE COMPONENT **/
+  command error_t Init.init() {
+    cleanstate();
+    call RandomInit.init();
+    return SUCCESS;
+  }
+
+  /** REQUEST BECHMARK RESULTS **/
+  command stat_t* BenchmarkCore.getStat(uint16_t idx) {
+    _ASSERT_( idx < MAX_EDGE_COUNT )
+    _ASSERT_( state == STATE_FINISHED )
+    _ASSERT_(idx < c_edge_cnt )
+
+    return stats + idx;
+  }
+
+  /** REQUEST PROFILE INFORMATION **/
+  command profile_t* BenchmarkCore.getProfile() {
+    return &profile;
+  }
+
+  /** REQUEST EDGE COUNT **/
+  command uint8_t BenchmarkCore.getEdgeCount() {
+    _ASSERT_( state >= STATE_CONFIGURED )
+    return c_edge_cnt;
+  }
+
+  /** REQUEST MOTE COUNT **/
+  command uint8_t BenchmarkCore.getMaxMoteId() {
+    _ASSERT_( state >= STATE_CONFIGURED )
+    return c_maxmoteid;
+  }
+
+  /** RESETS THE CORE **/
+  command void BenchmarkCore.reset() {
+    call Test.stop();
+    cleanstate();
+    signal BenchmarkCore.resetDone();
+  }
+
+  /** START THE REAL BENCHMARK */
+  void startBenchmark() {
+
+    dbg("Benchmark","BenchmarkCore startBenchmark\n");
+
+    // If this node sends initial message(s)
+    if ( pending )
+      post sendPending();
+
+    // Start the trigger timers
+    startTimers();
+
+    // Start the test timer
+    dbg("Benchmark","BenchmarkCore start TestTimer\n");
+    call TestTimer.startOneShot(config.runtime_msec);
+  }
+
+  void postNewTrigger(pending_t sbitmask) {
+    uint8_t i = 0;
+    pending_t blogd;
+
+    _ASSERT_( sbitmask > 0 )
+    _ASSERT_( state == STATE_RUNNING || state == STATE_IDLE || state ==  
STATE_POST_RUN )
+    _ASSERT_( ((~outgoing_edges) & sbitmask) == 0 )
+
+    atomic {
+      // Check which edges need to be backlogged
+      blogd = pending & sbitmask;
+      pending |= sbitmask;
+    }
+
+    // Count backlog values
+    for ( i = 0; blogd; ++i, blogd >>= 1) {
+      if ( blogd & 0x1 )
+        ++(stats[i].backlogCount);
+    }
+
+    // Count trigger values
+    for ( i = 0; sbitmask; ++i, sbitmask >>= 1) {
+      if ( sbitmask & 0x1 ) {
+        ++(stats[i].triggerCount);
+        if ( problem[i].nums.send_num == INFINITE )
+          problem[i].policy.inf_loop_on = 1;
+      }
+    }
+  }
+
+
+  /** SETUP THE BENCHMARK **/
+  command void BenchmarkCore.setup(setup_t conf) {
+    uint8_t idx;
+
+    dbg("Benchmark","BenchmarkCore.setup\n");
+
+    _ASSERT_( state == STATE_IDLE || state == STATE_CONFIGURED )
+    _ASSERT_( conf.runtime_msec > 0 );
+
+    // Do nothing if already configured or running or data is available
+    if ( state == STATE_CONFIGURED )
+      return;
+
+    // Save the configuration
+    config = conf;
+
+    // Setup the problem
+    // WARNING: This is a very dirty hack by intent. Benchmarks are  
preceded by a
+    // separator edge having sender = INVALID_SENDER and receiver =  
problem number.
+    // That separator edge we are now looking for!
+    idx = 0;
+    while ( problemSet[idx].receiver != 0 &&  // do not run past the last  
edge (PROBLEMSET_END)
+            ! ( problemSet[idx].sender == INVALID_SENDER &&
+                problemSet[idx].receiver == config.problem_idx ) ) {
+      ++idx;
+    }
+    // In case we haven't found any benchmark with the requested id, kill  
the mote.
+    if ( problemSet[idx].receiver == 0 ) {
+      SET_STATE( STATE_INVALID )
+      return;
+    } else {
+      problem = problemSet + idx + 1;
+    }
+
+    c_maxmoteid = 1;
+    // Initialize the edges
+    for( idx = 0; problem[idx].sender != INVALID_SENDER; ++idx )
+    {
+      edge_t* edge = problem + idx;
+      // Clean values that are changed during operation
+      edge->policy.inf_loop_on = 0;
+      edge->nums.left_num = edge->nums.send_num;
+      edge->nextmsgid = START_MSG_ID;
+
+      // Count the maximal mote id
+      if ( edge->sender > c_maxmoteid )
+        c_maxmoteid = edge->sender;
+      if ( edge->receiver > c_maxmoteid && edge->receiver != ALL )
+        c_maxmoteid = edge->receiver;
+
+      // If the sender is not this node, continue
+      if( edge->sender != TOS_NODE_ID )
+        continue;
+
+      // Set this bit because it is an outgoing edge from this mote
+      outgoing_edges |= 1<<idx;
+
+      // Set the pending bits if this node needs to send at start
+      if ( edge->policy.start_trigger == SEND_ON_INIT ) {
+        postNewTrigger( 1<<idx );
+
+      // Set the timer masks if this node needs to send at timer ticks
+      } else if ( edge->policy.start_trigger == SEND_ON_TIMER ) {
+        tickMask_start[edge->timers.start] |= 1 << idx;
+      }
+
+      // Set the timer masks if this node needs to stop on timer ticks
+      if ( edge->policy.stop_trigger & STOP_ON_TIMER )
+        tickMask_stop[edge->timers.stop] |= 1 << idx;
+    }
+    c_edge_cnt = idx;
+
+    SET_STATE( STATE_CONFIGURED )
+    signal BenchmarkCore.setupDone();
+  }
+
+  /** START THE CURRENTLY CONFIGURED BENCHMARK */
+  command error_t Test.start() {
+    _ASSERT_( state == STATE_CONFIGURED )
+    dbg("Benchmark","BenchmarkCore Test.start\n");
+    // Start the code profiler
+    call CodeProfileControl.start();
+
+#ifdef TRAFFIC_MONITOR
+    // save the current time.
+    profile.rtx_time = call TrafficMonitor.getActiveTime();
+    profile.rstart_count = call TrafficMonitor.getStartCount();
+    profile.rx_bytes = call TrafficMonitor.getRxBytes();
+    profile.tx_bytes = call TrafficMonitor.getTxBytes();
+    profile.rx_msgs = call TrafficMonitor.getRxMessages();
+#endif
+
+    // setup the applied MAC protocol
+#ifdef LOW_POWER_LISTENING
+    if ( config.flags & GLOBAL_USE_MAC_LPL )
+      call  
LowPowerListening.setLocalWakeupInterval(config.mac_setup[LPL_WAKEUP_OFFSET]);
+#endif
+
+#ifdef PACKET_LINK
+    if ( config.flags & GLOBAL_USE_MAC_PLINK ) {
+      call  
PacketLink.setRetries(&pkt,config.mac_setup[PLINK_RETRIES_OFFSET]);
+      call  
PacketLink.setRetryDelay(&pkt,config.mac_setup[PLINK_DELAY_OFFSET]);
+    }
+#endif
+
+    // If a pre-benchmark delay is requested, make a delay
+    if ( config.pre_run_msec > 0 ) {
+      SET_STATE ( STATE_PRE_RUN )
+      call TestTimer.startOneShot( call Random.rand32() %  
config.pre_run_msec );
+    } else {
+      SET_STATE( STATE_RUNNING )
+      startBenchmark();
+    }
+    return SUCCESS;
+  }
+
+  /** STOP A TEST */
+  command error_t Test.stop() {
+    uint8_t i = 0;
+
+    dbg("Benchmark","BenchmarkCore Test.stop\n");
+
+    _ASSERT_( state == STATE_PRE_RUN || state == STATE_RUNNING || state ==  
STATE_POST_RUN )
+
+    call TestTimer.stop();
+    SET_STATE( STATE_FINISHED );
+    stopTimers();
+
+    // cleanup the MAC
+#ifdef LOW_POWER_LISTENING
+    if ( config.flags & GLOBAL_USE_MAC_LPL )
+      call LowPowerListening.setLocalWakeupInterval(0);
+#endif
+
+#ifdef PACKET_LINK
+    if ( config.flags & GLOBAL_USE_MAC_PLINK ) {
+      call PacketLink.setRetries(&pkt,0);
+      call PacketLink.setRetryDelay(&pkt,0);
+    }
+#endif
+
+    // compute the remained statistic
+    for ( i = 0; pending; ++i, pending >>= 1) {
+      if ( pending & 0x1 )
+        ++(stats[i].remainedCount);
+    }
+
+    // Stop the code profiler
+    call CodeProfileControl.stop();
+
+    // Compute the mote-statistics
+    profile.min_atomic = call CodeProfile.getMinAtomicLength();
+    profile.min_interrupt = call CodeProfile.getMinInterruptLength();
+    profile.min_latency = call CodeProfile.getMinTaskLatency();
+
+    profile.max_atomic = call CodeProfile.getMaxAtomicLength();
+    profile.max_interrupt = call CodeProfile.getMaxInterruptLength();
+    profile.max_latency = call CodeProfile.getMaxTaskLatency();
+
+#ifdef TRAFFIC_MONITOR
+    // save the curent time.
+    profile.rtx_time = call TrafficMonitor.getActiveTime() -  
profile.rtx_time;
+    profile.rstart_count = call TrafficMonitor.getStartCount() -  
profile.rstart_count;
+    profile.rx_bytes = call TrafficMonitor.getRxBytes() - profile.rx_bytes;
+    profile.tx_bytes = call TrafficMonitor.getTxBytes() - profile.tx_bytes;
+    profile.rx_msgs = call TrafficMonitor.getRxMessages() -  
profile.rx_msgs;
+#endif
+
+    signal BenchmarkCore.finished();
+    return SUCCESS;
+  }
+
+  event void TestTimer.fired() {
+    dbg("Benchmark","BenchmarkCore TestTimer.fired\n");
+
+    switch(state) {
+
+      case STATE_PRE_RUN:
+        SET_STATE( STATE_RUNNING )
+        startBenchmark();
+        break;
+
+      case STATE_RUNNING:
+        // Stop the trigger timers
+        stopTimers();
+        // check if we need a post-run state
+        if ( config.post_run_msec > 0 ) {
+          SET_STATE( STATE_POST_RUN )
+          call TestTimer.startOneShot(config.post_run_msec);
+          break;
+        }
+        // break; missing: fallback to STATE_POST_RUN !
+
+      case STATE_POST_RUN:
+        call Test.stop();
+        break;
+
+      default:
+        _ASSERT_( 0 )
+    }
+  }
+
+  event void TriggerTimer.fired[uint8_t id]() {
+
+    // start on timer tick
+    if ( tickMask_start[id] != 0 ) {
+      postNewTrigger(tickMask_start[id]);
+      post sendPending();
+    }
+
+    // stop on timer tick
+    if ( tickMask_stop[id] != 0 ) {
+      uint8_t i = 0;
+      pending_t temp = tickMask_stop[id];
+      for ( i = 0; temp; ++i, temp >>= 1) {
+        if ( (temp & 0x1) && (problem[i].policy.stop_trigger &  
STOP_ON_TIMER) ) {
+          // This works for INFINITE and also for non-INF edges
+          problem[i].policy.inf_loop_on = 0;
+          problem[i].nums.left_num = problem[i].nums.send_num;
+        }
+      }
+    }
+
+  }
+
+  event message_t* RxTest.receive(message_t* bufPtr, void* payload,  
uint8_t len) {
+
+    testmsg_t* msg = (testmsg_t*)payload;
+    // helper variables
+    stat_t* stat = stats + msg->edgeid;
+    edge_t* edge = problem + msg->edgeid;
+
+    dbg("Benchmark","RxTest.receive\n");
+
+    // In case the message is sent to this mote (also)
+    if ( state == STATE_RUNNING || state == STATE_POST_RUN ){
+
+      ++(stat->receiveCount);
+
+      // If the message id is ok
+      if ( msg->msgid == edge->nextmsgid ) {
+        ++(stat->consecutiveCount);
+
+      } else {
+        ++(stat->wrongCount);
+
+        // If we got a message with a lower id than consecutive ->  
duplicate
+        if ( msg->msgid < edge->nextmsgid )
+          ++(stat->duplicateCount);
+        // If we got a message with a higher id than consecutive -> we  
have missed messages
+        else {
+          ++(stat->forwardCount);
+          stat->missedCount += msg->msgid - edge->nextmsgid;
+        }
+      }
+
+      // Set the next consecutive message id
+      edge->nextmsgid = msg->msgid + 1;
+
+      // Check whether we have to reply
+      if ( edge->reply_on & outgoing_edges ) {
+        // in case of "reply-to broadcast message" policy, the reply_on  
bitmask could
+        // contain edges whose source is not this mote.
+        // that is why, a filter is applied (outgoing_edges).
+        postNewTrigger(edge->reply_on & outgoing_edges );
+        post sendPending();
+      }
+    }
+    return bufPtr;
+  }
+
+  event void TxTest.sendDone(message_t* bufPtr, error_t error) {
+
+    testmsg_t* msg = (testmsg_t*)(call  
Packet.getPayload(bufPtr,sizeof(testmsg_t)));
+    bool validSend = TRUE, wasACK = FALSE, sendMore = TRUE;
+
+
+
+    // helper variables
+    stat_t* stat = stats + msg->edgeid;
+    edge_t* edge = problem + msg->edgeid;
+
+ dbg("Benchmark","TxTest.sendDone\n");
+    _ASSERT_( sendlock == LOCKED )
+    _ASSERT_( state == STATE_RUNNING || state == STATE_POST_RUN || state  
== STATE_FINISHED )
+
+    if ( state == STATE_RUNNING || state == STATE_POST_RUN ) {
+
+      _ASSERT_( edge->sender == TOS_NODE_ID )
+      _ASSERT_( pending & (1 << msg->edgeid) )
+      ++(stat->sendDoneCount);
+
+      if ( error == SUCCESS ) {
+        ++(stat->sendDoneSuccessCount);
+
+        // If ACK is not requested
+        if ( edge->policy.need_ack == 0 && (config.flags & GLOBAL_USE_ACK)  
== 0 ) {
+          ++(edge->nextmsgid);
+
+        // If ACK is requested and received
+        } else if ( call Ack.wasAcked(bufPtr) ) {
+          ++(edge->nextmsgid);
+          ++(stat->wasAckedCount);
+          wasACK = TRUE;
+
+        // Otherwise ACK requested but not received
+        } else {
+          ++(stat->notAckedCount);
+          validSend = FALSE;
+        }
+
+      } else {
+        ++(stat->sendDoneFailCount);
+        validSend = FALSE;
+      }
+
+      // If message is NOT considered to be sent
+      if ( ! validSend ) {
+        ++(stat->resendCount);
+
+      } else {
+
+        // Decrement the number of messages that are left to send
+        // and restore the original value if necessary
+        // this works for INFINITE and also for non-INF edges
+        if ( edge->nums.send_num != INFINITE && --(edge->nums.left_num) ==  
0 ) {
+          // Restore the value
+          edge->nums.left_num = edge->nums.send_num;
+          sendMore = FALSE;
+        }
+
+        // Check if we need to stop sending on ACK
+        if ( wasACK && (edge->policy.stop_trigger & STOP_ON_ACK) ) {
+            // This works for INFINITE and also for non-INF edges
+            edge->policy.inf_loop_on = 0;
+            edge->nums.left_num = edge->nums.send_num;
+            sendMore = FALSE;
+        }
+
+        // If the infinite sending loop has been stopped
+        if ( edge->nums.send_num == INFINITE && !edge->policy.inf_loop_on  
) {
+          sendMore = FALSE;
+        }
+      }
+
+      // Remove the pending bit if applicable
+      if ( !sendMore ) {
+        atomic { pending &= ~ (1 << msg->edgeid ); }
+      } else {
+        ++(stat->triggerCount);
+      }
+
+      sendlock = UNLOCKED;
+      if ( pending )
+        post sendPending();
+    }
+  }
+
+
+  task void sendPending() {
+
+    pending_t   pidx;
+    am_addr_t   address;
+    uint8_t     oldlock;
+    testmsg_t*  t_msg;
+
+    // safe locking
+    atomic{
+      oldlock = sendlock;
+      sendlock = LOCKED;
+    }
+
+
+
+
+    // In case we have any chance to send
+    if ( oldlock == UNLOCKED && state == STATE_RUNNING && pending ) {
+
+
+      dbg("Benchmark","sendPending-1\n");
+
+      // find the next edge on which there exist any request
+      do {
+        pidx = 1 << (++eidx);
+        if ( pidx == 0 ) {
+          eidx  = 0x0;
+          pidx  = 0x1;
+        }
+      } while ( !(pending & pidx) );
+
+      _ASSERT_( problem[eidx].sender == TOS_NODE_ID )
+
+      // Compose the new message
+      call Packet.clear(&pkt);
+      t_msg = (testmsg_t*)(call Packet.getPayload(&pkt,sizeof(testmsg_t)));
+      t_msg->edgeid = eidx;
+      t_msg->msgid = problem[eidx].nextmsgid;
+
+      // Find out the required addressing mode
+      address = ( config.flags & GLOBAL_USE_BCAST ) ? AM_BROADCAST_ADDR :  
problem[eidx].receiver;
+
+      dbg("Benchmark","sendPending address %d\n",address);
+
+      // MAC specific settings
+#ifdef LOW_POWER_LISTENING
+      if ( config.flags & GLOBAL_USE_MAC_LPL )
+        call LowPowerListening.setRemoteWakeupInterval(
+          &pkt,config.mac_setup[LPL_WAKEUP_OFFSET]);
+#endif
+
+#ifdef PACKET_LINK
+      if ( config.flags & GLOBAL_USE_MAC_PLINK ) {
+        call  
PacketLink.setRetries(&pkt,config.mac_setup[PLINK_RETRIES_OFFSET]);
+        call  
PacketLink.setRetryDelay(&pkt,config.mac_setup[PLINK_DELAY_OFFSET]);
+      }
+#endif
+
+      dbg("Benchmark","sendPending-2\n");
+
+      // Find out whether we need to use ACK
+      if ( (config.flags & GLOBAL_USE_ACK) ||  
problem[eidx].policy.need_ack ) {
+        call Ack.requestAck(&pkt);
+      } else {
+        call Ack.noAck(&pkt);
+      }
+
+      dbg("Benchmark","sendPending-3\n");
+
+      // Send out
+      switch ( call TxTest.send( address, &pkt, sizeof(testmsg_t)) ) {
+        case SUCCESS :
+        dbg("Benchmark","sendPending-4\n");
+          ++(stats[eidx].sendSuccessCount);
+          break;
+        case FAIL :
+        dbg("Benchmark","sendPending-5\n");
+          ++(stats[eidx].sendFailCount);
+          ++(stats[eidx].resendCount);
+          sendlock = UNLOCKED;
+          post sendPending();
+          break;
+        default :
+        dbg("Benchmark","sendPending-6\n");
+          _ASSERT_( 0 )
+          break;
+      }
+      ++(stats[eidx].sendCount);
+    }
+  }
+
+}
=======================================
--- /dev/null
+++ /trunk/apps/tests/LinkBench/Benchmarks.h	Tue Sep  6 00:34:50 2011
@@ -0,0 +1,75 @@
+/*
+* Copyright (c) 2010, University of Szeged
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* - Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* - Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* - Neither the name of University of Szeged nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+* OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Author: Krisztian Veress
+*         veresskrisztian at gmail.com
+*/
+
+#ifndef BENCHMARKS_H
+#define BENCHMARKS_H
+
+#include "BenchmarkCore.h"
+#include <AM.h>
+
+// Every benchmark can be numbered when defining it
+// This number is hidden in a separator edge right between the
+// benchmark's own edges
+#define _BMARK_START_(id)  
{INVALID_SENDER,(id),{0,0},{0,0,0,0,0},{0,0},0,0},
+#define _BMARK_END_ ,
+
+#define PROBLEMSET_END    {INVALID_SENDER,0,{0,0},{0,0,0,0,0},{0,0},0,0}
+
+#define INVALID_SENDER  AM_BROADCAST_ADDR
+#define ALL             AM_BROADCAST_ADDR
+
+#define REPLY_ON(POS) (1<<(POS))
+#define NUM(QTY) {(QTY), (QTY)}
+
+#define NO_REPLY      0
+#define START_MSG_ID  1
+#define NO_TIMER      {0,0}
+
+#define TIMER(X)      ((X)-1)
+
+edge_t problemSet[] = {
+
+#ifndef EXCLUDE_STANDARD
+#include "StandardBenchmarks.h"
+#endif
+
+#ifndef EXCLUDE_USERDEFINED
+#include "UserdefinedBenchmarks.h"
+#endif
+
+  PROBLEMSET_END
+}; // problemSet END
+
+#endif
=======================================
--- /dev/null
+++ /trunk/apps/tests/LinkBench/Makefile	Tue Sep  6 00:34:50 2011
@@ -0,0 +1,43 @@
+COMPONENT=BenchmarkAppC
+
+# MAC protocol usage
+CFLAGS += -DLOW_POWER_LISTENING
+#CFLAGS += -DPACKET_LINK
+
+# use 32-bit length statistics ? (default is 16 bits)
+#CFLAGS += -DUSE_32_BITS
+
+# the maximum edge count that is present in all benchmarks
+CFLAGS += -DMAX_EDGE_COUNT=8
+
+# exclude the standard benchmarks (or a part of it) from the problemset
+# for low-memory platforms like telosa it might be necessary
+#CFLAGS += -DEXCLUDE_STANDARD
+#CFLAGS += -DEXCLUDE_STANDARD_THROUGHPUT
+#CFLAGS += -DEXCLUDE_STANDARD_COLLISION
+#CFLAGS += -DEXCLUDE_STANDARD_FORWARDING
+
+# exclude the user defined benchmarks from the problemset
+CFLAGS += -DEXCLUDE_USERDEFINED
+
+# codeprofile, tossim support
+CFLAGS += -Icodeprofile
+CFLAGS += -Itossim
+#CFLAGS += -DTRAFFIC_MONITOR
+#CFLAGS += -I$(SZTETOSDIR)/lib/cc2420traffic
+
+# channel settings
+ifneq (,$(DEF_CHANNEL))
+	CFLAGS += -DCC2420_DEF_CHANNEL=$(DEF_CHANNEL)
+	CFLAGS += -DRF230_DEF_CHANNEL=$(DEF_CHANNEL)
+	CFLAGS += -DRFA1_DEF_CHANNEL=$(DEF_CHANNEL)
+endif
+
+ifneq (,$(findstring USE_32_BITS,$(CFLAGS)))
+  CFLAGS += -DTOSH_DATA_LENGTH=97
+else
+  CFLAGS += -DTOSH_DATA_LENGTH=90
+endif
+
+include $(MAKERULES)
+include Makefile.Pdetect
=======================================
--- /dev/null
+++ /trunk/apps/tests/LinkBench/Makefile.Pdetect	Tue Sep  6 00:34:50 2011
@@ -0,0 +1,51 @@
+# microcontroller identification
+ATM128_PLATFORMS = iris mica mica2 mica2dot micaz btnode3 ucmini ucdual  
ucmote900
+MSP430_PLATFORMS = epic eyesIFX eyesIFXv1 eyesIFXv2 shimmer shimmer2  
shimmer2r span telosa telosb tinynode z1
+PXA27X_PLATFORMS = intelmote2
+M16C62P_PLATFORMS= mulle
+CORTEX_PLATFORMS = sam3u_ek sam3s_ek
+
+ifneq ($(findstring $(PLATFORM),$(ATM128_PLATFORMS)),)
+	MCU ?= ATM128
+else ifneq ($(findstring $(PLATFORM),$(MSP430_PLATFORMS)),)
+	MCU ?= MSP430
+else ifneq ($(findstring $(PLATFORM),$(PXA27X_PLATFORMS)),)
+	MCU ?= PXA27X
+else ifneq ($(findstring $(PLATFORM),$(M16C62P_PLATFORMS)),)
+	MCU ?= M16C62P
+else ifneq ($(findstring $(PLATFORM),$(CORTEX_PLATFORMS)),)
+	MCU ?= CORTEX
+else
+	MCU ?= UNKNOWN
+endif
+CONTROLLER_$(MCU) = $(MCU)
+CFLAGS += -DCONTROLLER_$(MCU)
+
+# radio chip identification
+RFA1_PLATFORMS   = ucmini ucdual ucmote900
+RF230_PLATFORMS  = iris mulle
+CC1000_PLATFORMS = mica mica2 mica2dot btnode3
+CC2420_PLATFORMS = micaz telosa telosb shimmer shimmer2 shimmer2r epic  
span intelmote2 z1 sam3u_ek
+TDA5250_PLATFORMS= eyesIFX eyesIFXv1 eyesIFXv2
+XE1205_PLATFORMS = tinynode
+CC2520_PLATFORMS = sam3s_ek
+
+ifneq ($(findstring $(PLATFORM),$(RF230_PLATFORMS)),)
+	RCHIP ?= RF230
+else ifneq ($(findstring $(PLATFORM),$(CC1000_PLATFORMS)),)
+	RCHIP ?= CC1000
+else ifneq ($(findstring $(PLATFORM),$(CC2420_PLATFORMS)),)
+	RCHIP ?= CC2420
+else ifneq ($(findstring $(PLATFORM),$(TDA5250_PLATFORMS)),)
+	RCHIP ?= TDA5250
+else ifneq ($(findstring $(PLATFORM),$(XE1205_PLATFORMS)),)
+	RCHIP ?= XE1205
+else ifneq ($(findstring $(PLATFORM),$(CC2520_PLATFORMS)),)
+	RCHIP ?= CC2520
+else ifneq ($(findstring $(PLATFORM),$(RFA1_PLATFORMS)),)
+	RCHIP ?= RFA1
+else
+	RCHIP ?= UNKNOWN
+endif
+RADIO_$(RCHIP) = $(RCHIP)
+CFLAGS += -DRADIO_$(RCHIP)
=======================================
--- /dev/null
+++ /trunk/apps/tests/LinkBench/Messages.h	Tue Sep  6 00:34:50 2011
@@ -0,0 +1,102 @@
+/*
+* Copyright (c) 2010, University of Szeged
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* - Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* - Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* - Neither the name of University of Szeged nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+* OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Author: Krisztian Veress
+*         veresskrisztian at gmail.com
+*/
+
+#ifndef MESSAGES_H
+#define MESSAGES_H
+
+#include "BenchmarkCore.h"
+
+enum {
+  // AM Type identifiers
+
+  AM_TESTMSG_T      = 101,
+
+  AM_CTRLMSG_T      = 102,
+  AM_SYNCMSG_T      = 103,
+  AM_SETUPMSG_T     = 104,
+
+  AM_DATAMSG_T      = 105,
+
+  // Control / Response message types
+  SETUP_BASE        = 0,
+
+  CTRL_SETUP_SYN    = 5,
+  SYNC_SETUP_ACK    = 6,
+
+  CTRL_START        = 10,
+  CTRL_RESET        = 20,
+
+  CTRL_STAT_REQ     = 30,
+  DATA_STAT_OK      = 31,
+
+  CTRL_PROFILE_REQ  = 40,
+  DATA_PROFILE_OK   = 41
+};
+
+
+typedef nx_struct testmsg_t {
+  nx_uint8_t    edgeid;           // On which edge this message is  
intended to propagate through
+  nx_seq_base_t msgid;            // The auto-increment id of the message  
on the preset edge
+} testmsg_t;
+
+
+typedef nx_struct ctrlmsg_t {
+  nx_uint8_t    type;             // Control type
+  nx_uint8_t    data_req_idx;     // The requested stat-edge pair index in  
the requesting stage
+} ctrlmsg_t;
+
+typedef nx_struct syncmsg_t {
+  nx_uint8_t    type;
+  nx_uint8_t    edgecnt;          // How many edges are in the current  
benchmark?
+  nx_uint8_t    maxmoteid;        // How many motes are in the current  
benchmark?
+} syncmsg_t;
+
+typedef nx_struct setupmsg_t {
+  nx_uint8_t    type;
+  setup_t       config;
+} setupmsg_t;
+
+typedef nx_struct datamsg_t {
+  nx_uint8_t    type;             // Response type
+  nx_uint8_t    data_idx;         // The requested stat-edge pair index in  
the requesting stage
+  nx_union {
+    stat_t      stat;             // The requested stat structure in the  
requesting stage
+    profile_t   profile;          // The profile of the mote
+  } payload;
+} datamsg_t;
+
+
+#endif
+
=======================================
--- /dev/null
+++ /trunk/apps/tests/LinkBench/README	Tue Sep  6 00:34:50 2011
@@ -0,0 +1,148 @@
+LinkBench application README
+
+1. Authors/Contacts:
+   -----------------
+   veresskrisztian at gmail.com (Krisztian Veress, SZTE University, Szeged,  
Hungary )
+
+2. Description:
+   ------------
+   This application's main goal is to provide a universal framework that  
is able to
+   conduct reproducible tests/benchmarks in order to analyze and measure  
the radio-
+   communication generated by the applied benchmark.
+
+   The focus is on the radiocommunication, hence benchmarks are given by  
communica-
+   tion links in a directed graph representation. For specifying  
benchmarks, see
+   UserdefinedBenchmarks.h.
+
+3. TinyOS network requirements:
+   ----------------------------
+   To use the framework, one needs
+    - a BaseStation mote with TOS_NODE_ID = 0.
+      WARNING! When programming the BaseStation TOSH_DATA_LENGTH must be  
set to 110!
+
+    - multiple 'test motes' with TOS_NODE_IDs 1,2,3, ... based on the  
required mote
+      count of the benchmark to be run
+
+   One should take note that mote's channels are set to the same value  
(based on the
+   DEF_CHANNEL env variable), so when using different radio chips, compile  
time de-
+   finitions such as
+    -DRF230_DEF_CHANNEL  = $(DEF_CHANNEL), and
+    -DCC2420_DEF_CHANNEL = $(DEF_CHANNEL), ...
+
+   are preset in the Makefile. To change this channel, set the DEF_CHANNEL  
variable
+   to the required number:
+     - in Unix systems : export DEF_CHANNEL=22
+     - in Windows      : set DEF_CHANNEL=22
+
+4. Quick Install Guide:
+   --------------------
+    a, Connect one mote the your PC, and program it to be a BaseStation.
+       Check on which port it is connected ( with motelist for example),  
and remember it.
+    b, Connect as much motes as you would like to program to be  
benchmark 'test motes'.
+    c, Either program them as you like, or execute the minstall.sh script:
+       ./minstall.sh -i /dev/ttyUSBX
+       where /dev/ttyUSBX is the device on which the BaseStation lives.
+    d, Go to the javasrc directory and type:
+       ant
+       This will compile and assemble the Java sources.
+    e, Got to the javabin directory created by the previous command, and  
execute:
+       chmod +x *.sh
+       ./linkbench.sh --help
+
+4. Programming the motes:
+   ----------------------
+   To program the 'test motes', simply execute the make command with  
appropriate options.
+   Examples:
+    - iris mote connected to MIB510 programmer on the first USB slot,  
assign TOS_NODE_ID=1
+    Unix   : make iris install,1 mib510,/dev/ttyUSB0
+    Windows: make iris install,1 mib510,COM1
+
+    - telosa/telosb motes, assign TOS_NODE_ID=2 and 3
+             make telosa install,2
+             make telosb install,3
+    - ...
+
+    4./a 32-bit statistics support:
+         --------------------------
+         Statistics are generally 16-bit integers. If overflows are  
experienced, you should
+         consider setting the USE_32_BITS compile-time flag in the  
Makefile:
+         CFLAGS += -DUSE_32_BITS
+
+    4./b Defining and using benchmarks:
+         ------------------------------
+         To define your own benchmarks, do it in the  
UserdefinedBenchmarks.h file where
+         additional information is available on how you can do that. After  
doing that,
+         count the maximum of edges used in all your benchmarks, and set  
it in the Makefile:
+         CFLAGS += -DMAX_EDGE_COUNT=8
+
+         You can exclude benchmark sets by setting the EXCLUDE_STANDARD or
+         EXCLUDE_USERDEFINED flag in the Makefile.
+
+5. Compiling the PC program:
+   -------------------------
+    The application comes shipped with a PC-based control program located  
in the javasrc
+    directory. The program depends on the tinyos.jar (TinyOS Java  
components) file, which
+    comes with your TinyOS development libraries.
+
+    In order to successfully compile, the code needs mig-generated  
classes, so make sure
+    you have made a 'make <target>' for any target before compiling Java  
sources. Also you
+    gonna need the ant (at least 1.7) utility which is a make system for  
Java.
+
+    If everything is prepared, just type:
+      ant
+    in the javasrc directory. This will create a javabin directory in the  
root directory
+    of the project.
+
+    Then, executing either of the followings in the javabin folder:
+      java -jar linkbench.jar --help
+      sh linkbench.sh --help
+      ./linkbench --help          (if you have chmod-ed linkbench.sh to be  
executable)
+    which will give you details on how this application can be used.
+
+6. Using the application:
+   ----------------------
+   To use the application, power-on all programmed 'test-motes', plug in  
the BaseStation
+   mote to your PC, and set the MOTECOM variable to point to the  
BaseStation mote.
+   Examples:
+    - iris BaseStation mote connected to MIB510 programmer on the first  
USB slot
+      export MOTECOM=serial@/dev/ttyUSB1:iris
+    - telosb BaseStation mote connected on the second USB slot
+      export MOTECOM=serial@/dev/ttyUSB2:telosb
+
+   Then, execute the following:
+     java -jar linkbench.jar -b 10
+     ./linkbench -b 10
+   which will eventually execute the 0th benchmark, and print the results  
on your screen.
+   For more options, see
+     java -jar linkbench.jar --help
+     ./linkbench --help
+
+7. Status indicators on 'test-motes':
+   ----------------------------------
+   The code is written in a way so that the status of each 'test mote' can  
be tracked
+   during the whole process.
+    0. All LEDs   off : motes are in invalid state. This can only occur if  
you specify a
+                        benchmark to be run that is not available in the  
benchmark database.
+                        Do not worry, just reset them (java Benchmark -r),  
or simply run a
+                        benchmark which is available.
+    1. LED 1       on : mote is reset, standing by, waits for running a  
benchmark.
+    2. LED 2       on : mote received configuration, waits for handshake  
with the PC program
+    3. LED 1,LED 2 on : mote successfully configured, handshake is done
+    4. LED 3       on : benchmark is currently running
+    5. LED 3,LED 1 on : mote is in so-called 'lastchance' state -- being a  
pre-stop phase of
+                        the benchmark
+    6. LED 3,LED 2 on : mote finished the benchmark, statistics are ready
+    7. LED 3,LED 2 on : mote is uploading values to PC
+
+   Motes should not be in states 2,3 and 5 for LONG TIME, if it happens,  
you can reset them
+   by invoking either of the followings:
+     java -jar linkbench.jar
+     ./linkbench -r
+
+   ( Note that this will reset ALL motes! )
+
+8. Known limitations:
+   ----------------
+   - Configuration and data uploading is done in a one-hop manner,  
so 'test-motes' must be in the radio
+     reception range of the BaseStation.
+
=======================================
--- /dev/null
+++ /trunk/apps/tests/LinkBench/StandardBenchmarks.h	Tue Sep  6 00:34:50  
2011
@@ -0,0 +1,272 @@
+/**
+ * Standard Benchmark Database file
+ * ------------------------------------------------------------------------
+ * This is a no-modify file, keep it untouched.
+ */
+
+
+/* Throughput problems
+ * ----------------------
+ *
+ * In these problems, edges are present with continous message sending  
policies
+ * meaning that motes try to send messages as fast as they can.
+ * Such edges next to each other influence each other's behaviour.
+ *
+ * All of these benchmarks can be run with 4 motes (not all requires 4).
+ */
+
+#ifndef EXCLUDE_STANDARD_THROUGHPUT
+
+/** One-edge throughput **/
+_BMARK_START_(10)
+  { 1, 2, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID }
+_BMARK_END_
+
+/** Two-edge throughput **/
+_BMARK_START_(11)
+  { 1, 2, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID },
+  { 2, 1, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID }
+_BMARK_END_
+
+/** Three-edge, circle-style throughput **/
+_BMARK_START_(12)
+  { 1, 2, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID },
+  { 2, 3, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID },
+  { 3, 1, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID }
+_BMARK_END_
+
+/** One broadcast flooding mote **/
+_BMARK_START_(13)
+  { 4, ALL, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID }
+_BMARK_END_
+
+/** Two broadcast flooding motes **/
+_BMARK_START_(14)
+  { 4, ALL, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID },
+  { 3, ALL, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID }
+_BMARK_END_
+
+/** Three broadcast flooding motes **/
+_BMARK_START_(15)
+  { 4, ALL, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID },
+  { 3, ALL, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID },
+  { 2, ALL, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID }
+_BMARK_END_
+
+/** Two parallel throughput links **/
+_BMARK_START_(16)
+  { 1, 2, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID },
+  { 3, 4, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID }
+_BMARK_END_
+
+/** Two parallel throughput links, one with ACK request**/
+_BMARK_START_(17)
+  { 1, 2, NO_TIMER , { SEND_ON_INIT,  0, NEED_ACK, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID },
+  { 3, 4, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID }
+_BMARK_END_
+
+/** One throughput link next to one broadcast flooding mote **/
+_BMARK_START_(18)
+  { 1, 2, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID },
+  { 3, ALL, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID }
+_BMARK_END_
+
+/** Hidden terminal problem (2 motes flooding the same mote) **/
+_BMARK_START_(19)
+  { 1, 2, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID },
+  { 3, 2, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID }
+_BMARK_END_
+
+/** Hidden terminal problem (3 motes flooding the same mote) **/
+_BMARK_START_(20)
+  { 1, 4, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID },
+  { 2, 4, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID },
+  { 3, 4, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID }
+_BMARK_END_
+
+#endif // EXCLUDE_STANDARD_THROUGHPUT
+
+/* Collision problems
+ * ----------------------
+ *
+ * In these problems, communication is based on timers. Since all 4 timers  
that
+ * are supported can be highly customized, different timer configurations  
could
+ * result different scenarios.
+ * If the sending windows match, collision occur, thus the name of these  
benchmarks.
+ *
+ * All of these benchmarks can be run with 4 motes.
+ */
+
+#ifndef EXCLUDE_STANDARD_COLLISION
+
+/** Two parallel timer-based links **/
+_BMARK_START_(30)
+  { 1, 2, {TIMER(1), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID },
+  { 3, 4, {TIMER(2), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID }
+_BMARK_END_
+
+/** Two parallel timer-based links, broadcasting **/
+_BMARK_START_(31)
+  { 4, ALL, {TIMER(1), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1),  
NO_REPLY, START_MSG_ID },
+  { 3, ALL, {TIMER(2), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1),  
NO_REPLY, START_MSG_ID }
+_BMARK_END_
+
+/** Three parallel timer-based links, broadcasting **/
+_BMARK_START_(32)
+  { 4, ALL, {TIMER(1), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1),  
NO_REPLY, START_MSG_ID },
+  { 3, ALL, {TIMER(2), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1),  
NO_REPLY, START_MSG_ID },
+  { 2, ALL, {TIMER(3), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1),  
NO_REPLY, START_MSG_ID }
+_BMARK_END_
+
+/** Three parallel timer-based links, direct links **/
+_BMARK_START_(33)
+  { 1, 2, {TIMER(1), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID },
+  { 2, 3, {TIMER(2), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID },
+  { 3, 4, {TIMER(3), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID }
+_BMARK_END_
+
+/** Three timer-based links having a common destination **/
+_BMARK_START_(34)
+  { 1, 4, {TIMER(1), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID },
+  { 2, 4, {TIMER(2), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID },
+  { 3, 4, {TIMER(3), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID }
+_BMARK_END_
+
+/** One timer-based link influenced by a parallel flooding link **/
+_BMARK_START_(35)
+  { 1, 2, {TIMER(1), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID },
+  { 3, 4, NO_TIMER, { SEND_ON_INIT, 0, 0, 0, 0 }, NUM(INFINITE), NO_REPLY,  
START_MSG_ID }
+_BMARK_END_
+
+/** One timer-based link influenced by a parallel flooding link  
(broadcast) **/
+_BMARK_START_(36)
+  { 1, 2, {TIMER(1), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID },
+  { 4, ALL, NO_TIMER, { SEND_ON_INIT, 0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID }
+_BMARK_END_
+
+#endif // EXCLUDE_STANDARD_COLLISION
+
+/* Forwarding problems
+ * ----------------------
+ *
+ * In these problems, communication initiation is based on timers.  
Additionally, networks
+ * are created such a way that messages are to be forwarded, so if any  
mote hears a message,
+ * it should forward it on at least one link.
+ *
+ * All of these benchmarks can be run with 6 motes (not all requires 6).
+ */
+
+#ifndef EXCLUDE_STANDARD_FORWARDING
+
+/** M2 forwards to M1 what it hears from M1 **/
+_BMARK_START_(50)
+  { 1, 2, {TIMER(1), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1),  
REPLY_ON(1), START_MSG_ID },
+  { 2, 1, NO_TIMER, { SEND_ON_REQ, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID }
+_BMARK_END_
+
+/** M2 forwards to M1 what it hears from M1.
+    Also, a flooding broadcast disturbance edge is present. **/
+_BMARK_START_(51)
+  { 1, 2, {TIMER(1), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1),  
REPLY_ON(1), START_MSG_ID },
+  { 2, 1, NO_TIMER, { SEND_ON_REQ, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID },
+  { 4, ALL, NO_TIMER, { SEND_ON_INIT, 0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID }
+_BMARK_END_
+
+/** A message chain with 4 motes. M1 initiates, M2,M3 forwards to a sink  
mote, M4. **/
+_BMARK_START_(52)
+  { 1, 2, {TIMER(1), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1),  
REPLY_ON(1), START_MSG_ID },
+  { 2, 3, NO_TIMER, { SEND_ON_REQ, 0, 0, 0, 0 }, NUM(1), REPLY_ON(2),  
START_MSG_ID },
+  { 3, 4, NO_TIMER, { SEND_ON_REQ, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID }
+_BMARK_END_
+
+/** A message chain with 6 motes. M1 initiates, M2,M3,M4,M5 forwards to a  
sink mote, M6. **/
+_BMARK_START_(53)
+  { 1, 2, {TIMER(1), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1),  
REPLY_ON(1), START_MSG_ID },
+  { 2, 3, NO_TIMER, { SEND_ON_REQ, 0, 0, 0, 0 }, NUM(1), REPLY_ON(2),  
START_MSG_ID },
+  { 3, 4, NO_TIMER, { SEND_ON_REQ, 0, 0, 0, 0 }, NUM(1), REPLY_ON(3),  
START_MSG_ID },
+  { 4, 5, NO_TIMER, { SEND_ON_REQ, 0, 0, 0, 0 }, NUM(1), REPLY_ON(4),  
START_MSG_ID },
+  { 5, 6, NO_TIMER, { SEND_ON_REQ, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID }
+_BMARK_END_
+
+/** Two distinct, parallel forwarding chains: M1->M2->M3 and M4->M5->M6.  
**/
+_BMARK_START_(54)
+  { 1, 2, {TIMER(1), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1),  
REPLY_ON(1), START_MSG_ID },
+  { 2, 3, NO_TIMER, { SEND_ON_REQ, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID },
+  { 4, 5, {TIMER(2), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1),  
REPLY_ON(3), START_MSG_ID },
+  { 5, 6, NO_TIMER, { SEND_ON_REQ, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID }
+_BMARK_END_
+
+/** A "message collector" binary tree:
+    M1, M2 transmits to M4, M4 forwards these messages to M5.
+    M3 also transmits to M5.
+    M5 forwards those messages that are heared either from M4 or M3 to M6.
+ **/
+_BMARK_START_(55)
+  { 1, 4, {TIMER(1), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1),  
REPLY_ON(3), START_MSG_ID },
+  { 2, 4, {TIMER(2), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1),  
REPLY_ON(3), START_MSG_ID },
+  { 3, 5, {TIMER(3), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1),  
REPLY_ON(4), START_MSG_ID },
+  { 4, 5, NO_TIMER, { SEND_ON_REQ, 0, 0, 0, 0 }, NUM(1), REPLY_ON(4),  
START_MSG_ID },
+  { 5, 6, NO_TIMER, { SEND_ON_REQ, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID }
+_BMARK_END_
+
+/** A "noisy message collector" binary tree:
+    M1, M2 transmits to M4, M4 forwards these messages to M5.
+    M3 also transmits to M5.
+    M6 acts as a disturbance mote, continously broadcasting.
+ **/
+_BMARK_START_(56)
+  { 1, 4, {TIMER(1), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1),  
REPLY_ON(3), START_MSG_ID },
+  { 2, 4, {TIMER(2), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1),  
REPLY_ON(3), START_MSG_ID },
+  { 3, 5, {TIMER(3), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID },
+  { 4, 5, NO_TIMER, { SEND_ON_REQ, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID },
+  { 6, ALL, NO_TIMER, { SEND_ON_INIT, 0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID }
+_BMARK_END_
+
+/** A near complete binary tree message collector network.
+    There are three chains :  M1 -> M4 -> M6,  M2 -> M5 -> M6, and M3 ->  
M5 -> M6.
+ **/
+_BMARK_START_(57)
+  { 1, 4, {TIMER(1), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1),  
REPLY_ON(3), START_MSG_ID },
+  { 2, 5, {TIMER(2), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1),  
REPLY_ON(4), START_MSG_ID },
+  { 3, 5, {TIMER(3), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1),  
REPLY_ON(4), START_MSG_ID },
+  { 4, 6, NO_TIMER, { SEND_ON_REQ, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID },
+  { 5, 6, NO_TIMER, { SEND_ON_REQ, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID }
+_BMARK_END_
+
+/** A "message disseminator" binary tree:
+    M6 transmits to M5 which duplicates these messages towards M4 and M3.  
M3 is a sink, while
+    M4 also forwards the messages to M1 and M2.
+ **/
+_BMARK_START_(58)
+  { 6, 5, {TIMER(1), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1),  
REPLY_ON(1) | REPLY_ON(2), START_MSG_ID },
+  { 5, 4, NO_TIMER, { SEND_ON_REQ, 0, 0, 0, 0 }, NUM(1), REPLY_ON(3) |  
REPLY_ON(4), START_MSG_ID },
+  { 5, 3, NO_TIMER, { SEND_ON_REQ, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID },
+  { 4, 1, NO_TIMER, { SEND_ON_REQ, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID },
+  { 4, 2, NO_TIMER, { SEND_ON_REQ, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID }
+_BMARK_END_
+
+/** A "noisy message disseminator" binary tree:
+    M5 sends messages to M4 and M3. M3 is a sink, while M4 forwards the  
messages to M1 and M2.
+    M6 acts as a disturbance mote, continously broadcasting.
+ **/
+_BMARK_START_(59)
+  { 5, 4, {TIMER(1), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1),  
REPLY_ON(2) | REPLY_ON(3), START_MSG_ID },
+  { 5, 3, {TIMER(2), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID },
+  { 4, 1, NO_TIMER, { SEND_ON_REQ, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID },
+  { 4, 2, NO_TIMER, { SEND_ON_REQ, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID },
+  { 6, ALL, NO_TIMER, { SEND_ON_INIT, 0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID }
+_BMARK_END_
+
+/** A near complete binary tree message dissemination network.
+    There are three chains :  M6 -> M4 -> M1,  M6 -> M5 -> M2, and M6 ->  
M5 -> M3.
+ **/
+_BMARK_START_(60)
+  { 6, 4, {TIMER(1), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1),  
REPLY_ON(2), START_MSG_ID },
+  { 6, 5, {TIMER(2), 0}, { SEND_ON_TIMER, 0, 0, 0, 0 }, NUM(1),  
REPLY_ON(3) | REPLY_ON(4), START_MSG_ID },
+  { 4, 1, NO_TIMER, { SEND_ON_REQ, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID },
+  { 5, 2, NO_TIMER, { SEND_ON_REQ, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID },
+  { 5, 3, NO_TIMER, { SEND_ON_REQ, 0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID }
+_BMARK_END_
+
+#endif // EXCLUDE_STANDARD_FORWARDING
+
=======================================
--- /dev/null
+++ /trunk/apps/tests/LinkBench/UserdefinedBenchmarks.h	Tue Sep  6 00:34:50  
2011
@@ -0,0 +1,197 @@
+/**
+ * User Defined Benchmark Database file
+ * ------------------------------------------------------------------------
+ *
+ * This is a user-modifiable file, keep it clean, and stay to the rules  
below.
+ *
+ * Instructions for how to define a benchmark:
+ *  1, All benchmarks MUST begin with a _BMARK_START_(X) macro, where X is  
its unique identifier.
+ *     Note that if multiple benchmarks have the same id, only the first  
is seen by the program,
+ *     others are ignored -- thus only eating expensive memory.
+ *     Valid ids are from [200,...,255], lower values are reserved for  
standard benchmarks.
+ *
+ *  2, All benchmarks MUST end with a _BMARK_END_ macro.
+ *  3, Between these macros, the edges (allowed communication links  
between two)
+ *     separate motes) of the modeled network are enlisted.
+ *
+ *     Each edge is a 7-element structure :
+ *     { SENDER, RECEIVER, TIMER_DESC, POLICY_DESC, MSG_COUNT,  
REPLY, 'START_MSG_ID' }
+ *
+ *  4, SENDER:    - any positive number, denoting the mote id
+ *     RECEIVER:  - any positive number other than the sender, denoting  
the mote id,
+ *                - 'ALL', denoting all motes. This automatically implies
+ *                   that on this edge, broadcasting is used
+ *
+ *     TIMER_DESC:
+ *                - 'NO_TIMER', if timers are not used on this edge
+ *                - {START_TIMER_DESC, STOP_TIMER_DESC} otherwise
+ *
+ *     START_TIMER_DESC:
+ *     STOP_TIMER_DESC:
+ *                - '0', if sending/stopping is not initiated by a timer
+ *                - 'TIMER(X)', representing the Xth timer, ex: TIMER(2)
+ *
+ *     POLICY_DESC:
+ *                - { SEND_TRIG, STOP_TRIG, ACK, 0, 0 }
+ *     SEND_TRIG: - 'SEND_ON_REQ', to send only if implicitly required  
(see below)
+ *                - 'SEND_ON_INIT', to send message on benchmark start,
+ *                - 'SEND_ON_TIMER', to send message on timer event (
+ *                  see START_TIMER_DESC)
+ *     STOP_TRIG: - '0', if no message sending stopper is required
+ *                - 'STOP_ON_ACK', if message sending is required to stop  
on an ACK
+ *                - 'STOP_ON_TIMER', if message sending is req. to stop on  
a timer event (
+ *                  see STOP_TIMER_DESC)
+ *     ACK:       - '0', if acknowledgements are not requested
+ *                - 'NEED_ACK', if acknowledgements are requested
+ *
+ *     MSG_COUNT: - NUM(X), denoting X message(s) to send, where X can be  
from [1,..,255].
+ *                - NUM(INFINITE), denoting continous message sending.
+ *
+ *     REPLY:     - 'NO_REPLY', if message is not required to send on  
reception
+ *                - 'REPLY_EDGE(X)', if message is to send on reception on  
edge X.
+ *                - 'REPLY_EDGE(X) | REPLY_EDGE(Y) | ...', if message is  
to send on reception
+ *                   on edge X AND on edge Y also.
+ *                   (the edge ids count from zero in the current  
benchmark)
+ *
+ * By specifying the edges, the required mote count is implicitly  
determined by the maximal mote id
+ * present either in the sender or receiver sections of the edge  
descriptions. (This can aslo be
+ * overridden with a command line option (-mc) of the PC program. )
+ *
+ * In the following example, the implied mote count is 1:
+ * _BMARK_START_(202)
+ *  { 1, ALL, NO_TIMER , ... }
+ * _BMARK_END_
+ *
+ * However, if someone would like to increase this number (ex. to 4),  
there is a naughty trick:
+ * _BMARK_START_(202)
+ *  { 4, ALL, NO_TIMER , ... }
+ * _BMARK_END_
+ *
+ * You are encouraged to use this motecount-force, rather than depending  
on the command-line option.
+ *
+ * For complete examples, see the demo benchmarks below.
+ * These benchmarks are only for demo and reference purposes, so do not  
hesitate to erase them / comment them out to reduce the memory overhead.
+ *
+ */
+
+// Send 10 messages (Mote1 -> Mote 2) when the test starts, and that's it.
+_BMARK_START_(200)
+  { 1, 2, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(10), NO_REPLY,  
START_MSG_ID }
+_BMARK_END_
+
+// Send 10 messages (Mote2 -> Mote 1) when the test starts, and that's it.
+_BMARK_START_(201)
+  { 2, 1, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(10), NO_REPLY,  
START_MSG_ID }
+_BMARK_END_
+
+/* Send 10 broadcast messages when the test starts.
+ * Note: try this benchmark with different motecount options on the PC side
+ *  - if motecount is set to 1 (default for this benchmark), no reception  
is seen in receiver side stats,
+ *  - if motecount is set to 2 (-mc 2): 10 reception (Mote 2 is now  
present, hearing Mote 1),
+ *  - if motecount is set to 5 (-mc 5): 40 reception (Mote 2,3,4,5 are  
present, hearing Mote 1),
+ *  - ...
+ */
+_BMARK_START_(202)
+  { 1, ALL, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(10), NO_REPLY,  
START_MSG_ID }
+_BMARK_END_
+
+// Send 10 messages when the test starts, and request acks.
+_BMARK_START_(203)
+  { 1, 2, NO_TIMER , { SEND_ON_INIT,  0, NEED_ACK, 0, 0 }, NUM(10),  
NO_REPLY, START_MSG_ID }
+_BMARK_END_
+
+// Send a message and request ack for it. If not acked, fallback at most 5  
times.
+_BMARK_START_(204)
+  { 1, 2, NO_TIMER , { SEND_ON_INIT, STOP_ON_ACK, NEED_ACK, 0, 0 },  
NUM(5), NO_REPLY, START_MSG_ID }
+_BMARK_END_
+
+// Mote 1 sends 3 messages to Mote 2.
+// Mote 2 sends messages to Mote1, stops when ack received and sends at  
most 7 messages if no ack received.
+_BMARK_START_(205)
+  { 1, 2, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(3), NO_REPLY,  
START_MSG_ID },
+  { 2, 1, NO_TIMER , { SEND_ON_INIT,  STOP_ON_ACK, NEED_ACK, 0, 0 },  
NUM(7), NO_REPLY, START_MSG_ID }
+_BMARK_END_
+
+// Start sending continously messages when the test starts. Message  
sending stops when the test stops.
+_BMARK_START_(206)
+  { 1, 2, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID }
+_BMARK_END_
+
+/**
+ * Mote 1 starts contin. sending msgs to Mote 2 when the test starts. (1st  
edge)
+ * Also Mote 1 is sending cont. broadcast msgs. (2nd edge)
+ * Mote 3 sends at most 100 messages to Mote 1, request acks, and if it  
receives an ack, stops. (3rd edge)
+ *
+ * Note that this way the broadcast messages (2nd edge) are heared by Mote  
2 and Mote 3, so the receiver side
+ * statistics will be the double of the sender side ones on the 2nd edge.  
(Since every broadcast message sent by Mote 1 is heared by two motes!)
+ */
+_BMARK_START_(207)
+  { 1, 2  , NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID },
+  { 1, ALL, NO_TIMER , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(INFINITE),  
NO_REPLY, START_MSG_ID },
+  { 3, 1  , NO_TIMER , { SEND_ON_INIT,  STOP_ON_ACK, 0, 0, 0 }, NUM(100),  
NO_REPLY, START_MSG_ID }
+_BMARK_END_
+
+// Send one message on every timer tick. Timer1 is used.
+_BMARK_START_(208)
+  { 1, 2, {TIMER(1),0} , { SEND_ON_TIMER,  0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID }
+_BMARK_END_
+
+/* 1st edge: Send at most 10 messages on every timer tick. If ack  
received, stop sending. Timer1 is used.
+ * 2nd edge: Send one broadcast message to every node when Timer2 tickens.
+ */
+_BMARK_START_(209)
+  { 1, 2, {TIMER(1),0} , { SEND_ON_TIMER,  STOP_ON_ACK, 0, 0, 0 },  
NUM(10), NO_REPLY, START_MSG_ID },
+  { 1, ALL, {TIMER(2),0} , { SEND_ON_TIMER,  0, 0, 0, 0 }, NUM(1),  
NO_REPLY, START_MSG_ID }
+_BMARK_END_
+
+/* Start cont. sending messages on every timer tick of Timer1, and stop  
sending if Timer2 tickens.
+ * By changing the type (oneshot/periodic) and frequency of the timers,  
different traffic patterns are
+ * likely to be generated.
+ */
+_BMARK_START_(210)
+  { 1, 2, {TIMER(1),TIMER(2)} , { SEND_ON_TIMER,  STOP_ON_TIMER, 0, 0, 0  
}, NUM(INFINITE), NO_REPLY, START_MSG_ID }
+_BMARK_END_
+
+/* Mote 1 sends 3 messages on every timer tick of Timer1.
+ * Mote 2 starts cont. sending messages when the test starts and stops it  
if Timer2 tickens
+ * or receives an ack, whichever comes first.
+ */
+_BMARK_START_(211)
+  { 1, 2, {TIMER(1), 0} , { SEND_ON_TIMER,  0, 0, 0, 0 }, NUM(3),  
NO_REPLY, START_MSG_ID },
+  { 2, 1, {0,TIMER(2)} , { SEND_ON_INIT,  STOP_ON_TIMER | STOP_ON_ACK , 0,  
0, 0 }, NUM(INFINITE), NO_REPLY, START_MSG_ID }
+_BMARK_END_
+
+/* Mote 1 sends 2 messages to Mote 2 on every Timer1 ticks. It stops (only  
sends one message) if Mote 2
+ * acknowledges the message.
+ * If Mote 2 hears a message, it replies on edge 1 ( see REPLY_ON(1) of  
the 1st edge ), which means it
+ * will send one message to Mote 3 (2nd edge).
+ * Since REPLY_ON(2) is present in the 2nd edge, every time Mote 3 hears a  
message, it should reply on the
+ * 3rd edge: sends one message to Mote 1.
+ */
+_BMARK_START_(212)
+  { 1, 2,   {TIMER(1),0}, { SEND_ON_TIMER,  STOP_ON_ACK, 0, 0, 0 },  
NUM(2), REPLY_ON(1), START_MSG_ID },
+  { 2, 3,   NO_TIMER , { SEND_ON_REQ,  0, 0, 0, 0 }, NUM(1), REPLY_ON(2),  
START_MSG_ID },
+  { 3, 1,   NO_TIMER , { SEND_ON_REQ,  0, 0, 0, 0 }, NUM(1), NO_REPLY,  
START_MSG_ID }
+_BMARK_END_
+
+/* 1st edge : Mote 1 -> Mote 2: Exactly 2 messages on Timer1 ticks,  
request acks.
+ *  - every time Mote 2 hears a message from this edge, it should reply on  
the 3rd edge ( see REPLY_ON(2) )
+ * 2nd edge : Mote 3 -> Mote 2: One message on every Timer2 ticks, stop  
either on Timer3 ticks or on acks.
+ *  - note that in this case the STOP_ON_X policies are useless, since
+ *    on this edge only one message is to be sent, so no use to 'stop'  
it...
+ *  - every time Mote 2 hears a message from this edge, it should reply on  
the 3rd edge ( see REPLY_ON(2) )
+ * 3rd edge : Mote 2 broadcasts exactly one message.
+ *  - if anyone (Mote 1,Mote 3) hears it, it should reply on the 4th edge  
( REPLY_ON(3) ). Since the 4th edge's
+ *    sender is 3, this only applies for Mote 3.
+ * 4th edge : Mote 3 -> Mote 1: Exactly 4 messages to transmit.
+ *  - note that this edge has SEND_ON_INIT, so 4 messages are also  
transmitted when the test starts,
+ *    not just when Mote 3 replies for messages it gets on the 3rd edge!
+ */
+_BMARK_START_(213)
+  { 1, 2,   {TIMER(1),0}, { SEND_ON_TIMER, 0, NEED_ACK, 0, 0 }, NUM(2),  
REPLY_ON(2), START_MSG_ID },
+  { 3, 2,   {TIMER(2),TIMER(3)}, { SEND_ON_TIMER, STOP_ON_TIMER |  
STOP_ON_ACK, 0, 0, 0 }, NUM(1), REPLY_ON(2), START_MSG_ID },
+  { 2, ALL, NO_TIMER    , { SEND_ON_REQ,  0, 0, 0, 0 }, NUM(1),  
REPLY_ON(3), START_MSG_ID },
+  { 3, 1,   NO_TIMER    , { SEND_ON_INIT,  0, 0, 0, 0 }, NUM(4) ,  
NO_REPLY, START_MSG_ID }
+_BMARK_END_
+
+
=======================================
--- /dev/null
+++ /trunk/apps/tests/LinkBench/codeprofile/CodeProfile.nc	Tue Sep  6  
00:34:50 2011
@@ -0,0 +1,62 @@
+/*
+* Copyright (c) 2010, University of Szeged
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* - Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* - Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* - Neither the name of University of Szeged nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+* OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Author: Krisztian Veress
+*         veresskrisztian at gmail.com
+*/
+
+interface CodeProfile {
+
+  /**
+    * Retrieve the longest/shortest interrupt handling time in microseconds
+    *
+    * @return the maximum/minimum value
+    */
+  command int32_t getMaxInterruptLength();
+  command int32_t getMinInterruptLength();
+
+  /**
+    * Retrieve the longest/shortest atomic section's time in microseconds
+    *
+    * @return the maximum/minimum value
+    */
+  command int32_t getMaxAtomicLength();
+  command int32_t getMinAtomicLength();
+
+  /**
+    * Retrieve the maximum/minimum elapsed time in microseconds between  
two task.
+    *
+    * @return the maximum/minimum value
+    */
+  command int32_t getMaxTaskLatency();
+  command int32_t getMinTaskLatency();
+
+}
=======================================
--- /dev/null
+++ /trunk/apps/tests/LinkBench/codeprofile/CodeProfileC.nc	Tue Sep  6  
00:34:50 2011
@@ -0,0 +1,70 @@
+/*
+* Copyright (c) 2010, University of Szeged
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* - Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* - Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* - Neither the name of University of Szeged nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+* OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Author: Krisztian Veress
+*         veresskrisztian at gmail.com
+*/
+
+#if defined(TOSSIM) && ! defined(MHZ)
+  #define MHZ 8
+#endif
+
+configuration CodeProfileC {
+  provides {
+    interface StdControl;
+    interface CodeProfile;
+  }
+}
+
+implementation {
+
+  #if defined(CONTROLLER_ATM128)
+    components new AlarmMicro32C() as Alarm;
+
+  #elif defined(CONTROLLER_MSP430)
+    components Msp430CounterMicroC as Counter16;
+    components new AlarmMicro16C() as Alarm16;
+
+    components new  
TransformCounterC(TMicro,uint32_t,TMicro,uint16_t,0,uint32_t) as TCounter;
+    TCounter.CounterFrom -> Counter16;
+
+    components new TransformAlarmC(TMicro,uint32_t,TMicro,uint16_t,0) as  
Alarm;
+    Alarm.AlarmFrom -> Alarm16;
+    Alarm.Counter -> TCounter;
+
+  #endif
+
+  components CodeProfileP;
+  CodeProfileP.Alarm -> Alarm;
+
+  StdControl = CodeProfileP;
+  CodeProfile = CodeProfileP;
+}
=======================================
--- /dev/null
+++ /trunk/apps/tests/LinkBench/codeprofile/CodeProfileP.nc	Tue Sep  6  
00:34:50 2011
@@ -0,0 +1,148 @@
+/*
+* Copyright (c) 2010, University of Szeged
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* - Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* - Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* - Neither the name of University of Szeged nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+* OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Author: Krisztian Veress
+*         veresskrisztian at gmail.com
+*/
+
+#define ATOMIC_PERIODIC_TIME 4096
+
+#define _MAX_(a,b) (((a) < (b)) ? (b) : (a))
+#define _MIN_(a,b) (((a) > (b)) ? (b) : (a))
+
+module CodeProfileP @safe() {
+  provides {
+    interface StdControl;
+    interface CodeProfile;
+  }
+  uses {
+    interface Alarm<TMicro, uint32_t> as Alarm;
+  }
+}
+
+implementation {
+
+  int32_t        max_mil;           // Maximum Interrupt Length
+  int32_t        max_mal;           // Maximum Atomic Length
+  int32_t        max_mtl;           // Maximum Task Latency
+
+  int32_t        min_mil;           // Mininum Interrupt Length
+  int32_t        min_mal;           // Mininum Atomic Length
+  int32_t        min_mtl;           // Mininum Task Latency
+
+  uint32_t       mtl_offset;
+  uint32_t       mal_offset;
+  norace bool    alive;
+
+  command int32_t CodeProfile.getMaxInterruptLength()  { return max_mil; }
+  command int32_t CodeProfile.getMaxAtomicLength()     { atomic {return  
max_mal;} }
+  command int32_t CodeProfile.getMaxTaskLatency()      { return max_mtl; }
+
+  command int32_t CodeProfile.getMinInterruptLength()  { return min_mil; }
+  command int32_t CodeProfile.getMinAtomicLength()     { atomic {return  
min_mal;} }
+  command int32_t CodeProfile.getMinTaskLatency()      { return min_mtl; }
+
+  task void measureTask() {
+
+    uint32_t t1 = call Alarm.getNow();
+    uint32_t t2 = call Alarm.getNow();
+
+    // The difference between two consecutive getNow() call can be
+    // significantly greater than zero, if interrupt(s) occured in  
between. That
+    // difference is proportional to the running time of the
+    // interrupt handler.
+    max_mil = _MAX_((int32_t)(t2-t1),max_mil);
+    min_mil = _MIN_((int32_t)(t2-t1),min_mil);
+
+    // The difference between the posting time of this task (mtl_offset)
+    // and the first expression's execution time ( t1 ) is the time
+    // between two measureTask tasks.
+    // This way, interleaving tasks' running time is measured.
+    max_mtl = _MAX_((int32_t)(t1-mtl_offset),max_mtl);
+    min_mtl = _MIN_((int32_t)(t1-mtl_offset),min_mtl);
+
+    if ( alive ) {
+      mtl_offset = call Alarm.getNow();
+      post measureTask();
+    }
+
+  }
+
+
+  command error_t StdControl.start() {
+
+    alive = TRUE;
+    min_mil = min_mtl = 0x7fffffffL;
+    max_mil = max_mtl = -(0x7fffffffL-1L);
+
+    // Atomic Length Measurement Init
+    atomic {
+      max_mal = -(0x7fffffffL-1L);
+      min_mal = 0x7fffffffL;
+      call Alarm.stop();
+      mal_offset = call Alarm.getNow();
+      call Alarm.startAt(mal_offset, ATOMIC_PERIODIC_TIME);
+    }
+
+    mtl_offset = call Alarm.getNow();
+    post measureTask();
+
+    return SUCCESS;
+  }
+
+  command error_t StdControl.stop() {
+    call Alarm.stop();
+    alive = FALSE;
+    return SUCCESS;
+  }
+
+  async event void Alarm.fired() {
+    // Get the time
+    int64_t delay = (int64_t)call Alarm.getNow();
+
+    atomic {
+      // When the alarm should have been fired?
+      // This is also the base of the next fire target.
+      mal_offset += ATOMIC_PERIODIC_TIME;
+
+      // Compute the shift between now and the target
+      delay -= mal_offset;
+
+      max_mal = _MAX_((int32_t)delay,max_mal);
+      min_mal = _MIN_((int32_t)delay,min_mal);
+    }
+
+    if ( alive )
+      call Alarm.startAt(mal_offset,ATOMIC_PERIODIC_TIME);
+  }
+
+}
+
=======================================
--- /dev/null
+++ /trunk/apps/tests/LinkBench/javasrc/benchmark/cli/BenchmarkCli.java	Tue  
Sep  6 00:34:50 2011
@@ -0,0 +1,489 @@
+/** Copyright (c) 2010, University of Szeged
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* - Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* - Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* - Neither the name of University of Szeged nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+* OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Author: Krisztian Veress
+*         veresskrisztian at gmail.com
+*/
+
+package benchmark.cli;
+
+import benchmark.common.*;
+import java.io.FileNotFoundException;
+import java.io.PrintStream;
+
+import org.apache.commons.cli.*;
+
+public class BenchmarkCli {
+
+  private BenchmarkController ctrl;
+
+  public BenchmarkCli() {
+    ctrl = new BenchmarkController();
+  }
+
+  /**
+   * Print out the help information
+   */
+  public static void printHelp(final Options opt) {
+
+    HelpFormatter f = new HelpFormatter();
+    System.out.println("Usage scenarios:");
+
+    Options opt0 = new Options();
+    opt0.addOption(opt.getOption("h"));
+    System.out.println();
+    System.out.println("1. Print help information.");
+     
System.out.println("--------------------------------------------------------------------");
+    f.printHelp(150, "linkbench", "", opt0, "", true);
+
+    // Batch - usage
+    Options opt1 = new Options();
+    opt1.addOption(opt.getOption("F"));
+    opt1.addOption(opt.getOption("o"));
+    opt1.addOption(opt.getOption("tossim"));
+    System.out.println();
+    System.out.println("2. Running benchmarks with pre-defined  
configurations in batch mode.");
+     
System.out.println("--------------------------------------------------------------------");
+    f.printHelp(150, "linkbench", "", opt1, "", true);
+
+    // Reset - usage
+    Options opt2 = new Options();
+    opt2.addOption(opt.getOption("r"));
+    opt2.addOption(opt.getOption("tossim"));
+    System.out.println();
+    System.out.println("3. Reset all motes.");
+     
System.out.println("--------------------------------------------------------------------");
+    f.printHelp(150, "linkbench", "", opt2, "", true);
+
+    // Download - usage
+    Options opt3 = new Options();
+    opt3.addOption(opt.getOption("dload"));
+    opt3.addOption(opt.getOption("mc"));
+    opt3.addOption(opt.getOption("xml"));
+    System.out.println();
+    System.out.println("4. Only download data from the motes (if data  
available).");
+     
System.out.println("--------------------------------------------------------------------");
+    f.printHelp(150, "linkbench", "", opt3, "", true);
+
+    // Command-line usage
+    Options opt4 = new Options();
+    opt4.addOption(opt.getOption("b"));
+    opt4.addOption(opt.getOption("t"));
+    opt4.addOption(opt.getOption("rs"));
+    opt4.addOption(opt.getOption("lc"));
+    opt4.addOption(opt.getOption("tr"));
+    opt4.addOption(opt.getOption("ack"));
+    opt4.addOption(opt.getOption("bcast"));
+    opt4.addOption(opt.getOption("xml"));
+    opt4.addOption(opt.getOption("mac"));
+    opt4.addOption(opt.getOption("mc"));
+    opt4.addOption(opt.getOption("tossim"));
+    System.out.println();
+    System.out.println("5. Running a specific benchmark with command-line  
arguments");
+     
System.out.println("--------------------------------------------------------------------");
+    f.printHelp(88, "linkbench", "", opt4, "", true);
+
+  }
+
+  /**
+   * Construct the Options opt appropriate for
+   * the Apache CLI command-line interpreter.
+   */
+  private static void initOptions(Options opt) {
+
+    // Batch related options
+    Option batchfile = OptionBuilder
+            .withArgName("file")
+            .hasArg()
+            .withDescription("The batch file with configuration parameters  
for multiple benchmark runs")
+            .create("F");
+
+    Option batchoutput = OptionBuilder
+            .withArgName("file")
+            .hasArg()
+            .withDescription("The output XML file name. [default:  
results.xml]")
+            .create("o");
+
+    // Problem id option
+    Option problem = OptionBuilder
+            .withArgName("number")
+            .hasArg()
+            .withDescription("The benchmark to be used")
+            .withLongOpt("benchmark")
+            .create("b");
+
+    // Time- related options
+    Option randomstart = OptionBuilder
+            .withArgName("number")
+            .hasArg()
+            .withDescription("Random start delay in millisecs. [default: "  
+
+              BenchmarkCommons.DEF_RANDSTART + " msec]")
+            .withLongOpt("randomstart")
+            .create("rs");
+
+    Option runtime = OptionBuilder
+            .withArgName("normal")
+            .hasArg()
+            .withDescription("The benchmark running time in millisecs. " +
+              "[default: " + BenchmarkCommons.DEF_RUNTIME + " msec]")
+            .withLongOpt("time")
+            .create("t");
+
+    Option lastchance = OptionBuilder
+            .withArgName("number")
+            .hasArg()
+            .withDescription("The grace time period after test completion  
for" +
+              " last-chance reception. [default : " +
+              BenchmarkCommons.DEF_LASTCHANCE + " msec]")
+            .withLongOpt("lastchance")
+            .create("lc");
+
+    Option trtimers = OptionBuilder
+            .withArgName("timer config list")
+            .hasArg()
+            .withDescription("Trigger timer configuration " +
+              "index:isoneshot,maxrandomdelay,period.  [default : 1:" +
+              TimerParser.DEF_TIMER_ONESHOT + "," +
+              TimerParser.DEF_TIMER_DELAY + "," +
+              TimerParser.DEF_TIMER_PERIOD + " ]")
+            .withLongOpt("triggers")
+            .create("tr");
+
+    Option mac = OptionBuilder
+            .withArgName("MAC params")
+            .hasArg()
+            .withDescription("MAC along with parameters:   
mactype:param1,param2,...,paramN [ mactypes: lpl,plink ]")
+            .create("mac");
+
+    Option xml = OptionBuilder
+            .withArgName("file")
+            .hasArg()
+            .withDescription("Produce xml output")
+            .create("xml");
+
+    Option mcount = OptionBuilder
+            .withArgName("number")
+            .hasArg()
+            .withDescription("How many motes are in the network.")
+            .withLongOpt("motecount")
+            .create("mc");
+
+
+    Option reset = OptionBuilder
+            .withArgName("moteid")
+            .hasArg()
+            .withDescription("Reset the mote. If moteid set to 0, all  
motes are reset.")
+            .withLongOpt("reset")
+            .create("r");
+
+
+    opt.addOption(problem);
+    opt.addOption(randomstart);
+    opt.addOption(runtime);
+    opt.addOption(lastchance);
+    opt.addOption(xml);
+    opt.addOption(mac);
+    opt.addOption(mcount);
+    opt.addOption(trtimers);
+    opt.addOption(batchfile);
+    opt.addOption(batchoutput);
+    opt.addOption(reset);
+
+    opt.addOption("h", "help", false, "Print help for this application");
+    opt.addOption("ack", false, "Force acknowledgements. [default :  
false]");
+    opt.addOption("bcast", "broadcast", false, "Force broadcasting.  
[default : false]");
+    opt.addOption("dload", "download", false, "Only download data from  
motes.");
+
+    opt.addOption("tossim", false, "MUST be used if TOSSIM is in use.");
+
+  }
+
+  public boolean doReset(final boolean is_tossim, final int moteid) {
+    if ( moteid == 0 )
+        System.out.print("> Reset all motes ...     ");
+    else
+        System.out.print(String.format("> Reset  
mote %2d ...       ",moteid));
+
+    try {
+      if ( moteid == 0 )
+          ctrl.reset(!is_tossim);
+      else
+          ctrl.resetMote(moteid);
+
+      System.out.println("OK");
+      return true;
+    } catch (BenchmarkController.MessageSendException ex) {
+      System.out.println("FAIL");
+      return false;
+    }
+  }
+
+  public boolean doSync() {
+    System.out.print("> Synchronize motes ...   ");
+    try {
+      ctrl.syncAll();
+      System.out.println("OK");
+      return true;
+    } catch (BenchmarkController.CommunicationException ex) {
+      System.out.println("FAIL");
+      System.out.println("  " + ex.getMessage() );
+      return false;
+    }
+  }
+
+  public boolean doDownloadStat(final int maxMoteId) {
+    System.out.print("> Downloading data ...    ");
+    try {
+      ctrl.download_stat();
+      System.out.println("OK");
+      return true;
+    } catch (BenchmarkController.CommunicationException ex) {
+      System.out.println("FAIL");
+      System.out.println("  " + ex.getMessage() );
+      return false;
+    }
+  }
+
+  public boolean doDownloadProfile(final int maxMoteId) {
+    System.out.print("> Downloading profile ... ");
+    try {
+      ctrl.download_profile();
+      System.out.println("OK");
+      return true;
+    } catch (BenchmarkController.CommunicationException ex) {
+      System.out.println("FAIL");
+      System.out.println("  " + ex.getMessage() );
+      return false;
+    }
+  }
+
+  public boolean doSetup(final SetupT st, final boolean is_tossim) {
+    System.out.print("> Setting up motes ...    ");
+    try {
+      ctrl.setup(st,!is_tossim);
+      System.out.println("OK");
+      return true;
+    } catch (BenchmarkController.MessageSendException ex) {
+      System.out.println("FAIL");
+      return false;
+    }
+  }
+
+  public boolean doRun(final boolean is_tossim) {
+    System.out.print("> Running benchmark ...   ");
+    try {
+      ctrl.run(!is_tossim);
+      System.out.println("OK");
+      return true;
+    } catch (BenchmarkController.MessageSendException ex) {
+      System.out.println("FAIL");
+      return false;
+    }
+  }
+
+  public void doPrintXml(final String filename) {
+    PrintStream ps;
+    try {
+      ps = new PrintStream(filename);
+      ps.println(BenchmarkCommons.xmlHeader());
+      this.ctrl.getResults().printXml(ps);
+      ps.println(BenchmarkCommons.xmlFooter());
+      ps.close();
+    } catch (FileNotFoundException ex) {
+      System.out.println("Cannot open " + filename + " for writing!");
+    }
+  }
+
+  public void doPrint() {
+    this.ctrl.getResults().print(System.out);
+  }
+
+	public static void main (String[] args)
+  {
+    try {
+      // Make the options and parse it
+      Options opt = new Options();
+      BenchmarkCli.initOptions(opt);
+
+      BasicParser parser = new BasicParser();
+      CommandLine cl = parser.parse(opt, args);
+
+      // Help request -- if present, do nothing else.
+      //  
-----------------------------------------------------------------------
+      if ( cl.hasOption('h') ) {
+        BenchmarkCli.printHelp(opt);
+        System.exit(0);
+      }
+      // Reset request -- if present, do nothing else.
+      //  
-----------------------------------------------------------------------
+      else if ( cl. hasOption('r') ) {
+        BenchmarkCli cli = new BenchmarkCli();
+        if ( cli.doReset( cl.hasOption("tossim"),  
Integer.parseInt(cl.getOptionValue("r")) ) )
+            System.exit(0);
+        else
+            System.exit(1);
+      }
+      // Download request
+      //  
-----------------------------------------------------------------------
+      else if ( cl.hasOption("dload") ) {
+
+        int maxmoteid = cl.hasOption("mc")
+                                ? Integer.parseInt(cl.getOptionValue("mc"))
+                                : 1;
+        if ( maxmoteid < 1 )
+          throw new MissingOptionException("Invalid number of motes  
specified!");
+
+        // Do what needs to be done
+        BenchmarkCli cli = new BenchmarkCli();
+        if ( cli.doSync() &&
+             cli.doDownloadStat(maxmoteid) &&
+             cli.doDownloadProfile(maxmoteid) )
+        {
+          // Dump results to XML or STDOUT
+          if ( cl.hasOption("xml") )
+            cli.doPrintXml(cl.getOptionValue("xml"));
+          else
+            cli.doPrint();
+
+          System.exit(0);
+        } else
+          System.exit(1);
+      }
+      // Batch request
+      //  
-----------------------------------------------------------------------
+      else if ( cl.hasOption('F') ) {
+        String bfile = cl.getOptionValue('F');
+        String ofile = cl.hasOption('o') ?  
cl.getOptionValue('o') : "results.xml";
+
+        BenchmarkBatch rbb = new BenchmarkBatch(ofile);
+        if ( rbb.parse(bfile) && rbb.run( cl.hasOption("tossim") ) ) {
+          System.exit(0);
+        } else
+          System.exit(1);
+      }
+      // Command line control
+      //  
-----------------------------------------------------------------------
+      else if ( cl.hasOption('b') ) {
+
+        short problemidx = (short)Integer.parseInt(cl.getOptionValue('b'));
+        if ( problemidx < 0 )
+          throw new MissingOptionException("Invalid problem specified!");
+
+        int startdelay = cl.hasOption("rs")
+                                ? Integer.parseInt(cl.getOptionValue("rs"))
+                                : BenchmarkCommons.DEF_RANDSTART;
+        if ( startdelay < 0 )
+            throw new MissingOptionException("Invalid random start time  
specified!");
+
+        int runtimemsec = cl.hasOption('t')
+                                ? Integer.parseInt(cl.getOptionValue("t"))
+                                : BenchmarkCommons.DEF_RUNTIME;
+        if ( runtimemsec <= 0 )
+          throw new MissingOptionException("Invalid runtime specified!");
+
+        int lchance = cl.hasOption("lc")
+                                ? Integer.parseInt(cl.getOptionValue("lc"))
+                                : BenchmarkCommons.DEF_LASTCHANCE;
+        if ( lchance < 0 )
+          throw new MissingOptionException("Invalid last chance time  
specified!");
+
+        int maxmoteid = cl.hasOption("mc")
+                                ? Integer.parseInt(cl.getOptionValue("mc"))
+                                : 1;
+        if ( maxmoteid < 1 )
+          throw new MissingOptionException("Invalid number of motes  
specified!");
+
+        // Trigger timer parsing
+        TimerParser tp = new TimerParser(BenchmarkStatic.MAX_TIMER_COUNT);
+        if ( cl.hasOption("tr") ) {
+          for ( String s : cl.getOptionValues("tr") ) {
+            tp.parse(s);
+          }
+        }
+
+        // Trigger timer parsing
+        MacParser mac = new MacParser();
+        if ( cl.hasOption("mac") ) {
+          for ( String s : cl.getOptionValues("mac") ) {
+            mac.parse(s);
+          }
+        }
+
+        // Mac protocols may have flags set
+        short flags = mac.getFlags();
+        if ( cl.hasOption("ack") )
+          flags |= BenchmarkStatic.GLOBAL_USE_ACK;
+        if ( cl.hasOption("bcast") )
+          flags |= BenchmarkStatic.GLOBAL_USE_BCAST;
+
+        // Create the setup structure
+        SetupT st = new SetupT();
+        st.set_problem_idx(problemidx);
+        st.set_pre_run_msec(startdelay);
+        st.set_runtime_msec(runtimemsec);
+        st.set_post_run_msec(lchance);
+        st.set_flags(flags);
+        st.set_timers_isoneshot(tp.getIos());
+        st.set_timers_delay(tp.getDelay());
+        st.set_timers_period_msec(tp.getPeriod());
+        st.set_mac_setup(mac.getMacParams());
+
+        // Do what needs to be done
+        boolean tossim = cl.hasOption("tossim");
+        BenchmarkCli cli = new BenchmarkCli();
+        if (cli.doReset(tossim,0)            &&
+            cli.doSetup(st,tossim)           &&
+            cli.doSync()                     &&
+            cli.doRun(tossim)                &&
+            cli.doDownloadStat(maxmoteid)    &&
+            cli.doDownloadProfile(maxmoteid) )
+        {
+
+          // Dump results to XML or STDOUT
+          if ( cl.hasOption("xml") )
+            cli.doPrintXml(cl.getOptionValue("xml"));
+          else
+            cli.doPrint();
+
+          System.exit(0);
+        } else {
+          System.exit(1);
+        }
+      } else {
+        throw new MissingOptionException("Invalid program arguments, use  
--help for help!");
+      }
+    } catch (Exception e) {
+      System.err.println();
+      System.err.println("Error : " + e.getMessage());
+      System.err.println();
+      System.exit(1);
+    }
+  }
+}
=======================================
--- /dev/null
+++  
/trunk/apps/tests/LinkBench/javasrc/benchmark/common/BenchmarkBatch.java	 
Tue Sep  6 00:34:50 2011
@@ -0,0 +1,323 @@
+/*
+* Copyright (c) 2010, University of Szeged
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* - Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* - Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* - Neither the name of University of Szeged nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+* OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Author: Krisztian Veress
+*         veresskrisztian at gmail.com
+*/
+
+package benchmark.common;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.yaml.snakeyaml.Yaml;
+
+public class BenchmarkBatch {
+
+  private List<SetupT>  setups;
+  private List<Integer> motecounts;
+  private String        outputfile;
+
+  private final String S_CONFIG           = "config";
+  private final String S_CONFIG_BMARK     = "bmark";
+  private final String S_CONFIG_MOTEC     = "motes";
+  private final String S_CONFIG_RANDSTART = "randstart";
+  private final String S_CONFIG_TIME      = "time";
+  private final String S_CONFIG_LC        = "lchance";
+  private final String S_TIMERS           = "timers";
+  private final String S_TIMER_PREFIX     = "t";
+  private final String S_FORCES           = "forces";
+  private final String S_FORCES_ACK       = "ack";
+  private final String S_FORCES_BCAST     = "bcast";
+
+  private final String S_MAC              = "mac";
+
+
+  class WrongFormatException extends Exception {
+    public WrongFormatException(String message) {
+      super(message);
+    }
+  }
+
+  /**
+   * Construct an object being able to conduct batch benchmark runs.
+   * @param outputfile the file where we should output the results
+   */
+  public BenchmarkBatch(final String outputfile) {
+    this.outputfile = outputfile;
+    this.setups = new ArrayList<SetupT>();
+    this.motecounts = new ArrayList<Integer>();
+  }
+
+  private void checkUnknownTags(final Set<String> reference, final  
Set<String> check) throws WrongFormatException {
+    Set<String> difference = new HashSet<String>(check);
+    difference.removeAll(reference);
+    if ( ! difference.isEmpty() ) {
+      throw new WrongFormatException("Unknown tags found : " +  
difference.toString());
+    }
+  }
+
+  /**
+   * Parse a YAML-formatted configuration file, and save it for further  
processing.
+   *
+   * @param configfile the file
+   * @return TRUE if no error detected, FALSE otherwise
+   * @throws WrongFormatException
+   */
+  public boolean parse(final String configfile) throws  
WrongFormatException {
+    try {
+      System.out.print("> Parsing configuration file ... ");
+      int num = 0;
+      for (Object doc : new Yaml().loadAll(new FileInputStream(new  
File(configfile)))) {
+        ++num;
+
+        // whole benchmark section
+        //  
---------------------------------------------------------------------
+        Map<String, Object> bmark = (Map<String, Object>) doc;
+        // Format checking
+        if ( bmark == null )
+          throw new WrongFormatException("Check your configuration file's  
format, it is incorrect!");
+        else {
+          String ref[] = { S_CONFIG, S_TIMERS, S_FORCES, S_MAC };
+          checkUnknownTags(new HashSet(Arrays.asList(ref)),  
bmark.keySet());
+
+          if ( !bmark.containsKey(S_CONFIG) )
+            throw new WrongFormatException("No '" + S_CONFIG + "' section  
found in benchmark description : " + num);
+        }
+
+        // config section - it MUST exist (previously we checked it!)
+        //  
---------------------------------------------------------------------
+        Map<String, Integer> bconfig = (Map<String, Integer>)  
bmark.get(S_CONFIG);
+        // Format checking
+        {
+          String ref[] = { S_CONFIG_BMARK, S_CONFIG_MOTEC, S_CONFIG_TIME,  
S_CONFIG_LC, S_CONFIG_RANDSTART };
+          checkUnknownTags(new HashSet(Arrays.asList(ref)),  
bconfig.keySet());
+
+          if ( !bconfig.containsKey(S_CONFIG_BMARK) | 
| !bconfig.containsKey(S_CONFIG_TIME) )
+            throw new WrongFormatException("The '" + S_CONFIG_BMARK + "'  
and '" + S_CONFIG_TIME + "' values are mandatory!");
+
+          // Value check
+          if ( bconfig.containsKey(S_CONFIG_BMARK) &&  
bconfig.get(S_CONFIG_BMARK) < 0)
+            throw new WrongFormatException("All '" + S_CONFIG_BMARK + "'  
values must be non-negative!");
+
+          if ( bconfig.containsKey(S_CONFIG_TIME) &&  
bconfig.get(S_CONFIG_TIME) <= 0)
+            throw new WrongFormatException("All '" + S_CONFIG_TIME + "'  
values must be positive!");
+
+          if ( bconfig.containsKey(S_CONFIG_MOTEC) &&  
bconfig.get(S_CONFIG_MOTEC) < 1)
+            throw new WrongFormatException("All '" + S_CONFIG_MOTEC + "'  
values must be positive!");
+
+          if ( bconfig.containsKey(S_CONFIG_LC) &&  
bconfig.get(S_CONFIG_LC) < 0)
+            throw new WrongFormatException("All '" + S_CONFIG_LC + "'  
values must be non-negative!");
+
+          if ( bconfig.containsKey(S_CONFIG_RANDSTART) &&  
bconfig.get(S_CONFIG_RANDSTART) < 0)
+            throw new WrongFormatException("All '" + S_CONFIG_RANDSTART  
+ "' values must be non-negative!");
+
+        }
+
+        // timers section
+        //  
---------------------------------------------------------------------
+        List< Map<String,List<Integer>> > btimers =  
bmark.containsKey(S_TIMERS)
+                ? (List< Map<String,List<Integer>> >) bmark.get(S_TIMERS)
+                : null;
+
+        TimerParser tp = new TimerParser(BenchmarkStatic.MAX_TIMER_COUNT);
+
+        // Format checking
+        if (btimers != null) {
+          for (Map<String, List<Integer>> timerspec : btimers) {
+            for (byte i = 1; i <= BenchmarkStatic.MAX_TIMER_COUNT; ++i) {
+              if (timerspec.containsKey(S_TIMER_PREFIX + i)) {
+                List<Integer> timervalues = (List<Integer>)  
timerspec.get(S_TIMER_PREFIX + i);
+                if (timervalues.size() != 3) {
+                  throw new WrongFormatException("All timer specification  
must contain exactly 3 values!");
+                }
+
+                tp.setSpec((byte)(i-1),
+                        timervalues.get(0).shortValue(),
+                        timervalues.get(1).longValue(),
+                        timervalues.get(2).longValue());
+              }
+            }
+          }
+        }
+
+        // MAC parameter section
+        //  
---------------------------------------------------------------------
+        List< Map<String,List<Integer>> > macparams =  
bmark.containsKey(S_MAC)
+                ? (List< Map<String,List<Integer>> >) bmark.get(S_MAC)
+                : null;
+
+        MacParser mp = new MacParser();
+        // Format checking
+        if (macparams != null) {
+          for (Map<String, List<Integer>> macspec : macparams) {
+            for ( String key : macspec.keySet() ) {
+              mp.parseAll(key, toIntArray(macspec.get(key)) );
+            }
+          }
+        }
+
+        // forces section
+        //  
---------------------------------------------------------------------
+        List<String> forceopts = bmark.containsKey(S_FORCES)
+                ? (List<String>) bmark.get(S_FORCES)
+                : null;
+        // Format + value checking
+        if ( forceopts != null ) {
+          String ref[] = { S_FORCES_ACK, S_FORCES_BCAST};
+          checkUnknownTags(new HashSet(Arrays.asList(ref)), new  
HashSet<String>(forceopts));
+        }
+
+        short flags = mp.getFlags();
+        if ( forceopts != null ) {
+          if ( forceopts.contains(S_FORCES_ACK) )
+            flags |= BenchmarkStatic.GLOBAL_USE_ACK;
+          if ( forceopts.contains(S_FORCES_BCAST) )
+            flags |= BenchmarkStatic.GLOBAL_USE_BCAST;
+        }
+
+        // Create a SetupT for the current benchmark
+        SetupT setup = new SetupT();
+        setup.set_problem_idx(bconfig.get(S_CONFIG_BMARK).shortValue());
+
+        setup.set_pre_run_msec(
+                bconfig.containsKey(S_CONFIG_RANDSTART) ?
+                bconfig.get(S_CONFIG_RANDSTART) :
+                BenchmarkCommons.DEF_RANDSTART);
+
+        setup.set_runtime_msec(bconfig.get(S_CONFIG_TIME).shortValue());
+        setup.set_post_run_msec(
+                bconfig.containsKey(S_CONFIG_LC) ?
+                bconfig.get(S_CONFIG_LC) :
+                BenchmarkCommons.DEF_LASTCHANCE);
+
+        setup.set_mac_setup(mp.getMacParams());
+        setup.set_flags(flags);
+
+        setup.set_timers_isoneshot(tp.getIos());
+        setup.set_timers_delay(tp.getDelay());
+        setup.set_timers_period_msec(tp.getPeriod());
+
+        // update our attributes
+        this.setups.add(setup);
+        this.motecounts.add(
+                bconfig.containsKey(S_CONFIG_MOTEC) ?
+                bconfig.get(S_CONFIG_MOTEC) : 1);
+
+      }
+      System.out.println("OK");
+      System.out.println("   " + configfile + " : " + this.setups.size()  
+ " benchmark(s) successfully parsed.");
+      return true;
+
+    } catch (FileNotFoundException ex) {
+      System.out.println("FAIL");
+      System.out.println("   File named " + configfile + " not found!");
+
+    } catch (WrongFormatException ex) {
+      System.out.println("FAIL");
+      System.out.println("   " + ex.getMessage());
+
+    } catch (Exception ex) {
+      System.out.println("FAIL");
+      System.out.println("   Wrong configuration file format! The file  
must be YAML-formatted.");
+      System.out.println("   " + ex.getMessage());
+    }
+    return false;
+  }
+
+  /**
+   * Run the previously parsed benchmark configurations.
+   */
+  public boolean run(final boolean is_tossim) {
+    PrintStream ps = null;
+    try {
+      ps = new PrintStream(this.outputfile);
+      ps.println(BenchmarkCommons.xmlHeader());
+
+      BenchmarkController ctrl = new BenchmarkController();
+      ctrl.reset(!is_tossim);
+
+      int i = 0;
+      int total = this.setups.size();
+      int progress = 1;
+      // Run each benchmark sequentially
+      for (SetupT s : setups) {
+        ctrl.updateMoteCount(this.motecounts.get(i++));
+
+        System.out.print("\r> Progress : " + (progress * 100 / total )  
+ "% (" + progress + "/" + total + ")" );
+        try {
+          ctrl.reset(!is_tossim);
+          ctrl.setup(s,!is_tossim);
+          ctrl.syncAll();
+          ctrl.run(!is_tossim);
+          ctrl.download_stat();
+          ctrl.download_profile();
+        } catch (BenchmarkController.MessageSendException ex) {
+          ctrl.getResults().setError(ex.getMessage());
+        } catch (BenchmarkController.CommunicationException ex) {
+          ctrl.getResults().setError(ex.getMessage());
+        }
+        ++progress;
+        ctrl.getResults().printXml(ps);
+      }
+      ps.println(BenchmarkCommons.xmlFooter());
+      ps.close();
+      System.out.println();
+      System.out.println("> Batch processing successfully finished!");
+      return true;
+    } catch (FileNotFoundException ex) {
+      System.out.println("   File named " + outputfile + " cannot be  
created!");
+      System.out.println("> Batch processing failed!");
+      return false;
+    } catch (Exception ex) {
+      System.out.println("   " + ex.getMessage());
+      System.out.println("> Batch processing failed!");
+      return false;
+    }
+  }
+
+  private static int[] toIntArray(List<Integer> list)  {
+    int[] ret = new int[list.size()];
+    int i = 0;
+    for (Integer e : list)
+        ret[i++] = e.intValue();
+    return ret;
+  }
+
+
+}
=======================================
--- /dev/null
+++  
/trunk/apps/tests/LinkBench/javasrc/benchmark/common/BenchmarkCommons.java	 
Tue Sep  6 00:34:50 2011
@@ -0,0 +1,323 @@
+/*
+* Copyright (c) 2010, University of Szeged
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* - Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* - Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* - Neither the name of University of Szeged nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+* OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Author: Krisztian Veress
+*         veresskrisztian at gmail.com
+*/
+package benchmark.common;
+
+import java.util.Vector;
+
+public class BenchmarkCommons {
+
+  public static final short   DEF_RANDSTART     = 0;
+  public static final short   DEF_RUNTIME       = 1000;
+  public static final short   DEF_LASTCHANCE    = 20;
+
+  private static final String nl = System.getProperty("line.separator");
+
+  /**
+   * Compute the overall running time of the benchmark defined by the  
argument
+   * @param config The benchmark configuration
+   * @return the overall running time in msecs
+   */
+  public static long getRuntime(final SetupT config) {
+    return config.get_pre_run_msec() +
+           config.get_runtime_msec() +
+           config.get_post_run_msec();
+  }
+
+  /**
+   * Get the XML header for results generation
+   * @return the XML header as one string
+   */
+  public static String xmlHeader() {
+    return "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>" +
+           "<?xml-stylesheet type=\"text/xsl\"  
href=\"assets/benchmark.xsl\"?>" +
+           nl + "<resultset>";
+  }
+
+  /**
+   * Get the XML footer for results generation
+   * @return the XML footer as one string
+   */
+  public static String xmlFooter() {
+    return "</resultset>";
+  }
+
+
+  /**
+   * Generates a multi-line String representation of a benchmark
+   * configuration passed as an argument.
+   *
+   * @param config The configuration
+   * @return the string representation
+   */
+  public static String setupAsString(final SetupT config) {
+
+    String out = "> Problem: \t" + config.get_problem_idx() + nl;
+    out += "  Runtime: \t[max (" + config.get_pre_run_msec() + "ms) + "
+           + config.get_runtime_msec() + "ms + "
+           + config.get_post_run_msec() + " ms]" + nl;
+    out += "  F.Ack/Bcast: \t";
+    out += ( config.get_flags() & 0x1 ) > 0 ? "On/" : "Off/";
+    out += ( config.get_flags() & 0x2 ) > 0 ? "On" : "Off";
+    out += nl;
+
+
+    out += "  Timers: \t[";
+    short ios[] = config.get_timers_isoneshot();
+    long delay[] = config.get_timers_delay();
+    long period[] = config.get_timers_period_msec();
+
+    for (int i=0; i< BenchmarkStatic.MAX_TIMER_COUNT; ++i) {
+      out += (ios[i] == 1 ) ? "1shot " : "period ";
+      out += delay[i] + "ms/";
+      out += period[i] + "ms";
+      if (i != BenchmarkStatic.MAX_TIMER_COUNT-1)
+        out += " | ";
+    }
+    out += "]" + nl;
+
+    out +=  
MacParser.macAsString(config.get_flags(),config.get_mac_setup());
+    return out;
+  }
+
+  /**
+   * Generates an XML representation of a benchmark
+   * configuration passed as an argument.
+   *
+   * @param config The configuration
+   * @return the XML representation
+   */
+  public static String setupAsXml(final SetupT config) {
+    String out = "<configuration>"+nl;
+    out +="<benchidx>" + config.get_problem_idx() + "</benchidx>"+nl;
+    out +="<pre_runtime>" + config.get_pre_run_msec()  
+ "</pre_runtime>"+nl;
+    out +="<runtime>" + config.get_runtime_msec() + "</runtime>"+nl;
+    out +="<post_runtime>" + config.get_post_run_msec()  
+ "</post_runtime>"+nl;
+    out +="<ack>" + (((config.get_flags() & BenchmarkStatic.GLOBAL_USE_ACK  
) > 0 )? "On" : "Off") + "</ack>"+nl;
+    out +="<bcast>" + (((config.get_flags() &  
BenchmarkStatic.GLOBAL_USE_BCAST ) > 0 ) ? "On" : "Off") + "</bcast>"+nl;
+
+    out += MacParser.macAsXml(config.get_flags(),config.get_mac_setup());
+
+    short ios[] = config.get_timers_isoneshot();
+    long delay[] = config.get_timers_delay();
+    long period[] = config.get_timers_period_msec();
+    for (int i=0; i< BenchmarkStatic.MAX_TIMER_COUNT; ++i) {
+      out += "<timer idx=\"" + i + "\" ";
+      out += (ios[i] == 1 )? "oneshot=\"yes\" " : "oneshot=\"no\" ";
+      out += "delay=\"" + delay[i] + "\" ";
+      out += "period=\"" + period[i] + "\"/>"+nl;
+    }
+    out += "</configuration>";
+    return out;
+  }
+
+  /**
+   * Generates a multi-line String representation of the results of a  
benchmark
+   *
+   * @param stats the collection of the results
+   * @return the string representation
+   */
+  public static String statsAsString(final Vector<StatT> stats) {
+    String hdr =
+            "   
-----------------------------------------------------------------------------------------------------------------"  
+ nl +
+            "  Statistics :\t[ Tri Blg Res | send Succ Fail | sDone Succ  
Fail | Ack NAck | Recv  Exp Wrng Dupl Frwd Miss | Rem ]";
+    String ret = "";
+    for (int i = 0; i < stats.size(); ++i) {
+      StatT s = stats.get(i);
+      String str = String.format("    Edge(%2d) :\t[ %2$3d %3$3d %4$3d  
| %5$4d %6$4d %7$4d | %8$5d %9$4d %10$4d | %11$3d %12$4d  
| %13$4d %14$4d %15$4d %16$4d %17$4d %18$4d | %19$3d ]",
+              i,
+              s.get_triggerCount(),
+              s.get_backlogCount(),
+              s.get_resendCount(),
+              s.get_sendCount(),
+              s.get_sendSuccessCount(),
+              s.get_sendFailCount(),
+              s.get_sendDoneCount(),
+              s.get_sendDoneSuccessCount(),
+              s.get_sendDoneFailCount(),
+              s.get_wasAckedCount(),
+              s.get_notAckedCount(),
+              s.get_receiveCount(),
+              s.get_consecutiveCount(),
+              s.get_wrongCount(),
+              s.get_duplicateCount(),
+              s.get_forwardCount(),
+              s.get_missedCount(),
+              s.get_remainedCount());
+       ret += str + nl;
+    }
+    return hdr + nl + ret;
+  }
+
+   /**
+   * Generates an XML representation of the results of a benchmark.
+   *
+   * @param stats the collection of the results
+   * @return the XML representation
+   */
+  public static String statsAsXml(final Vector<StatT> stats) {
+    String ret = "<statlist>"+nl;
+    for ( int i = 0; i< stats.size(); ++i ) {
+      StatT s = stats.get(i);
+      ret += "<stat idx=\"" + i + "\">";
+
+      ret += "<TC>" + s.get_triggerCount() + "</TC>";
+      ret += "<BC>" + s.get_backlogCount() + "</BC>";
+      ret += "<RC>" + s.get_resendCount() + "</RC>";
+
+      ret += "<SC>" + s.get_sendCount() + "</SC>";
+      ret += "<SSC>" + s.get_sendSuccessCount() + "</SSC>";
+      ret += "<SFC>" + s.get_sendFailCount() + "</SFC>";
+
+      ret += "<SDC>" + s.get_sendDoneCount() + "</SDC>";
+      ret += "<SDSC>" + s.get_sendDoneSuccessCount() + "</SDSC>";
+      ret += "<SDFC>" + s.get_sendDoneFailCount() + "</SDFC>";
+
+      ret += "<WAC>" + s.get_wasAckedCount() + "</WAC>";
+      ret += "<NAC>" + s.get_notAckedCount() + "</NAC>";
+
+      ret += "<RCC>" + s.get_receiveCount() + "</RCC>";
+      ret += "<EXC>" + s.get_consecutiveCount() + "</EXC>";
+      ret += "<WC>" + s.get_wrongCount() + "</WC>";
+      ret += "<FC>" + s.get_forwardCount() + "</FC>";
+      ret += "<DRC>" + s.get_duplicateCount() + "</DRC>";
+      ret += "<MC>" + s.get_missedCount() + "</MC>";
+
+      ret += "<REMC>" + s.get_remainedCount() + "</REMC>";
+      ret += "</stat>" + nl;
+    }
+    ret += "</statlist>";
+    return ret;
+  }
+
+  /**
+   * Generates a String representation of the profile information of a  
benchmark
+   *
+   * @param profiles the computed profiles
+   * @return the string representation
+   */
+  public static String profilesAsString(final Vector<ProfileT> profiles) {
+    String hdr = "    Profiles :\t[ Dbg | MaxAtom MaxInt MaxLat | MinAtom  
MinInt MinLat |   RxTxTime  RStartCnt     RxMsgs       Rx_B       Tx_B ]";
+    String ret = "";
+    for (int i = 0; i < profiles.size(); ++i) {
+      ProfileT p = profiles.get(i);
+      String str = String.format("    Mote(%2d) :\t[ %2$3d  
| %3$7d %4$6d %5$6d | %6$7d %7$6d %8$6d  
| %9$10d %10$10d %11$10d %12$10d %13$10d ]",
+              i+1,
+              p.get_debug(),
+              p.get_max_atomic(),
+              p.get_max_interrupt(),
+              p.get_max_latency(),
+              p.get_min_atomic(),
+              p.get_min_interrupt(),
+              p.get_min_latency(),
+              p.get_rtx_time(),
+              p.get_rstart_count(),
+              p.get_rx_msgs(),
+              p.get_rx_bytes(),
+              p.get_tx_bytes());
+       ret += str + nl;
+    }
+    return hdr + nl + ret;
+  }
+
+  /**
+   * Generates an XML representation of the profile information of a  
benchmark
+   *
+   * @param profiles the computed profiles
+   * @return the XML representation
+   */
+  public static String profilesAsXml(final Vector<ProfileT> profiles) {
+    String ret = "<profilelist>"+nl;
+    for ( int i = 0; i< profiles.size(); ++i ) {
+      ProfileT p = profiles.get(i);
+      ret += "<profile idx=\"" + (i+1) + "\">";
+
+      ret += "<MAT>" + p.get_max_atomic() + "</MAT>";
+      ret += "<MINT>" + p.get_max_interrupt() + "</MINT>";
+      ret += "<MLAT>" + p.get_max_latency() + "</MLAT>";
+      ret += "<MINAT>" + p.get_min_atomic() + "</MINAT>";
+      ret += "<MININT>" + p.get_min_interrupt() + "</MININT>";
+      ret += "<MINLAT>" + p.get_min_latency() + "</MINLAT>";
+      ret += "<RXTX>" + p.get_rtx_time() + "</RXTX>";
+      ret += "<RST>" + p.get_rstart_count() + "</RST>";
+      ret += "<RXMSGS>" + p.get_rx_msgs() + "</RXMSGS>";
+      ret += "<RXB>" + p.get_rx_bytes() + "</RXB>";
+      ret += "<TXB>" + p.get_tx_bytes() + "</TXB>";
+      ret += "<DBG>" + p.get_debug() + "</DBG>";
+
+      ret += "</profile>"+nl;
+    }
+    ret += "</profilelist>";
+    return ret;
+  }
+
+  /**
+   * Generates a String from the error which may have occured during the  
benchmark
+   * @param s the error
+   * @return the ready-for-output representation
+   */
+  public static String errorAsString(final String s) {
+    return "       Error :\t" + ((s.compareTo("") == 0) ? "No errors." :  
s);
+  }
+
+  /**
+   * Generates an XML tag from the error which may have occured during the  
benchmark
+   * @param s the error
+   * @return the ready-for-output XML representation
+   */
+  public static String errorAsXml(final String s) {
+    return "<error>" + s + "</error>";
+  }
+
+
+  /**
+   * Parses a parameter from an array based on its offset and length in  
bytes.
+   * @param a underlying byte array
+   * @param offset where does it start?
+   * @param bytes how long?
+   * @return the parameter
+   *
+   * Generated interfaces force us to use short for parameter 'a' but it is
+   * a byte array in real.
+   */
+  private static final long parseMacParameter(final short[] a, final byte  
offset, final byte bytes) {
+    long l = 0;
+    for(int i= offset; i< bytes; ++i) {
+      l |= (byte)(a[i]) & 0xFF;
+      l <<= 8;
+    }
+    return l;
+  }
+
+}
=======================================
--- /dev/null
+++  
/trunk/apps/tests/LinkBench/javasrc/benchmark/common/BenchmarkController.java	 
Tue Sep  6 00:34:50 2011
@@ -0,0 +1,407 @@
+/** Copyright (c) 2010, University of Szeged
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* - Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* - Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* - Neither the name of University of Szeged nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+* OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Author: Krisztian Veress
+*         veresskrisztian at gmail.com
+*/
+
+package benchmark.common;
+
+import java.util.concurrent.locks.*;
+import java.util.concurrent.TimeUnit;
+import net.tinyos.message.*;
+
+/**
+ * The class that is able to communicate with the LinkBenchmark
+ * TinyOS application.
+ *
+ * This class is responsible for sending and receiving control/data  
messages
+ * to/from the motes via a BaseStation mote.
+ *
+ * It is designed to be minimal and full, so everything is functional yet  
user-
+ * friendlyness must be implemented elsewhere.
+ */
+public class BenchmarkController implements MessageListener {
+
+	private MoteIF  mif;
+
+  // Needed for proper downloading
+  final Lock                  lock        = new ReentrantLock();
+  final Condition             answered    = lock.newCondition();
+  private boolean             handshake;
+  private static int          currentMote = 1;
+  private static short        currentData = 0;
+
+  // Public to be able to set it easily
+  public static final short   MAXPROBES   = 6;
+  public static final short   MAXTIMEOUT  = 2000;
+
+  private BenchmarkResult     results;
+
+  // These values are updated during the synchronization phase
+  private int                 maxMoteId   = 2;
+  private int                 edgecount   = 0;
+
+  public class MessageSendException extends Exception {};
+  public class CommunicationException extends Exception {
+    public CommunicationException(String message) {
+      super(message);
+    }
+  };
+
+  /**
+   * Contruct a controller.
+   *
+   * @param motecount How many motes are used?
+   */
+  public BenchmarkController()
+	{
+    mif = new MoteIF();
+    mif.registerListener(new SyncMsgT(),this);
+    mif.registerListener(new DataMsgT(),this);
+
+    maxMoteId = 2;
+    results = new BenchmarkResult();
+	}
+
+  /**
+   * Set the maximal mote id in the network.
+   *
+   * @param maxMoteId The new value
+   */
+  public void updateMoteCount(final int maxMoteId) {
+    this.maxMoteId = maxMoteId;
+    this.edgecount = 0;
+  }
+
+  /**
+   * Get the results
+   * @return an object containing the current results
+   */
+  public BenchmarkResult getResults() {
+    return this.results;
+  }
+
+  /**
+   * Send a RESET control message to the network.
+   * It is a broadcast message, so every mote should receive it.
+   *
+   * @param use_bcast Whether send one broadcast message or iterate  
through the motes
+   * @throws MessageSendException if an error occured (message is failed  
to send)
+   */
+  public boolean reset(final boolean use_bcast) throws MessageSendException
+  {
+    CtrlMsgT cmsg = new CtrlMsgT();
+    cmsg.set_type(BenchmarkStatic.CTRL_RESET);
+		try {
+      if (use_bcast ){
+        mif.send(MoteIF.TOS_BCAST_ADDR,cmsg);
+      } else {
+        currentMote = 1;
+        while ( currentMote <= maxMoteId ) {
+          mif.send(currentMote++,cmsg);
+        }
+      }
+      Thread.sleep((int)(500));
+		} catch(Exception e) {
+      throw new MessageSendException();
+    }
+    return true;
+	}
+
+  /**
+   * Send a RESET control message to only one mote.
+   *
+   * @param moteId The mote to be resetted
+   * @param use_bcast Whether send one broadcast message or iterate  
through the motes
+   * @throws MessageSendException if an error occured (message is failed  
to send)
+   */
+  public boolean resetMote(final int moteId) throws MessageSendException
+  {
+    CtrlMsgT cmsg = new CtrlMsgT();
+    cmsg.set_type(BenchmarkStatic.CTRL_RESET);
+    try {
+        mif.send(moteId,cmsg);
+        Thread.sleep((int)(500));
+	} catch(Exception e) {
+      throw new MessageSendException();
+    }
+    return true;
+  }
+
+  /**
+   * Send a SETUP control message to the network.
+   * It is a broadcast message, so every mote should receive it.
+   *
+   * @param config The benchmark configurationT
+   * @throws MessageSendException if an error occured (message is failed  
to send)
+   */
+
+  /**
+   * Send a SETUP control message to the network.
+   * It is a broadcast message, so every mote should receive it.
+   *
+   * @param config The benchmark configurationT
+   * @param use_bcast Whether use one broadcast message or iterate through  
the motes
+   * @throws MessageSendException if an error occured (message is failed  
to send)
+   */
+  public void setup(final SetupT config, final boolean use_bcast) throws  
MessageSendException {
+    this.results.setConfig(config);
+
+    // Create an appropriate setup message
+    SetupMsgT smsg = new SetupMsgT();
+
+    smsg.set_config_problem_idx(config.get_problem_idx());
+    smsg.set_config_pre_run_msec(config.get_pre_run_msec());
+    smsg.set_config_runtime_msec(config.get_runtime_msec());
+    smsg.set_config_post_run_msec(config.get_post_run_msec());
+    smsg.set_config_flags(config.get_flags());
+
+    smsg.set_config_timers_isoneshot(config.get_timers_isoneshot());
+    smsg.set_config_timers_delay(config.get_timers_delay());
+    smsg.set_config_timers_period_msec(config.get_timers_period_msec());
+
+    smsg.set_config_mac_setup(config.get_mac_setup());
+    smsg.set_type(BenchmarkStatic.SETUP_BASE);
+
+   	try {
+      if (use_bcast ){
+        mif.send(MoteIF.TOS_BCAST_ADDR,smsg);
+      } else {
+        currentMote = 1;
+        while ( currentMote <= maxMoteId )
+          mif.send(currentMote++,smsg);
+      }
+      Thread.sleep((int)(500));
+		} catch(Exception e) {
+		  throw new MessageSendException();
+    }
+  }
+
+  /**
+   * Synchronize all motes in the network having mote id from 1 to
+   * the 'motecount' value specified either in the constructor or set by  
the
+   * setMoteCount setter method.
+   *
+   * By synchronizing, we can detect failed motes (not answering),  
improperly
+   * configured motes (wrong answers), and get the real motecount based on  
the
+   * active benchmark configured in the network.
+   *
+   * @throws CommunicationException if synchronization error happens
+   */
+  public void syncAll() throws CommunicationException {
+    currentMote = 1;
+    while ( currentMote <= maxMoteId ) {
+      if ( !sync(currentMote) ) {
+        throw new CommunicationException(
+                "Synchronization Error with Mote ID: " + currentMote + "."  
+
+                " -- Possible reasons: Bad benchmark ID, Mote not  
operational, not configured (Only LED 1 On), or badly configured (No LEDS  
On)"
+                );
+      }
+      else
+        ++currentMote;
+    }
+  }
+
+  /**
+   * Send a SETUP_SYN control message to the specified mote.
+   * It is a direct addressing message, so only the specified mote should
+   * receive, and answer it.
+   *
+   * The handshake is probed MAXPROBES times using MAXTIMEOUT waiting for  
each.
+   *
+   * @param moteId The mote's id whom to send the synchronization request.
+   * @return TRUE if the mote answered to our sync request, FALSE otherwise
+   */
+  public boolean sync(final int moteId) {
+
+    // Create a SYNC-request control message
+    CtrlMsgT cmsg = new CtrlMsgT();
+    cmsg.set_type(BenchmarkStatic.CTRL_SETUP_SYN);
+
+    lock.lock();
+    handshake = false;
+    for( short probe = 0; !handshake && probe < MAXPROBES; ++probe ) {
+      try {
+ 	  	  mif.send(moteId,cmsg);
+ 	  	  answered.await(MAXTIMEOUT,TimeUnit.MILLISECONDS);
+ 	    } catch(Exception e) {
+        break;
+      }
+    }
+    lock.unlock();
+    return handshake;
+  }
+
+  /**
+   * Send a START control message to the network.
+   * It is a broadcast message, so every mote should receive it.
+   *
+   * @param use_bcast Whether use one broadcast message or iterate through  
the motes
+   * @throws MessageSendException if an error occured (message is failed  
to send)
+   */
+  public void run(final boolean use_bcast) throws MessageSendException {
+
+    // Create a START control message
+    CtrlMsgT cmsg = new CtrlMsgT();
+    cmsg.set_type(BenchmarkStatic.CTRL_START);
+
+    try {
+      if (use_bcast ){
+        mif.send(MoteIF.TOS_BCAST_ADDR,cmsg);
+      } else {
+        currentMote = 1;
+        while ( currentMote <= maxMoteId )
+          mif.send(currentMote++,cmsg);
+      }
+      // Wait for test completion + 100 msecs
+      Thread.sleep(
+              (int)(BenchmarkCommons.getRuntime(this.results.getConfig())  
+ 100)
+              );
+		} catch(Exception e) {
+      throw new MessageSendException();
+    }
+  }
+
+  /**
+   * Download the statistics from the motes.
+   *
+   * @throws CommunicationException
+   */
+  public void download_stat() throws CommunicationException
+	{
+    for ( currentMote = 1; currentMote <= maxMoteId ; ++currentMote ) {
+      for ( currentData = 0; currentData < edgecount; ++currentData ) {
+        if  
( !requestData(currentMote,currentData,BenchmarkStatic.CTRL_STAT_REQ) ) {
+          throw new CommunicationException(
+                "Download Error with Mote ID: " + currentMote +
+                ", stat index: " + currentData + "."
+                );
+
+        }
+      }
+    }
+	}
+
+  /**
+   * Download the profile information from the motes.
+   *
+   * @throws CommunicationException
+   */
+  public void download_profile() throws CommunicationException
+	{
+    for (currentMote = 1; currentMote <= maxMoteId; ++currentMote) {
+      if (!requestData(currentMote, currentData,  
BenchmarkStatic.CTRL_PROFILE_REQ)) {
+        throw new CommunicationException(
+                "Download Debug Error with Mote ID: " + currentMote + ".");
+      }
+    }
+
+	}
+
+  /**
+   * Send a data requesting control message to a specific mote with a  
specified
+   * data index. Data can be either the statistics on a specific edge, or  
the debug
+   * information on the mote.
+   *
+   * @param moteId The mote we are targeting
+   * @param dataidx The index of the data (only used when statistics are  
downloaded)
+   * @param type BenchmarkStatic.CTRL_STAT_REQ or  
BenchmarkStatic.CTRL_DBG_REQ
+   * @return TRUE if data has been received, FALSE otherwise
+   */
+  private boolean requestData(final int moteId, final short dataidx, final  
short type) {
+
+    // Create a download request control message
+    CtrlMsgT cmsg = new CtrlMsgT();
+    cmsg.set_type(type);
+    cmsg.set_data_req_idx(dataidx);
+
+    lock.lock();
+    handshake = false;
+    for( short probe = 0; !handshake && probe < MAXPROBES; ++probe ) {
+      try {
+ 	  	  mif.send(moteId,cmsg);
+ 	  	  answered.await(MAXTIMEOUT,TimeUnit.MILLISECONDS);
+ 	    } catch(Exception e) {
+        break;
+      }
+    }
+    lock.unlock();
+    return handshake;
+  }
+
+  /**
+   * The event which is triggered on message reception. We can receive  
messages
+   * in two situations:
+   *  - either in the synchronization phase (sync acknowledgements)
+   *  - or in the downloading phases (stats or debug info)
+   *
+   * @param dest_addr The source mote id of the message
+   * @param msg The message received
+   */
+  public void messageReceived(int dest_addr,Message msg)
+	{
+	  lock.lock();
+    // Received a SyncMsgT
+    if ( msg instanceof SyncMsgT ) {
+      SyncMsgT smsg = (SyncMsgT)msg;
+      if ( smsg.get_type() == BenchmarkStatic.SYNC_SETUP_ACK ) {
+        handshake = true;
+        edgecount = smsg.get_edgecnt();
+        if ( smsg.get_maxmoteid() > maxMoteId )
+          maxMoteId = smsg.get_maxmoteid();
+
+        // update the results structure
+        this.results.cleanResize(maxMoteId, edgecount);
+        answered.signal();
+
+      }
+    // Received a DataMsgT
+    } else if ( msg instanceof DataMsgT ) {
+
+      DataMsgT rmsg = (DataMsgT) msg;
+      switch (rmsg.get_type()) {
+        case BenchmarkStatic.DATA_STAT_OK:
+          // Process the message only if this message is the answer for  
our query
+          // This prevents us from makeing corrupt statistics.
+          if (currentData == rmsg.get_data_idx()) {
+            this.results.appendStatFromMessage(currentData, rmsg);
+          }
+          break;
+        case BenchmarkStatic.DATA_PROFILE_OK:
+          this.results.appendProfileFromMessage(currentMote, rmsg);
+          break;
+      }
+      handshake = true;
+      answered.signal();
+    }
+    lock.unlock();
+	}
+}
=======================================
--- /dev/null
+++  
/trunk/apps/tests/LinkBench/javasrc/benchmark/common/BenchmarkResult.java	 
Tue Sep  6 00:34:50 2011
@@ -0,0 +1,273 @@
+/*
+* Copyright (c) 2010, University of Szeged
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* - Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* - Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* - Neither the name of University of Szeged nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+* OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Author: Krisztian Veress
+*         veresskrisztian at gmail.com
+*/
+package benchmark.common;
+
+import java.io.PrintStream;
+import java.util.Calendar;
+import java.util.Vector;
+
+/**
+ * This class holds all the results of a benchmark run along with the  
computed
+ * statistics and any error which may occur during the test run.
+ *
+ */
+public class BenchmarkResult {
+
+  private SetupT            config;
+  private Vector<StatT>     stats;
+  private Vector<ProfileT>  profiles;
+  private String            error;
+
+  /**
+   * Basic constuctor of a result holder.
+   */
+  public BenchmarkResult() {
+    this.init(null);
+  }
+
+  /**
+   * Construct a result holder with a known configuration.
+   * @param config the configuration
+   */
+  public BenchmarkResult(final SetupT config) {
+    this.init(config);
+  }
+
+  /**
+   * Helper function for constructors
+   * @param config the configuration
+   */
+  private void init(final SetupT config) {
+    this.config = config;
+    this.stats = null;
+    this.profiles = null;
+    this.error = "";
+  }
+
+  /**
+   * Clean the result holder object and make it ready for a new benchmark.
+   *
+   * @param motecount the new benchmark's motecount
+   * @param edgecount the new benchmark's edgecount
+   */
+  public void cleanResize(final int motecount, final int edgecount) {
+    if ( this.stats != null ) {
+      this.stats.clear();
+      this.profiles.clear();
+    }
+
+    this.stats = new Vector(edgecount);
+    this.profiles = new Vector(motecount);
+
+    // Initialize the elements
+    for (int i = 0; i< edgecount; ++i ) {
+      this.stats.add(new StatT());
+    }
+
+    // Initialize the elements
+    for (int i = 0; i< motecount; ++i ) {
+      this.profiles.add(new ProfileT());
+    }
+
+    this.error = "";
+  }
+
+  /**
+   * Set the configuration of the benchmark for the results holder object.
+   * @param config the configuration
+   */
+  public void setConfig(final SetupT config) {
+    this.config = config;
+  }
+
+  /**
+   * Get the actual benchmark result's configuration
+   * @return the configuration
+   */
+  public SetupT getConfig() {
+    return config;
+  }
+
+  /**
+   * Set an error indicating that an error occured durint the test run.
+   * @param error the string representation of the error
+   */
+  public void setError(final String error) {
+    this.error = error;
+  }
+
+  /**
+   * Get the error which may have occured.
+   * @return the string representation of the error
+   */
+  public String getError() {
+    return this.error;
+  }
+
+  /**
+   * Append new profile information to existing ones from a message.
+   * Note that the message does not contain the sender's id, that is why
+   * we must explicitly specify it for this function.
+   *
+   * @param idx the mote's id to which this information belongs
+   * @param msg the message holding the information
+   */
+  public void appendProfileFromMessage(final int idx, final DataMsgT msg) {
+
+    // Get the new Profile from the message
+    ProfileT p = new ProfileT();
+    p.set_max_atomic(msg.get_payload_profile_max_atomic());
+    p.set_max_interrupt(msg.get_payload_profile_max_interrupt());
+    p.set_max_latency(msg.get_payload_profile_max_latency());
+    p.set_min_atomic(msg.get_payload_profile_min_atomic());
+    p.set_min_interrupt(msg.get_payload_profile_min_interrupt());
+    p.set_min_latency(msg.get_payload_profile_min_latency());
+
+    p.set_rtx_time(msg.get_payload_profile_rtx_time());
+    p.set_rstart_count(msg.get_payload_profile_rstart_count());
+    p.set_rx_bytes(msg.get_payload_profile_rx_bytes());
+    p.set_tx_bytes(msg.get_payload_profile_tx_bytes());
+    p.set_rx_msgs(msg.get_payload_profile_rx_msgs());
+    p.set_debug(msg.get_payload_profile_debug());
+
+    this.profiles.set(idx-1, p);
+  }
+
+  /**
+   * Append new statistics to existing ones from a message.
+   * Note that the message does not contain the sender's id, that is why
+   * we must explicitly specify it for this function.
+   *
+   * @param idx the mote's id to which this information belongs
+   * @param msg the message holding the information
+   */
+  public void appendStatFromMessage(final int idx, final DataMsgT msg) {
+
+    // Get the new Stat from the message
+    StatT s = new StatT();
+    s.set_triggerCount(msg.get_payload_stat_triggerCount());
+    s.set_backlogCount(msg.get_payload_stat_backlogCount());
+    s.set_resendCount(msg.get_payload_stat_resendCount());
+    s.set_sendCount(msg.get_payload_stat_sendCount());
+    s.set_sendSuccessCount(msg.get_payload_stat_sendSuccessCount());
+    s.set_sendFailCount(msg.get_payload_stat_sendFailCount());
+
+    s.set_sendDoneCount(msg.get_payload_stat_sendDoneCount());
+     
s.set_sendDoneSuccessCount(msg.get_payload_stat_sendDoneSuccessCount());
+    s.set_sendDoneFailCount(msg.get_payload_stat_sendDoneFailCount());
+
+    s.set_wasAckedCount(msg.get_payload_stat_wasAckedCount());
+    s.set_notAckedCount(msg.get_payload_stat_notAckedCount());
+
+    s.set_receiveCount(msg.get_payload_stat_receiveCount());
+    s.set_consecutiveCount(msg.get_payload_stat_consecutiveCount());
+    s.set_wrongCount(msg.get_payload_stat_wrongCount());
+    s.set_duplicateCount(msg.get_payload_stat_duplicateCount());
+    s.set_missedCount(msg.get_payload_stat_missedCount());
+    s.set_forwardCount(msg.get_payload_stat_forwardCount());
+
+    s.set_remainedCount(msg.get_payload_stat_remainedCount());
+
+    // Get the current stat
+    StatT s1 = this.stats.get(idx);
+
+    // Make a new stat - this will be the merginf of the current and the  
new one.
+    StatT news = new StatT();
+
+    news.set_triggerCount(         s1.get_triggerCount()          +    
s.get_triggerCount());
+    news.set_backlogCount(         s1.get_backlogCount()          +    
s.get_backlogCount());
+    news.set_resendCount(          s1.get_resendCount()           +    
s.get_resendCount());
+    news.set_sendCount(            s1.get_sendCount()             +    
s.get_sendCount());
+    news.set_sendSuccessCount(     s1.get_sendSuccessCount()      +    
s.get_sendSuccessCount());
+    news.set_sendFailCount(        s1.get_sendFailCount()         +    
s.get_sendFailCount());
+
+    news.set_sendDoneCount(        s1.get_sendDoneCount()         +    
s.get_sendDoneCount());
+    news.set_sendDoneSuccessCount( s1.get_sendDoneSuccessCount()  +    
s.get_sendDoneSuccessCount());
+    news.set_sendDoneFailCount(    s1.get_sendDoneFailCount()     +    
s.get_sendDoneFailCount());
+
+    news.set_wasAckedCount(        s1.get_wasAckedCount()         +    
s.get_wasAckedCount());
+    news.set_notAckedCount(        s1.get_notAckedCount()         +    
s.get_notAckedCount());
+
+    news.set_receiveCount(         s1.get_receiveCount()          +    
s.get_receiveCount());
+    news.set_consecutiveCount(        s1.get_consecutiveCount()          
+   s.get_consecutiveCount());
+    news.set_wrongCount(           s1.get_wrongCount()            +    
s.get_wrongCount());
+    news.set_duplicateCount(       s1.get_duplicateCount()        +    
s.get_duplicateCount());
+    news.set_missedCount(          s1.get_missedCount()           +    
s.get_missedCount());
+    news.set_forwardCount(         s1.get_forwardCount()          +    
s.get_forwardCount());
+
+    news.set_remainedCount((short)(s1.get_remainedCount()         +    
s.get_remainedCount()));
+
+    this.stats.set(idx, news);
+  }
+
+  /**
+   * Print the current result's configuration into a character stream.
+   *
+   * @param stream the stream
+   */
+  public void printConfig(PrintStream stream) {
+    stream.println(BenchmarkCommons.setupAsString(this.config));
+  }
+
+  /**
+   * Print the current results with debug and error information into a  
character
+   * stream.
+   *
+   * @param stream the stream
+   */
+  public void print(PrintStream stream) {
+    stream.println(BenchmarkCommons.setupAsString(this.config));
+    stream.println(BenchmarkCommons.statsAsString(this.stats));
+    stream.println(BenchmarkCommons.profilesAsString(this.profiles));
+    stream.println(BenchmarkCommons.errorAsString(this.error));
+  }
+
+  /**
+   * Print the current results with debug and error information into a  
character
+   * stream with XML formatting.
+   *
+   * @param stream the stream
+   */
+  public void printXml(PrintStream stream) {
+    Calendar calendar = Calendar.getInstance();
+    stream.println("<testresult date=\"" + calendar.getTime().toString()  
+ "\">");
+    stream.println(BenchmarkCommons.setupAsXml(this.config));
+    stream.println(BenchmarkCommons.statsAsXml(this.stats));
+    stream.println(BenchmarkCommons.profilesAsXml(this.profiles));
+    stream.println(BenchmarkCommons.errorAsXml(this.error));
+    stream.println("</testresult>");
+  }
+
+}
=======================================
--- /dev/null
+++ /trunk/apps/tests/LinkBench/javasrc/benchmark/common/MacParser.java	Tue  
Sep  6 00:34:50 2011
@@ -0,0 +1,162 @@
+/*
+* Copyright (c) 2010, University of Szeged
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* - Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* - Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* - Neither the name of University of Szeged nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+* OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Author: Krisztian Veress
+*         veresskrisztian at gmail.com
+*/
+package benchmark.common;
+
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+
+public class MacParser {
+
+  private int macparams[];
+  private short flags;
+
+  public class MacParserException extends Exception {
+    public MacParserException(String msg) { super(msg); }
+  }
+
+  public MacParser() {
+    this.macparams = new int[BenchmarkStatic.MAC_SETUP_LENGTH];
+    this.flags = 0;
+    for (int i = 0; i < BenchmarkStatic.MAC_SETUP_LENGTH; ++i) {
+      this.macparams[i] = 0;
+    }
+  }
+
+  public void parse(final String spec) throws MacParserException {
+
+    Pattern pattern = Pattern.compile("^(\\w+):([\\d+,]+)$");
+    Matcher matcher = pattern.matcher(spec);
+
+    if (matcher.find()) {
+      this.parseAll(matcher.group(1),matcher.group(2).split(","));
+
+    } else {
+      throw new MacParserException("Invalid MAC parameter specification,  
see help!");
+    }
+  }
+
+  public void parseAll(final String type, final String[] params) throws  
MacParserException {
+    int[] iparams = new int[params.length];
+    for(byte i=0; i< params.length; ++i)
+      iparams[i] = Integer.parseInt(params[i]);
+
+    this.parseAll(type, iparams);
+  }
+
+  public void parseAll(final String type, final int[] params) throws  
MacParserException {
+    this.parseLPL(type, params);
+    this.parsePacketLink(type, params);
+
+    if ( (this.flags & (this.flags - 1)) != 0)
+      throw new MacParserException("Only one MAC protocol is allowed!");
+
+  }
+
+  public static String macAsString(final short flags, final int[] params) {
+    String nl = System.getProperty("line.separator");
+
+    return  LPLasString(flags,params) + nl +
+            PacketLinkasString(flags,params) + nl;
+  }
+
+  public static String macAsXml(final short flags, final int[] params) {
+    String nl = System.getProperty("line.separator");
+
+    return "<mac>" +
+            LPLasXml(flags,params) +
+            PacketLinkasXml(flags,params) +
+            "</mac>" + nl;
+  }
+
+  private void parseLPL(final String type, final int[] params) throws  
MacParserException {
+    if ( type.equals("lpl") ) {
+      if (params.length != 1) {
+        throw new MacParserException(
+                "LPL MAC requires exactly one parameter ( Wakeup interval  
(ms) )!");
+      }
+      flags |= BenchmarkStatic.GLOBAL_USE_MAC_LPL;
+      this.macparams[BenchmarkStatic.LPL_WAKEUP_OFFSET] = params[0];
+    }
+  }
+
+  private static String LPLasString(final short flags, final int[] params)  
{
+    String ret="";
+    if ((flags & BenchmarkStatic.GLOBAL_USE_MAC_LPL) != 0) {
+      ret = "  LPL: \t\t" + params[0] + " ms";
+    }
+    return ret;
+  }
+
+  private static String LPLasXml(final short flags, final int[] params) {
+    String ret="";
+    if ((flags & BenchmarkStatic.GLOBAL_USE_MAC_LPL) != 0) {
+      ret = "<lpl wakeup=\"" + params[0] + "\"/>";
+    }
+    return ret;
+  }
+
+  private void parsePacketLink(final String type, final int[] params)  
throws MacParserException {
+    if ( type.equals("plink") ) {
+      if (params.length != 2) {
+        throw new MacParserException(
+                "Packet Link MAC requires exactly two parameters ( Retries  
(ms) + Delay (ms) )!");
+      }
+      flags |= BenchmarkStatic.GLOBAL_USE_MAC_PLINK;
+      this.macparams[BenchmarkStatic.PLINK_RETRIES_OFFSET] = params[0];
+      this.macparams[BenchmarkStatic.PLINK_DELAY_OFFSET] = params[1];
+    }
+  }
+
+  private static String PacketLinkasString(final short flags, final int[]  
params) {
+    String ret="";
+    if ((flags & BenchmarkStatic.GLOBAL_USE_MAC_PLINK) != 0) {
+      ret = "  Packet Link:  Retries: " + params[0] + " ms, Delay: " +  
params[0] + " ms";
+    }
+    return ret;
+  }
+
+  private static String PacketLinkasXml(final short flags, final int[]  
params) {
+    String ret="";
+    if ((flags & BenchmarkStatic.GLOBAL_USE_MAC_PLINK) != 0) {
+      ret = "<plink retries=\"" + params[0] + "\" delay=\"" + params[1]  
+ "\"/>";
+    }
+    return ret;
+  }
+
+
+  public int[]  getMacParams()    { return macparams;     }
+  public short  getFlags()        { return flags;         }
+
+}
=======================================
--- /dev/null
+++ /trunk/apps/tests/LinkBench/javasrc/benchmark/common/TimerParser.java	 
Tue Sep  6 00:34:50 2011
@@ -0,0 +1,115 @@
+/*
+* Copyright (c) 2010, University of Szeged
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* - Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* - Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* - Neither the name of University of Szeged nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+* OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Author: Krisztian Veress
+*         veresskrisztian at gmail.com
+*/
+package benchmark.common;
+
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+
+public class TimerParser {
+
+  private short ios[];
+  private long  delay[];
+  private long  period[];
+  private byte  maxtimer = 0;
+
+  public static final short   DEF_TIMER_ONESHOT = 1;
+  public static final short   DEF_TIMER_DELAY   = 0;
+  public static final short   DEF_TIMER_PERIOD  = 100;
+
+  public class TimerParserException extends Exception {
+    public TimerParserException(String msg) { super(msg); }
+  }
+
+  public TimerParser(final byte maxtimercount) {
+
+    this.maxtimer = maxtimercount;
+
+    this.ios = new short[maxtimercount];
+    this.delay = new long[maxtimercount];
+    this.period = new long[maxtimercount];
+
+    for (int i = 0; i < maxtimercount; ++i) {
+      this.ios[i]    = DEF_TIMER_ONESHOT;
+      this.delay[i]  = DEF_TIMER_DELAY;
+      this.period[i] = DEF_TIMER_PERIOD;
+    }
+  }
+
+  public void parse(final String spec) throws TimerParserException {
+
+    Pattern pattern = Pattern.compile("(\\d+):(\\d+),(\\d+),(\\d+)");
+    Matcher matcher = pattern.matcher(spec);
+
+    if (matcher.find()) {
+      int trigidx = Integer.parseInt(matcher.group(1));
+
+      if (trigidx < 1 || trigidx > this.maxtimer) {
+        throw new TimerParserException("Valid timer indexes are : [1.." +  
this.maxtimer + "]!");
+      }
+      --trigidx;
+
+      this.ios[trigidx] = (byte) Integer.parseInt(matcher.group(2));
+
+      this.delay[trigidx] = Integer.parseInt(matcher.group(3));
+      this.period[trigidx] = Integer.parseInt(matcher.group(4));
+
+      if (  this.period[trigidx] < 0 ||
+            this.delay[trigidx] < 0 ||
+            this.ios[trigidx] < 0 ||
+            this.ios[trigidx] > 1) {
+        throw new TimerParserException("Trigger timer " + (trigidx + 1)  
+ " is invalid!");
+      }
+
+      // at time 0, only one-shot timers are allowed to fire
+      if ( this.period[trigidx] == 0 && this.ios[trigidx] != 1) {
+        throw new TimerParserException("Only one-shot timers are allowed  
with 0 ms period!");
+      }
+
+    } else {
+      throw new TimerParserException("Invalid spec timer specification!");
+    }
+  }
+
+  public void setSpec(final byte idx,final short ios,final long delay,  
final long period) {
+    this.ios[idx] = ios;
+    this.delay[idx] = delay;
+    this.period[idx] = period;
+  }
+
+  public short[]  getIos()    { return ios;     }
+  public long[]   getDelay()  { return delay;   }
+  public long[]   getPeriod() { return period;  }
+
+}
=======================================
--- /dev/null
+++ /trunk/apps/tests/LinkBench/javasrc/build.xml	Tue Sep  6 00:34:50 2011
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="LinkBench" default="dist" basedir=".">
+  <description>LinkBench ANT script</description>
+
+  <!-- set global properties for this build -->
+  <property name="base" location="${basedir}/benchmark"/>
+  <property name="dist-addon" location="${basedir}/dist-addon"/>
+
+  <property name="src-cli" location="${base}/cli"/>
+  <property name="src-common" location="${base}/common"/>
+
+  <property name="build" location="${basedir}/build"/>
+  <property name="dist"  location="${basedir}/../javabin"/>
+  <property name="lib" location="${dist}/lib"/>
+
+  <property name="java-package" value="benchmark.common"/>
+
+  <property environment="env"/>
+  <property name="jar-tinyos"  
location="${env.TOSROOT}/support/sdk/java/tinyos.jar"/>
+
+  <path id="classpath">
+    <pathelement location="${build}"/>
+    <fileset dir="${lib}" includes="**/*.jar"/>
+    <fileset file="${jar-tinyos}"/>
+  </path>
+
+  <target name="-check-init-build-done">
+    <available property="init.build.done" file="${build}"/>
+  </target>
+
+  <target name="-check-init-dist-done">
+    <available property="init.dist.done" file="${dist}"/>
+  </target>
+
+  <target name="-check-compile-common">
+    <available property="compile.common" file="${build}/benchmark/common"/>
+  </target>
+
+  <target name="-init-build" depends="-check-init-build-done"  
unless="init.build.done">
+    <echo level="info" message="Creating build environment"/>
+    <mkdir dir="${build}"/>
+  </target>
+
+  <target name="-init-dist" depends="-check-init-dist-done"  
unless="init.dist.done">
+    <echo level="info" message="Creating dist environment"/>
+    <mkdir dir="${dist}"/>
+    <copy todir="${dist}" >
+      <fileset dir="${dist-addon}" />
+    </copy>
+  </target>
+
+  <target name="-init-mig">
+		<echo message="Generating TinyOS message classes (Mig)" />
+
+		<exec executable="mig" failonerror="true">
+			<arg value="-target=iris" />
+			<arg value="-o" />
+			<arg path="${src-common}/StatT.java" />
+			<arg value="-java-classname=${java-package}.StatT" />
+			<arg value="java" />
+			<arg path="${basedir}/../BenchmarkCore.h" />
+			<arg value="stat_t" />
+		</exec>
+
+		<exec executable="mig" failonerror="true">
+			<arg value="-target=iris" />
+			<arg value="-o" />
+			<arg path="${src-common}/ProfileT.java" />
+			<arg value="-java-classname=${java-package}.ProfileT" />
+			<arg value="java" />
+			<arg path="${basedir}/../BenchmarkCore.h" />
+			<arg value="profile_t" />
+		</exec>
+
+		<exec executable="mig" failonerror="true">
+			<arg value="-target=iris" />
+			<arg value="-o" />
+			<arg path="${src-common}/SetupT.java" />
+			<arg value="-java-classname=${java-package}.SetupT" />
+			<arg value="java" />
+			<arg path="${basedir}/../BenchmarkCore.h" />
+			<arg value="setup_t" />
+		</exec>
+
+		<exec executable="mig" failonerror="true">
+			<arg value="-target=iris" />
+			<arg value="-o" />
+			<arg path="${src-common}/CtrlMsgT.java" />
+			<arg value="-java-classname=${java-package}.CtrlMsgT" />
+			<arg value="java" />
+			<arg path="${basedir}/../Messages.h" />
+			<arg value="ctrlmsg_t" />
+		</exec>
+
+		<exec executable="mig" failonerror="true">
+			<arg value="-target=iris" />
+			<arg value="-o" />
+			<arg path="${src-common}/SyncMsgT.java" />
+			<arg value="-java-classname=${java-package}.SyncMsgT" />
+			<arg value="java" />
+			<arg path="${basedir}/../Messages.h" />
+			<arg value="syncmsg_t" />
+		</exec>
+
+		<exec executable="mig" failonerror="true">
+			<arg value="-target=iris" />
+			<arg value="-o" />
+			<arg path="${src-common}/SetupMsgT.java" />
+			<arg value="-java-classname=${java-package}.SetupMsgT" />
+			<arg value="java" />
+			<arg path="${basedir}/../Messages.h" />
+			<arg value="setupmsg_t" />
+		</exec>
+
+		<exec executable="mig" failonerror="true">
+			<arg value="-target=iris" />
+			<arg value="-o" />
+			<arg path="${src-common}/DataMsgT.java" />
+			<arg value="-java-classname=${java-package}.DataMsgT" />
+			<arg value="java" />
+			<arg path="${basedir}/../Messages.h" />
+			<arg value="datamsg_t" />
+		</exec>
+
+		<exec executable="ncg" failonerror="true">
+			<arg line="-target=iris -o ${src-common}/BenchmarkStatic.java  
-java-classname=${java-package}.BenchmarkStatic java  
${basedir}/../Messages.h MAX_TIMER_COUNT SETUP_BASE CTRL_SETUP_SYN  
SYNC_SETUP_ACK CTRL_START CTRL_RESET CTRL_STAT_REQ DATA_STAT_OK  
CTRL_PROFILE_REQ DATA_PROFILE_OK GLOBAL_USE_ACK GLOBAL_USE_BCAST  
GLOBAL_USE_MAC_LPL GLOBAL_USE_MAC_PLINK LPL_WAKEUP_OFFSET  
PLINK_RETRIES_OFFSET PLINK_DELAY_OFFSET MAC_SETUP_LENGTH" />
+		</exec>
+
+	</target>
+
+  <target name="init" depends="-init-build,-init-dist,-init-mig" />
+
+  <target name="-clean-build">
+    <delete dir="${build}"/>
+  </target>
+
+  <target name="-clean-mig">
+  	<delete>
+    	<fileset dir="${src-common}" includes="**/*T.java"/>
+  	</delete>
+    <delete file="${src-common}/BenchmarkStatic.java"/>
+  </target>
+
+  <target name="-clean-dist">
+    <input
+      message="All data is going to be deleted from ${dist}. It is  
possible that results live there. Continue (y/n)?"
+      validargs="y,n"
+      addproperty="do.delete"
+    />
+    <condition property="do.abort">
+      <equals arg1="n" arg2="${do.delete}"/>
+    </condition>
+    <fail if="do.abort">Clean task aborted by user.</fail>
+    <delete dir="${dist}"/>
+  </target>
+
+  <target name="clean" depends="-clean-build,-clean-dist,-clean-mig"  
description="clean up" />
+
+
+  <target name="compile-common" depends="-check-compile-common,init"  
unless="compile.common" description="compile the Common library code">
+    <javac srcdir="${src-common}" destdir="${build}"  
classpathref="classpath"/>
+  </target>
+
+  <target name="compile-cli" depends="init,compile-common"  
description="compile the CLI code">
+    <javac srcdir="${src-cli}" destdir="${build}"  
classpathref="classpath"/>
+  </target>
+
+  <target name="jar-common" depends="compile-common" description="make the  
Common jar">
+    <jar destfile="${lib}/benchmark-common.jar" basedir="${build}"  
includes="**/common/**">
+      <manifest>
+        <attribute name="Class-Path" value="${jar-tinyos}  
snakeyaml-1.7.jar"/>
+      </manifest>
+    </jar>
+  </target>
+
+  <target name="jar-cli" depends="compile-cli" description="make the CLI  
jar">
+    <jar destfile="${dist}/linkbench.jar" basedir="${build}"  
includes="**/cli/**">
+      <manifest>
+        <attribute name="Main-Class" value="benchmark.cli.BenchmarkCli"/>
+        <attribute name="Class-Path" value="lib/benchmark-common.jar  
lib/commons-cli-1.2.jar"/>
+      </manifest>
+    </jar>
+  </target>
+
+  <target name="dist" depends="jar-common,jar-cli,-clean-build"  
description="generate the distribution" >
+  </target>
+
+
+</project>
=======================================
--- /dev/null
+++ /trunk/apps/tests/LinkBench/javasrc/dist-addon/README.TXT	Tue Sep  6  
00:34:50 2011
@@ -0,0 +1,36 @@
+Howto run the LinkBench application
+-----------------------------------
+
+I. Windows users:
+---------------------
+   1, You should start a command line tool by clicking on Start->Run and  
entering cmd.exe .
+   2, Then, navigate to the directory where this (README.TXT) file is  
located.
+   3, Type the following in the command line for more instructions :
+      java -jar linkbench.jar --help
+
+II. Unix/Linux users:
+---------------------
+   1, Open a terminal (xterm, gnome-terminal, etc) and navigate to the  
directory where this
+      (README.TXT) file is located.
+
+   2/a, Type the following in the command line for more instructions :
+          java -jar linkbench.jar --help
+
+   2/b, First make the bmark.sh file executable, and start the application  
after :
+          chmod u+x linkbench.sh
+          ./linkbench.sh --help
+
+Troubleshooting:
+----------------
+   1, Problem : The linkbench.jar file does not exist.
+      Solution: Maybe you forgot to compile the sources, or deleted that  
file. You should re-compile the Java
+                sources (and possibly the TinyOS sources). For  
instructions, see the README file in the root
+                directory of the application.
+
+   2, Problem : There is no such command as 'java'.
+      Solution: You must install the Java SDK 1.6 to be able to compile  
and run this application. Once you
+                have it, follow the instruction in the README file in the  
root directory of the application.
+
+   3, Problem : I have read all READMEs, instructions, but I cannot  
overcome my specific problem.
+      Solution: Write me an email (verkri at inf.u-szeged.hu) describing your  
system ( platform, JDK version,
+                TinyOS version, where you have installed the application,  
etc).
=======================================
--- /dev/null
+++ /trunk/apps/tests/LinkBench/javasrc/dist-addon/assets/benchmark.css	Tue  
Sep  6 00:34:50 2011
@@ -0,0 +1,141 @@
+body {
+  font: 13px sans-serif;
+  background-color: #DDDDDD;
+  margin: 0px 5px 0px 5px;
+}
+
+div.title {
+  font: 15px sans-serif;
+  font-weight: bold;
+  background-color: #798EF9;
+  text-align: center;
+  margin-top: 0; margin-bottom: 0;
+  padding: 1px 1px 1px 1px;
+  color: #000000;
+}
+
+div.title_light {
+  font: 15px sans-serif;
+  font-weight: bold;
+  text-align: center;
+  margin-top: 0; margin-bottom: 0;
+  padding: 1px 1px 1px 1px;
+  color: #000000;
+}
+
+div.debuglist, div.error {
+  margin-top: 5px;
+  text-align: center;
+}
+
+table.testresult {
+  margin-bottom: 10px;
+  border: 0px;
+  border-spacing: 0px;
+  border-padding: 0px;
+  width: 100%;
+}
+
+table.summary, table.data {
+  margin: 2px 0px 0px 0px;
+  border: 1px solid #888888;
+  width: 100%;
+  border-spacing: 1px;
+  border-padding: 0px;
+}
+
+.rt {
+  background-color: white;
+  text-align: right;
+  font: 11px sans-serif;
+  padding-right: 5px;
+}
+
+.rt_data {
+  background-color: white;
+  text-align: center;
+  font: 13px sans-serif;
+  font-weight: bold;
+}
+
+.rcv {
+  color: #770202;
+}
+.snd {
+  color: #027702;
+}
+
+.cprofile {
+  color: #33469A;
+}
+
+.rprofile {
+  color: #554666;
+}
+
+.title_send {
+  background-color: #ACF979;
+  font: 13px sans-serif;
+  font-weight: bold;
+  text-align: center;
+  border-style: solid;
+  border-width: 0px 0px 1px 0px;
+}
+
+.title_rcv {
+  background-color: #FFA579;
+  font: 13px sans-serif;
+  font-weight: bold;
+  text-align: center;
+  border-style: solid;
+  border-width: 0px 0px 1px 0px;
+}
+
+.title_cprofile {
+  background-color: #5579BC;
+  font: 13px sans-serif;
+  font-weight: bold;
+  text-align: center;
+  border-style: solid;
+  border-width: 0px 0px 1px 0px;
+}
+
+.title_rprofile {
+  background-color: #887999;
+  font: 13px sans-serif;
+  font-weight: bold;
+  text-align: center;
+  border-style: solid;
+  border-width: 0px 0px 1px 0px;
+}
+
+.sub {
+  background-color: #FFF3A0;
+  font: 11px sans-serif;
+  text-align: center;
+}
+
+div.top {
+  text-align : center;
+  font: 18px sans-serif;
+  font-weight: bold;
+  margin-bottom: 10px;
+}
+
+span.debug_ok {
+  color: #027702;
+  padding-left: 5px;
+  padding-right: 5px;
+  font-weight: bold;
+}
+
+span.debug_fail, div.error {
+  color: #770202;
+  padding-left: 5px;
+  padding-right: 5px;
+  font-weight: bold;
+}
+a { font: 11px verdana, arial, helvetica, sans-serif; }
+a:link    { color: #0011BB; text-decoration: none; }
+a:visited { color: #0011BB; text-decoration: none; }
+a:hover   { color: #605040; text-decoration: underline; }
=======================================
--- /dev/null
+++ /trunk/apps/tests/LinkBench/javasrc/dist-addon/assets/benchmark.xsl	Tue  
Sep  6 00:34:50 2011
@@ -0,0 +1,326 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0"  
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<!--<xsl:output indent="yes" method="xml" media-type="text/xhtml"  
omit-xml-declaration="yes" /> -->
+
+<xsl:template match="/">
+<html>
+
+<head>
+<meta name="generator" content="Benchmark result report" />
+<meta name="robots" content="noindex,nofollow" />
+<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+<meta http-equiv="description" content="RadioTest result report" />
+<title>RadioTest result report</title>
+<link rel="stylesheet" href="assets/benchmark.css" type="text/css"/>
+</head>
+
+<body>
+<div class="top"></div>
+<xsl:apply-templates/>
+</body>
+</html>
+</xsl:template>
+
+<xsl:template match="testresult">
+<table class="testresult">
+  <tr valign="top">
+
+    <td width="20%">
+      <div class="title">Testcase</div>
+      <xsl:apply-templates select="configuration"/>
+    </td>
+
+    <td>
+      <div class="title">Statistics (<xsl:value-of select="@date"/>)</div>
+      <table class="data">
+        <tr>
+          <td class="sub"></td>
+          <td class="title_send" colspan="4">&#160;</td>
+          <td class="title_send" colspan="3">send()</td>
+          <td class="title_send" colspan="3">sendDone()</td>
+          <td class="title_send" colspan="2">&#160;</td>
+          <td class="title_rcv" colspan="6">receive()</td>
+        </tr>
+        <tr>
+          <td class="sub"><strong>Edge</strong></td>
+          <td class="sub">Rem</td>
+          <td class="sub">Triggered</td>
+          <td class="sub">Backlog</td>
+          <td class="sub">Resend</td>
+
+          <td class="sub">Total</td>
+          <td class="sub">SUCC</td>
+          <td class="sub">FAIL</td>
+
+          <td class="sub">Total</td>
+          <td class="sub">SUCC</td>
+          <td class="sub">FAIL</td>
+
+          <td class="sub">ACK</td>
+          <td class="sub">noACK</td>
+
+          <td class="sub">Total</td>
+          <td class="sub">Consecutive</td>
+          <td class="sub">Wrong</td>
+          <td class="sub">Duplicate</td>
+          <td class="sub">Forward</td>
+          <td class="sub">Missed</td>
+
+        </tr>
+        <xsl:for-each select="statlist/stat">
+        <tr>
+          <xsl:variable name="curr_idx" select="@idx"/>
+          <td class="sub"><xsl:value-of select="$curr_idx"/></td>
+          <xsl:apply-templates select="current()[@idx=$curr_idx]"/>
+        </tr>
+        </xsl:for-each>
+      </table>
+
+      <table class="data">
+        <tr>
+          <td class="sub"></td>
+          <td class="title_cprofile" colspan="3">Code Profile</td>
+          <td class="title_rprofile" colspan="5">Radio Profile</td>
+          <td class="sub"></td>
+        </tr>
+        <tr>
+          <td class="sub"><strong>Mote</strong></td>
+          <td class="sub">Min/Max Atomic</td>
+          <td class="sub">Min/Max Interrupt</td>
+          <td class="sub">Min/Max Latency</td>
+          <td class="sub">RxTx Time</td>
+          <td class="sub">Radio Start cnt</td>
+          <td class="sub">Total Msg cnt</td>
+          <td class="sub">Rx Bytes</td>
+          <td class="sub">Tx Bytes</td>
+          <td class="sub">Debug</td>
+
+        </tr>
+        <xsl:for-each select="profilelist/profile">
+        <tr>
+          <xsl:variable name="curr_idx" select="@idx"/>
+          <td class="sub"><xsl:value-of select="$curr_idx"/></td>
+          <xsl:apply-templates select="current()[@idx=$curr_idx]"/>
+        </tr>
+        </xsl:for-each>
+      </table>
+
+
+<!-- ERROR CHECKING -->
+
+      <!--<table class="data">
+      <tr>
+        <td class="sub"><strong>Edge</strong></td>
+        <td class="sub">Send (S/F)</td>
+        <td class="sub">sDone(S/F)</td>
+        <td class="sub">ACK</td>
+        <td class="sub">resendC</td>
+        <td class="sub">Recv (E/W)</td>
+        <td class="sub">Wrong (Dupl/Fwd)</td>
+      </tr>
+      <xsl:for-each select="statlist/stat">
+        <tr>
+          <td class="sub"><xsl:value-of select="@idx"/></td>
+
+          <td class="sub">
+          <xsl:choose>
+            <xsl:when test="SC - SSC - SFC = 0"><span  
class="debug_ok">OK</span>
+            </xsl:when>
+            <xsl:otherwise><span class="debug_fail">ERR</span>
+            </xsl:otherwise>
+          </xsl:choose>
+          </td>
+          <td class="sub">
+          <xsl:choose>
+            <xsl:when test="SDC - SDSC - SDFC = 0"><span  
class="debug_ok">OK</span>
+            </xsl:when>
+            <xsl:otherwise><span class="debug_fail">ERR</span>
+            </xsl:otherwise>
+          </xsl:choose>
+          </td>
+          <td class="sub">
+          <xsl:choose>
+            <xsl:when test="../../configuration/ack = 'Off'"><span  
class="debug_ok">-</span>
+            </xsl:when>
+            <xsl:otherwise>
+              <xsl:choose>
+              <xsl:when test="SDSC - WAC - NAC = 0"><span  
class="debug_ok">OK</span>
+              </xsl:when>
+              <xsl:otherwise><span class="debug_fail">ERR</span>
+              </xsl:otherwise>
+              </xsl:choose>
+            </xsl:otherwise>
+          </xsl:choose>
+          </td>
+          <td class="sub">
+          <xsl:choose>
+            <xsl:when test="RC - SFC - SDFC - NAC = 0"><span  
class="debug_ok">OK</span>
+            </xsl:when>
+            <xsl:otherwise><span class="debug_fail">ERR</span>
+            </xsl:otherwise>
+          </xsl:choose>
+          </td>
+
+          <td class="sub">
+          <xsl:choose>
+            <xsl:when test="RCC - EXC - WC = 0"><span  
class="debug_ok">OK</span>
+            </xsl:when>
+            <xsl:otherwise><span class="debug_fail">ERR</span>
+            </xsl:otherwise>
+          </xsl:choose>
+          </td>
+
+          <td class="sub">
+          <xsl:choose>
+            <xsl:when test="WC - DRC - FC = 0"><span  
class="debug_ok">OK</span>
+            </xsl:when>
+            <xsl:otherwise><span class="debug_fail">ERR</span>
+            </xsl:otherwise>
+          </xsl:choose>
+          </td>
+
+        </tr>
+      </xsl:for-each>
+      </table> -->
+
+      <xsl:apply-templates select="error"/>
+
+    </td>
+  </tr>
+</table>
+</xsl:template>
+
+<xsl:template match="configuration">
+      <table class="summary">
+        <tr>
+          <td class="rt" width="80">Problem : </td>
+          <td class="rt_data"><xsl:value-of select="benchidx"/></td>
+        </tr>
+        <tr>
+          <td class="rt">Rand start : </td>
+          <td class="rt_data"><xsl:value-of select="pre_runtime"/> ms</td>
+        </tr>
+        <tr>
+          <td class="rt">Runtime : </td>
+          <td class="rt_data"><xsl:value-of select="runtime"/> ms</td>
+        </tr>
+        <tr>
+          <td class="rt">Lastchance : </td>
+          <td class="rt_data"><xsl:value-of select="post_runtime"/> ms</td>
+        </tr>
+
+        <tr>
+          <td class="rt">Forces : </td>
+          <td class="rt_data">
+        <xsl:choose>
+          <xsl:when test="concat(ack,bcast)!='OffOff'">
+            <xsl:choose>
+              <xsl:when test="ack!='Off'"> ack </xsl:when>
+            </xsl:choose>
+            <xsl:choose>
+              <xsl:when test="bcast!='Off'"> bcast </xsl:when>
+            </xsl:choose>
+           </xsl:when>
+          <xsl:otherwise>
+          none
+          </xsl:otherwise>
+        </xsl:choose>
+        </td>
+        </tr>
+
+        <xsl:apply-templates select="mac"/>
+
+        <xsl:for-each select="timer">
+          <xsl:sort select="@idx"/>
+          <tr>
+            <td class="rt">Timer(<xsl:value-of select="@idx"/>) : </td>
+            <td class="rt_data">
+            <xsl:choose>
+            <xsl:when test="@oneshot='yes'"> 1sh </xsl:when>
+            <xsl:otherwise> per </xsl:otherwise>
+            </xsl:choose>
+            | <xsl:value-of select="@delay"/>/<xsl:value-of  
select="@period"/></td>
+          </tr>
+
+        </xsl:for-each>
+      </table>
+</xsl:template>
+
+<xsl:template match="mac">
+  <xsl:apply-templates/>
+</xsl:template>
+
+<xsl:template match="lpl">
+        <tr>
+          <td class="rt">LPL : </td>
+          <td class="rt_data"><xsl:value-of select="@wakeup"/> ms</td>
+        </tr>
+</xsl:template>
+
+<xsl:template match="plink">
+        <tr>
+          <td class="rt" rowspan="2">Packet Link : </td>
+          <td class="rt_data">Retries : <xsl:value-of  
select="@retries"/><br/></td>
+        </tr>
+        <tr>
+          <td class="rt_data">Delay : <xsl:value-of  
select="@delay"/><br/></td>
+        </tr>
+</xsl:template>
+
+<xsl:template match="stat">
+
+          <td class="sub"><xsl:value-of select="REMC"/></td>
+          <td class="rt_data"><xsl:value-of select="TC"/></td>
+          <td class="rt_data"><xsl:value-of select="BC"/></td>
+          <td class="rt_data"><xsl:value-of select="RC"/></td>
+
+          <td class="rt_data snd"><xsl:value-of select="SC"/></td>
+          <td class="rt_data snd"><xsl:value-of select="SSC"/></td>
+          <td class="rt_data snd"><xsl:value-of select="SFC"/></td>
+
+          <td class="rt_data snd"><xsl:value-of select="SDC"/></td>
+          <td class="rt_data snd"><xsl:value-of select="SDSC"/></td>
+          <td class="rt_data snd"><xsl:value-of select="SDFC"/></td>
+
+          <td class="rt_data"><xsl:value-of select="WAC"/></td>
+          <td class="rt_data"><xsl:value-of select="NAC"/></td>
+
+          <td class="rt_data rcv"><xsl:value-of select="RCC"/></td>
+          <td class="rt_data rcv"><xsl:value-of select="EXC"/></td>
+          <td class="rt_data rcv"><xsl:value-of select="WC"/></td>
+          <td class="rt_data rcv"><xsl:value-of select="DRC"/></td>
+          <td class="rt_data rcv"><xsl:value-of select="FC"/></td>
+          <td class="rt_data rcv"><xsl:value-of select="MC"/></td>
+
+</xsl:template>
+
+<xsl:template match="profile">
+
+          <td class="rt_data cprofile"><xsl:value-of select="MINAT"/> /  
<xsl:value-of select="MAT"/></td>
+          <td class="rt_data cprofile"><xsl:value-of select="MININT"/> /  
<xsl:value-of select="MINT"/></td>
+          <td class="rt_data cprofile"><xsl:value-of select="MINLAT"/> /  
<xsl:value-of select="MLAT"/></td>
+
+          <td class="rt_data rprofile"><xsl:value-of select="RXTX"/></td>
+          <td class="rt_data rprofile"><xsl:value-of select="RST"/></td>
+          <td class="rt_data rprofile"><xsl:value-of select="RXMSGS"/></td>
+          <td class="rt_data rprofile"><xsl:value-of select="RXB"/></td>
+          <td class="rt_data rprofile"><xsl:value-of select="TXB"/></td>
+
+          <td class="sub">
+          <xsl:choose>
+          <xsl:when test="DBG='0'">
+            <span class="debug_ok">OK</span>
+          </xsl:when>
+          <xsl:otherwise>
+            <span class="debug_fail">FAIL (<xsl:value-of  
select="DBG"/>)</span>
+          </xsl:otherwise>
+          </xsl:choose>
+          </td>
+
+</xsl:template>
+
+<xsl:template match="error">
+  <div class="error"><xsl:value-of select="."/></div>
+</xsl:template>
+
+</xsl:stylesheet>
=======================================
--- /dev/null
+++ /trunk/apps/tests/LinkBench/javasrc/dist-addon/batchfiles/batch_all.yml	 
Tue Sep  6 00:34:50 2011
@@ -0,0 +1,57 @@
+config: {bmark: 10, time: 1000 }
+---
+config: {bmark: 11, time: 1000 }
+---
+config: {bmark: 12, time: 1000 }
+---
+config: {bmark: 13, time: 1000 }
+---
+config: {bmark: 14, time: 1000 }
+---
+config: {bmark: 15, time: 1000 }
+---
+config: {bmark: 16, time: 1000 }
+---
+config: {bmark: 17, time: 1000 }
+---
+config: {bmark: 18, time: 1000 }
+---
+config: {bmark: 19, time: 1000 }
+---
+config: {bmark: 20, time: 1000 }
+---
+config: {bmark: 30, time: 1000 }
+---
+config: {bmark: 31, time: 1000 }
+---
+config: {bmark: 32, time: 1000 }
+---
+config: {bmark: 33, time: 1000 }
+---
+config: {bmark: 34, time: 1000 }
+---
+config: {bmark: 35, time: 1000 }
+---
+config: {bmark: 36, time: 1000 }
+---
+config: {bmark: 50, time: 1000 }
+---
+config: {bmark: 51, time: 1000 }
+---
+config: {bmark: 52, time: 1000 }
+---
+config: {bmark: 53, time: 1000 }
+---
+config: {bmark: 54, time: 1000 }
+---
+config: {bmark: 55, time: 1000 }
+---
+config: {bmark: 56, time: 1000 }
+---
+config: {bmark: 57, time: 1000 }
+---
+config: {bmark: 58, time: 1000 }
+---
+config: {bmark: 59, time: 1000 }
+---
+config: {bmark: 60, time: 1000 }
=======================================
--- /dev/null
+++  
/trunk/apps/tests/LinkBench/javasrc/dist-addon/batchfiles/batch_collisions.yml	 
Tue Sep  6 00:34:50 2011
@@ -0,0 +1,87 @@
+config: {bmark: 30, time: 1000}
+---
+config: {bmark: 30, time: 1000}
+forces: [ack]
+---
+config: {bmark: 30, time: 1000}
+timers:
+ - t2: [0, 50, 100]
+---
+config: {bmark: 30, time: 1000}
+timers:
+ - t2: [0, 50, 100]
+forces: [ack]
+---
+config: {bmark: 31, time: 1000}
+---
+config: {bmark: 31, time: 1000}
+timers:
+ - t2: [0, 50, 100]
+---
+config: {bmark: 32, time: 1000}
+---
+config: {bmark: 32, time: 1000}
+timers:
+ - t3: [0, 50, 100]
+---
+config: {bmark: 32, time: 1000}
+timers:
+ - t2: [0, 33, 100]
+ - t3: [0, 66, 100]
+---
+config: {bmark: 33, time: 1000}
+---
+config: {bmark: 33, time: 1000}
+forces: [ack]
+---
+config: {bmark: 33, time: 1000}
+timers:
+ - t3: [0, 50, 100]
+---
+config: {bmark: 33, time: 1000}
+timers:
+ - t3: [0, 50, 100]
+forces: [ack]
+---
+config: {bmark: 33, time: 1000}
+timers:
+ - t2: [0, 33, 100]
+ - t3: [0, 66, 100]
+---
+config: {bmark: 33, time: 1000}
+timers:
+ - t2: [0, 33, 100]
+ - t3: [0, 66, 100]
+forces: [ack]
+---
+config: {bmark: 34, time: 1000}
+---
+config: {bmark: 34, time: 1000}
+forces: [ack]
+---
+config: {bmark: 34, time: 1000}
+timers:
+ - t3: [0, 50, 100]
+---
+config: {bmark: 34, time: 1000}
+timers:
+ - t3: [0, 50, 100]
+forces: [ack]
+---
+config: {bmark: 34, time: 1000}
+timers:
+ - t2: [0, 33, 100]
+ - t3: [0, 66, 100]
+---
+config: {bmark: 34, time: 1000}
+timers:
+ - t2: [0, 33, 100]
+ - t3: [0, 66, 100]
+forces: [ack]
+---
+config: {bmark: 35, time: 1000}
+---
+config: {bmark: 35, time: 1000}
+forces: [ack]
+---
+config: {bmark: 36, time: 1000}
=======================================
--- /dev/null
+++  
/trunk/apps/tests/LinkBench/javasrc/dist-addon/batchfiles/batch_forwarding.yml	 
Tue Sep  6 00:34:50 2011
@@ -0,0 +1,150 @@
+config: {bmark: 50, time: 1000}
+timers:
+ - t1: [0, 0, 100]
+---
+config: {bmark: 50, time: 1000}
+timers:
+ - t1: [0, 0, 100]
+forces: [ack]
+---
+config: {bmark: 50, time: 1000}
+timers:
+ - t1: [0, 0, 50]
+---
+config: {bmark: 50, time: 1000}
+timers:
+ - t1: [0, 0, 50]
+forces: [ack]
+---
+config: {bmark: 50, time: 1000}
+timers:
+ - t1: [0, 0, 25]
+---
+config: {bmark: 50, time: 1000}
+timers:
+ - t1: [0, 0, 25]
+forces: [ack]
+---
+config: {bmark: 50, time: 1000}
+timers:
+ - t1: [0, 0, 10]
+---
+config: {bmark: 50, time: 1000}
+timers:
+ - t1: [0, 0, 10]
+forces: [ack]
+---
+config: {bmark: 51, time: 1000}
+timers:
+ - t1: [0, 0, 100]
+---
+config: {bmark: 51, time: 1000}
+timers:
+ - t1: [0, 0, 50]
+---
+config: {bmark: 51, time: 1000}
+timers:
+ - t1: [0, 0, 25]
+---
+config: {bmark: 51, time: 1000}
+timers:
+ - t1: [0, 0, 10]
+---
+config: {bmark: 52, time: 1000}
+timers:
+ - t1: [0, 0, 100]
+---
+config: {bmark: 52, time: 1000}
+timers:
+ - t1: [0, 0, 50]
+---
+config: {bmark: 52, time: 1000}
+timers:
+ - t1: [0, 0, 25]
+---
+config: {bmark: 52, time: 1000}
+timers:
+ - t1: [0, 0, 10]
+---
+config: {bmark: 53, time: 1000}
+timers:
+ - t1: [0, 0, 100]
+---
+config: {bmark: 53, time: 1000}
+timers:
+ - t1: [0, 0, 50]
+---
+config: {bmark: 53, time: 1000}
+timers:
+ - t1: [0, 0, 25]
+---
+config: {bmark: 53, time: 1000}
+timers:
+ - t1: [0, 0, 10]
+---
+config: {bmark: 54, time: 1000}
+---
+config: {bmark: 54, time: 1000}
+forces: [ack]
+---
+config: {bmark: 54, time: 1000}
+timers:
+ - t2: [0, 50, 100]
+---
+config: {bmark: 54, time: 1000}
+timers:
+ - t2: [0, 50, 100]
+forces: [ack]
+---
+config: {bmark: 55, time: 1000}
+---
+config: {bmark: 55, time: 1000}
+forces: [ack]
+---
+config: {bmark: 55, time: 1000}
+timers:
+ - t1: [0, 0, 100]
+ - t2: [0, 33, 100]
+ - t3: [0, 66, 100]
+---
+config: {bmark: 55, time: 1000}
+timers:
+ - t1: [0, 0, 100]
+ - t2: [0, 33, 100]
+ - t3: [0, 66, 100]
+forces: [ack]
+---
+config: {bmark: 56, time: 1000}
+---
+config: {bmark: 56, time: 1000}
+timers:
+ - t1: [0, 0, 100]
+ - t2: [0, 33, 100]
+ - t3: [0, 66, 100]
+---
+config: {bmark: 57, time: 1000}
+---
+config: {bmark: 57, time: 1000}
+forces: [ack]
+---
+config: {bmark: 57, time: 1000}
+timers:
+ - t1: [0, 0, 100]
+ - t2: [0, 33, 100]
+ - t3: [0, 66, 100]
+---
+config: {bmark: 57, time: 1000}
+timers:
+ - t1: [0, 0, 100]
+ - t2: [0, 33, 100]
+ - t3: [0, 66, 100]
+forces: [ack]
+---
+config: {bmark: 58, time: 1000}
+---
+config: {bmark: 58, time: 1000}
+forces: [ack]
+---
+config: {bmark: 59, time: 1000}
+---
+config: {bmark: 60, time: 1000}
=======================================
--- /dev/null
+++ /trunk/apps/tests/LinkBench/javasrc/dist-addon/batchfiles/batch_lpl.yml	 
Tue Sep  6 00:34:50 2011
@@ -0,0 +1,159 @@
+config: {bmark: 30, time: 1000}
+timers:
+ - t1: [0, 0, 100]
+ - t2: [0, 0, 100]
+wakeup: 0
+---
+config: {bmark: 30, time: 1000}
+timers:
+ - t1: [0, 0, 100]
+ - t2: [0, 0, 100]
+wakeup: 30
+---
+config: {bmark: 30, time: 1000}
+timers:
+ - t1: [0, 0, 100]
+ - t2: [0, 0, 100]
+wakeup: 70
+---
+config: {bmark: 30, time: 1000}
+timers:
+ - t1: [0, 0, 100]
+ - t2: [0, 0, 100]
+wakeup: 130
+---
+config: {bmark: 30, time: 1000}
+timers:
+ - t1: [0, 0, 100]
+ - t2: [0, 50, 100]
+wakeup: 0
+---
+config: {bmark: 30, time: 1000}
+timers:
+ - t1: [0, 0, 100]
+ - t2: [0, 50, 100]
+wakeup: 30
+---
+config: {bmark: 30, time: 1000}
+timers:
+ - t1: [0, 0, 100]
+ - t2: [0, 50, 100]
+wakeup: 70
+---
+config: {bmark: 30, time: 1000}
+timers:
+ - t1: [0, 0, 100]
+ - t2: [0, 50, 100]
+wakeup: 130
+---
+config: {bmark: 35, time: 1000}
+wakeup: 0
+---
+config: {bmark: 35, time: 1000}
+wakeup: 30
+---
+config: {bmark: 35, time: 1000}
+wakeup: 70
+---
+config: {bmark: 35, time: 1000}
+wakeup: 130
+---
+config: {bmark: 50, time: 1000}
+wakeup: 0
+---
+config: {bmark: 50, time: 1000}
+wakeup: 30
+---
+config: {bmark: 50, time: 1000}
+wakeup: 70
+---
+config: {bmark: 50, time: 1000}
+wakeup: 130
+---
+config: {bmark: 53, time: 1000}
+wakeup: 0
+---
+config: {bmark: 53, time: 1000}
+wakeup: 30
+---
+config: {bmark: 53, time: 1000}
+wakeup: 70
+---
+config: {bmark: 53, time: 1000}
+wakeup: 130
+---
+config: {bmark: 53, time: 1000}
+timers:
+ - t1: [0, 0, 20]
+wakeup: 0
+---
+config: {bmark: 53, time: 1000}
+timers:
+ - t1: [0, 0, 20]
+wakeup: 30
+---
+config: {bmark: 53, time: 1000}
+timers:
+ - t1: [0, 0, 20]
+wakeup: 70
+---
+config: {bmark: 53, time: 1000}
+timers:
+ - t1: [0, 0, 20]
+wakeup: 130
+---
+config: {bmark: 55, time: 1000}
+timers:
+ - t1: [0, 0, 100]
+ - t2: [0, 33, 100]
+ - t3: [0, 66, 100]
+wakeup: 0
+---
+config: {bmark: 55, time: 1000}
+timers:
+ - t1: [0, 0, 100]
+ - t2: [0, 33, 100]
+ - t3: [0, 66, 100]
+wakeup: 30
+---
+config: {bmark: 55, time: 1000}
+timers:
+ - t1: [0, 0, 100]
+ - t2: [0, 33, 100]
+ - t3: [0, 66, 100]
+wakeup: 70
+---
+config: {bmark: 55, time: 1000}
+timers:
+ - t1: [0, 0, 100]
+ - t2: [0, 33, 100]
+ - t3: [0, 66, 100]
+wakeup: 130
+---
+config: {bmark: 58, time: 1000}
+timers:
+ - t1: [0, 0, 100]
+ - t2: [0, 33, 100]
+ - t3: [0, 66, 100]
+wakeup: 0
+---
+config: {bmark: 58, time: 1000}
+timers:
+ - t1: [0, 0, 100]
+ - t2: [0, 33, 100]
+ - t3: [0, 66, 100]
+wakeup: 30
+---
+config: {bmark: 58, time: 1000}
+timers:
+ - t1: [0, 0, 100]
+ - t2: [0, 33, 100]
+ - t3: [0, 66, 100]
+wakeup: 70
+---
+config: {bmark: 58, time: 1000}
+timers:
+ - t1: [0, 0, 100]
+ - t2: [0, 33, 100]
+ - t3: [0, 66, 100]
+wakeup: 130
=======================================
--- /dev/null
+++  
/trunk/apps/tests/LinkBench/javasrc/dist-addon/batchfiles/batch_throughputs.yml	 
Tue Sep  6 00:34:50 2011
@@ -0,0 +1,48 @@
+config: {bmark: 10, time: 1000}
+---
+config: {bmark: 11, time: 1000}
+---
+config: {bmark: 12, time: 1000}
+---
+config: {bmark: 10, time: 1000}
+forces: [ack]
+---
+config: {bmark: 11, time: 1000}
+forces: [ack]
+---
+config: {bmark: 12, time: 1000}
+forces: [ack]
+---
+config: {bmark: 10, time: 1000}
+forces: [bcast]
+---
+config: {bmark: 11, time: 1000}
+forces: [bcast]
+---
+config: {bmark: 12, time: 1000}
+forces: [bcast]
+---
+config: {bmark: 13, time: 1000}
+---
+config: {bmark: 14, time: 1000}
+---
+config: {bmark: 15, time: 1000}
+---
+config: {bmark: 16, time: 1000}
+---
+config: {bmark: 16, time: 1000}
+forces: [ack]
+---
+config: {bmark: 17, time: 1000}
+---
+config: {bmark: 18, time: 1000}
+---
+config: {bmark: 19, time: 1000}
+---
+config: {bmark: 19, time: 1000}
+forces: [ack]
+---
+config: {bmark: 20, time: 1000}
+---
+config: {bmark: 20, time: 1000}
+forces: [ack]
=======================================
--- /dev/null
+++  
/trunk/apps/tests/LinkBench/javasrc/dist-addon/batchfiles/generate_batch.sh	 
Tue Sep  6 00:34:50 2011
@@ -0,0 +1,87 @@
+#!/bin/bash
+# This shell script is useful for generating hundreds of benchmarks
+# based on specific needs without the need of typing 1 billion words.
+#
+# Modify the code of main() as you like.
+
+# Here is an example how to generate a bunch of descriptions
+main() {
+  A_BMARK=""
+  TIME=10000
+  TIMER1=(0 0 100)
+  #TIMER2=(0 33 100)
+  #TIMER3=(0 66 100)
+  #ACK=yes
+  #ACK=yes
+  WAKEUP=400
+  TIMES="100 500 1000 2000"
+  for t in $TIMES; do
+
+  for BMARK in `seq 100 105`; do
+    TIMER1[2]=$t
+    #for WAKEUP in $A_WAKEUP; do
+      print_bmark >> $1
+
+    done
+  done
+}
+
+# Print a YAML-correct benchmark description based on env vars
+print_bmark() {
+  # start benchmark
+  echo "---"
+  # config section
+  if [[ -z $TIME || -z $BMARK ]]; then
+    echo "Undefined BMARK or TIME value!"
+    exit 1
+  fi
+
+  echo -n "config: {bmark: $BMARK, time: $TIME"
+  echo -n ${MOTES:+", motes: $MOTES"};
+  echo -n ${RANDSTART:+", randstart: $RANDSTART"};
+  echo -n ${LCHANCE:+", lchance: $LCHANCE"};
+  echo "}"
+
+  #timers section
+  GOTTIMER=0
+  if [[ -n $TIMER1 && ${#TIMER1[*]} -eq 3 ]]; then
+   GOTTIMER=1
+   TIMERV[0]="t1: [${TIMER1[0]}, ${TIMER1[1]}, ${TIMER1[2]}]"
+  fi
+  if [[ -n $TIMER2 && ${#TIMER2[*]} -eq 3 ]]; then
+   GOTTIMER=1
+   TIMERV[1]="t2: [${TIMER2[0]}, ${TIMER2[1]}, ${TIMER2[2]}]"
+  fi
+  if [[ -n $TIMER3 && ${#TIMER3[*]} -eq 3 ]]; then
+   GOTTIMER=1
+   TIMERV[2]="t3: [${TIMER3[0]}, ${TIMER3[1]}, ${TIMER3[2]}]"
+  fi
+  if [[ -n $TIMER4 && ${#TIMER4[*]} -eq 3 ]]; then
+   GOTTIMER=1
+   TIMERV[3]="t4: [${TIMER4[0]}, ${TIMER4[1]}, ${TIMER4[2]}]"
+  fi
+  if [[ $GOTTIMER -eq 1 ]]; then
+    echo "timers:"
+    echo ${TIMERV[0]}${TIMERV[1]}${TIMERV[2]}${TIMERV[3]} |  
sed 's/\]t/\]\nt/g' | sed 's/\(t[0-9]\):/ - \1:/g'
+  fi
+
+  unset GOTTIMER
+  unset TIMERV
+
+  # forces section
+  FORCES=${BCAST}${ACK}
+  echo -n ${FORCES:+"forces: "}
+  FORCESV="[${BCAST:+bcast}, ${ACK:+ack}]"
+  echo -n $FORCESV | sed 's:, \]:\]:g' | sed 's:\[, :\[:g' |  
sed 's:\[\]::g'
+  echo -ne ${FORCES:+'\n'}
+
+  unset FORCES
+  unset FORCESV
+  # wakeup section
+  echo -en ${WAKEUP:+"wakeup: $WAKEUP\n"};
+}
+
+main $1
+
+
+
=======================================
--- /dev/null
+++  
/trunk/apps/tests/LinkBench/javasrc/dist-addon/batchfiles/sample_batch_config.yml	 
Tue Sep  6 00:34:50 2011
@@ -0,0 +1,84 @@
+# Benchmark batch configuration sample file
+# -----------------------------------------
+#
+# This file describes multiple benchmarks to be run in sequence with the  
LinkBenchmark
+# TinyOS application along with its supporting PC-side Java application.
+#
+# The content of this file is YAML-formatted with a reduced key set and  
value sets.
+# Benchmark definitions must be separated with 3 dashes ('---') in a  
separate line.
+#
+# The example below demonstrates ALL options that can be specified in the  
correct
+# format:
+# ---
+# config: {bmark: 10, motes: 6, time: 1000, randstart: 30, lchance: 20}
+# timers:
+#  - t1: [1, 10, 100]
+#  - t2: [0, 20, 200]
+#  - t3: [1, 30, 300]
+#  - t4: [0, 30, 300]
+# forces: [ack, bcast]
+# mac:
+#  - lpl: [ 200 ]
+#  - plink: [ 200 100 ]
+# ---
+#
+# All values must be integers. The mandatory options are: config,  
config.bmark,
+# and config.time, so the most simple description is:
+# config: {bmark: X, time: Y}
+#
+# If some options are not explicitly specified, but are required for the  
benchmarks,
+# the default values are used. Use the command line Java code's help to  
get these values.
+#
+#
+# See below some dummy examples for your pleasure!
+
+config: {bmark: 10, motes: 3, time: 1000, randstart: 30}
+---
+config: {bmark: 10, time: 20, lchance: 100}
+mac:
+  - lpl: [ 200 ]
+  - plink: [ 200 100 ]
+
+---
+config: {bmark: 10, time: 200, motes: 5}
+forces: [ack]
+---
+config: {bmark: 10, motes: 3, time: 3000}
+forces: [bcast]
+---
+config: {bmark: 15, time: 1000, randstart: 30}
+---
+config: {bmark: 30, time: 322}
+timers:
+ - t1: [1,  50, 200]
+ - t2: [1, 500, 100]
+---
+config: {bmark: 30, time: 1000}
+timers:
+ - t1: [0, 0, 200]
+ - t2: [0, 0, 100]
+forces: [bcast]
+mac:
+  - plink: [ 200 100 ]
+---
+config: {bmark: 34, time: 1000}
+timers:
+ - t1: [0, 10, 100]
+ - t2: [0, 20, 200]
+ - t3: [0, 30, 300]
+forces: [ack]
+---
+config: {bmark: 50, time: 1000}
+timers:
+ - t1: [0, 10, 100]
+forces: [ack]
+---
+config: {bmark: 50, time: 1000}
+timers:
+ - t1: [0, 10, 100]
+forces: [bcast]
+---
+config: {bmark: 53, time: 1000}
+forces: [ack]
+---
+config: {bmark: 10, time: 1000}
=======================================
--- /dev/null
+++  
/trunk/apps/tests/LinkBench/javasrc/dist-addon/batchfiles/tos_metric.yml	 
Tue Sep  6 00:34:50 2011
@@ -0,0 +1,7 @@
+config: {bmark: 10, time: 1000 }
+---
+config: {bmark: 11, time: 1000 }
+---
+config: {bmark: 19, time: 1000 }
+---
+config: {bmark: 20, time: 1000 }
=======================================
--- /dev/null	
+++ /trunk/apps/tests/LinkBench/javasrc/dist-addon/lib/commons-cli-1.2.jar	 
Tue Sep  6 00:34:50 2011
Binary file, no diff available.
=======================================
--- /dev/null	
+++ /trunk/apps/tests/LinkBench/javasrc/dist-addon/lib/snakeyaml-1.7.jar	 
Tue Sep  6 00:34:50 2011
Binary file, no diff available.
=======================================
--- /dev/null
+++ /trunk/apps/tests/LinkBench/javasrc/dist-addon/linkbench.sh	Tue Sep  6  
00:34:50 2011
@@ -0,0 +1,7 @@
+#!/bin/bash
+EXEC="linkbench.jar"
+if [ -f $EXEC ]; then
+  java -jar $EXEC $@
+else
+  echo -e "No \033[1m$EXEC\033[0m file found. Have you built the Java  
application?";
+fi
=======================================
--- /dev/null
+++ /trunk/apps/tests/LinkBench/javasrc/dist-addon/tos_metric.sh	Tue Sep  6  
00:34:50 2011
@@ -0,0 +1,232 @@
+#!/bin/bash
+# TinyOS software metric generator script
+# This script's purpose is to run the LinkBench application with
+# arbitrary benchmarks, but using always different TinyOS svn revisions.
+#
+
+PROGNAME=`basename $0`
+PROGVERSION=0.1
+
+# default values
+MPLATFORM=iris
+TOSSVNDIR=$TOSROOT
+LINKBDIR=".."
+START_DATE=`date +%Y-%m-%d`
+STOP_DATE=`date +%Y-%m-%d`
+DATE_STEP='1 month'
+BENCH_FILE="batchfiles/${PROGNAME%.*}.yml"
+
+LOGFILE=${PROGNAME%.*}.log
+
+SHORTOPTS="hvF:"
+LONGOPTS="help,version,svn:,step:,benchfile:,start:,stop:"
+usage()
+{
+  echo "
+  Usage: $PROGNAME [options] [LinkBench root dir]
+
+    Executes a TinyOS metric using different SVN revisions and the  
LinkBench TinyOS application.
+    Revisions are going from 'start date' until 'stop date'. Date format  
is YYYY-MM-DD. Stop date
+    is defaulted to the current date.
+
+    Step size can be configured using the --step option.
+
+    Options:
+       -h|--help        show this output
+       -v|--version     show version information
+       -F|--benchfile   the benchmark batch file to use [ default :  
$BENCH_FILE ]
+       --start <date>   set the start date in format: YYYY-MM-DD
+       --stop  <date>   set the stop  date in format: YYYY-MM-DD
+       --svn   <dir >    set the TinyOS root directory   [ default :  
$TOSROOT ]
+       --step  <spec>   set the step size in format : [1-9][0-9]* day| 
month|year
+          examples: 10 day, 2 day, 2 month, 1 year
+  "
+}
+
+check_params() {
+  echo -e " SVN repository : \033[1m$TOSSVNDIR\033[0m"
+  if [[ ! -d $TOSSVNDIR || ! -r $TOSSVNDIR || ! -w $TOSSVNDIR || ! -x  
$TOSSVNDIR ]]; then
+    echo "   '$TOSSVNDIR' is not a good location as SVN root directory!"
+    exit 1
+  fi
+
+  echo -e " LinkBench dir. : \033[1m$LINKBDIR\033[0m"
+  if [[ ! -e $LINKBDIR/BenchmarkAppC.nc || ! -d $LINKBDIR/javasrc || ! -e  
$LINKBDIR/javasrc/build.xml ]]; then
+    echo "   '$LINKBDIR' does not seem to be the LinkBench application's  
root directory!"
+    exit 1
+  fi
+
+  echo -e " Benchmark file : \033[1m$BENCH_FILE\033[0m"
+  if [[ ! -e $BENCH_FILE ]]; then
+    echo "   '$BENCH_FILE' does not exist!"
+    exit 1
+  fi
+
+  check_date $START_DATE
+  if [ $? -gt 0 ]; then
+    echo "   '$START_DATE' is not a valid date!"
+    exit 1
+  fi
+
+  check_date $STOP_DATE
+  if [ $? -gt 0 ]; then
+    echo "   '$STOP_DATE' is not a valid date!"
+    exit 1
+  fi
+
+  date1_le_date2 $START_DATE $STOP_DATE
+  if [ $? -gt 0 ]; then
+    echo "   '$START_DATE' is in the future compared to '$STOP_DATE'!"
+    exit 1
+  fi
+
+  if [ `echo $DATE_STEP | grep -c '[1-9][0-9]* \(day\|month\|year\)'` -eq  
0 ]; then
+    echo "   '$DATE_STEP' is not a valid time step!"
+    exit 1
+  else
+    DATE_STEP=`echo $DATE_STEP | grep -o '[1-9][0-9]* \(day\|month\| 
year\)'`;
+  fi
+
+  # count how many iterations we will have
+  STEP_TOTAL=0
+  DATE_TMP=$START_DATE
+  date1_le_date2 $DATE_TMP $STOP_DATE
+  while [ $? -eq 0 ]; do
+    ((STEP_TOTAL++))
+    DATE_TMP=`date -d "$DATE_TMP +$DATE_STEP" +%Y-%m-%d`
+    date1_le_date2 $DATE_TMP $STOP_DATE
+  done
+  unset DATE_TMP
+
+  echo -e " Date  interval : \033[1m$START_DATE\033[0m ->  
\033[1m$STOP_DATE\033[0m with \033[1m$DATE_STEP\033[0m increment ( total of  
$STEP_TOTAL step(s) )"
+}
+
+# check if valid date
+check_date() {
+  if [ `echo $1 | grep -E -c '[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}'` -eq 0 ];  
then
+    return 1;
+  fi
+  declare -i year month day
+  eval $(echo $1 | sed 's:\([0-9]*\)-\([0-9]*\)-\([0-9]*\):year=\1  
month=\2 day=\3:')
+  return `cal $month $year | grep -c -w $day >/dev/null`
+}
+
+# check if $1 < $2 chronologically
+date1_le_date2() {
+  if [[ `echo "$(date -d $1 +%s) <= $(date -d $2 +%s)" | bc` == "1" ]];  
then
+    return 0
+  else
+    return 1
+  fi
+}
+
+check_last() {
+  RET=$?
+  DOFAIL="no"
+  [ "$1" = "--fail" ] && DOFAIL="yes" && shift
+  cat $3 >> $LOGFILE
+  if [ $RET -eq 0 ]; then
+    echo -ne "[\033[1m $1 \033[0m]"
+    return 0
+  else
+    echo -ne "[\033[1m $2 \033[0m]"
+    [ $DOFAIL = "yes" ] && return 1
+    cat $3
+    rm $3
+    exit 1
+  fi
+}
+
+#
+# PARSE COMMAND LINE
+#
+ARGS=$(getopt -s bash --options $SHORTOPTS --longoptions $LONGOPTS --name  
$PROGNAME -- "$@" )
+eval set -- "$ARGS"
+
+while true; do
+   case $1 in
+      -h|--help)
+         usage; exit 0;;
+      -v|--version)
+         echo "$PROGNAME version $PROGVERSION"; exit 0;;
+      -F|--benchfile)
+         shift;
+         BENCH_FILE=$1;;
+      --svn)
+         shift;
+         TOSSVNDIR=$1;;
+      --step)
+         shift;
+         DATE_STEP=$1;;
+      --start)
+         shift;
+         START_DATE=$1;;
+      --stop)
+         shift;
+         STOP_DATE=$1;;
+      --) shift ; break ;;
+      *)  shift ; break ;;
+   esac
+   shift
+done
+
+# parse mandatory parameters
+if [[ $# -gt 0 ]]; then
+  LINKBDIR=$1;
+fi
+
+# check for the established parameters if they are valid or not
+check_params
+
+SVNBIN=/usr/bin/svn
+TMP=`tempfile`
+trap '{ rm -f "$TMP"; }' EXIT
+
+# make executable the linkbench.sh script
+chmod +x linkbench.sh
+
+echo "-------------------------------------------------------------------------------------------"
+
+# while we do not run past the stop date
+STEP_CURRENT=0
+NEXT_DATE=$START_DATE
+
+rm -f $LOGFILE
+while [ $STEP_CURRENT -lt $STEP_TOTAL ]; do
+
+  ((STEP_CURRENT++))
+  # we can initiate the next svn update, to save as much time as we can.
+  START_DATE=$NEXT_DATE
+  NEXT_DATE=`date -d "$START_DATE +$DATE_STEP" +%Y-%m-%d`
+
+  printf "(%2d/%2d) - %s : " $STEP_CURRENT $STEP_TOTAL $START_DATE | tee  
-a $LOGFILE
+
+  # (1) update the svn repository
+  ( cd $TOSSVNDIR; $SVNBIN update -r {$START_DATE} > $TMP 2>&1 )
+  check_last "Rev: `tail -1 $TMP | tr -cd '[:digit:]'`" "SVN ERROR" $TMP
+
+  # (2) re-make the nesc code
+  ( cd $LINKBDIR; ./minstall.sh --compileonly > $TMP 2>&1 )
+  check_last --fail "COMPILE OK" "COMPILE ERROR" $TMP || { echo "";  
continue; }
+
+  # (3) program the motes
+  ( cd $LINKBDIR ; ./minstall.sh --progonly > $TMP 2>&1 )
+  check_last --fail "PROGRAM OK" "PROGRAM ERROR" $TMP || { echo "";  
continue; }
+  sleep 2
+
+  # (4) run the benchmark
+  ./linkbench.sh -F $BENCH_FILE -o result-${START_DATE}.xml > $TMP 2>&1
+  check_last "RUN OK" "RUN ERROR" $TMP
+
+  sleep 2
+  ./linkbench.sh -r > $TMP 2>&1
+  check_last "RESET OK" "RESET ERROR" $TMP
+
+  # (5) clean
+  ( cd $LINKBDIR; make clean 2>&1 | tee -a $LOGFILE > $TMP )
+  check_last "CLEAN OK" "CLEAN ERROR" $TMP
+
+  echo ""
+done
+rm $TMP
+exit 0
=======================================
***Additional files exist in this changeset.***


More information about the Tinyos-2-commits mailing list