Beispiel #1
0
    def build_arguments(a):
        build_args = a.build_arguments()

        configuration = Configuration.create(a.args.configuration, a.args)

        build_args.update(configuration.build_arguments())

        return build_args
Beispiel #2
0
    def build_arguments(self, a):
        build_args = a.build_arguments()

        configuration = Configuration.create(a.args.configuration, a.args)
        build_args.update(configuration.build_arguments())

        try:
            build_args.update(LOG_MODES[self.log_mode])
        except KeyError:
            raise RuntimeError(
                f"Unknown testbed log mode {self.log_mode}. Available: {LOG_MODES.keys()}"
            )

        return build_args
Beispiel #3
0
    def _get_configuration(self, **kwargs):
        args = ('network size', 'distance', 'node id order', 'seed')
        arg_converters = {
            'network size': int,
            'distance': float,
            'seed': int,
        }

        kwargs_copy = {k.replace("_", " "): v for (k,v) in kwargs.items()}

        arg_values = {
            name: arg_converters.get(name, lambda x: x)(kwargs_copy[name])
            for name in args
            if name in kwargs_copy
        }

        return Configuration.create(kwargs['configuration'], arg_values)
Beispiel #4
0
    def build_arguments(self, a):
        build_args = a.build_arguments()

        configuration = Configuration.create(a.args.configuration, a.args)

        build_args.update(configuration.build_arguments())
        build_args.update(self.testbed.build_arguments())

        log_mode = self.testbed.log_mode()

        modes = {
            "printf": {
                "USE_SERIAL_PRINTF": 1,
                "SERIAL_PRINTF_BUFFERED": 1
            },
            "unbuffered_printf": {
                "USE_SERIAL_PRINTF": 1,
                "SERIAL_PRINTF_UNBUFFERED": 1
            },
            "uart_printf": {
                "USE_SERIAL_PRINTF": 1,
                "SERIAL_PRINTF_UART": 1
            },
            "serial": {
                "USE_SERIAL_MESSAGES": 1
            },
            "disabled": {
                "NO_SERIAL_OUTPUT": 1
            },
            "avrora": {
                "AVRORA_OUTPUT": 1
            },
            "cooja": {
                "COOJA_OUTPUT": 1
            },
        }

        try:
            build_args.update(modes[log_mode])
        except KeyError:
            raise RuntimeError(
                f"Unknown testbed log mode {log_mode}. Available: {modes.keys()}"
            )

        return build_args
Beispiel #5
0
def post_build_actions(target_directory, a):
    import os.path
    import shutil

    from simulator import Configuration

    # Create main.elf
    shutil.copy(os.path.join(target_directory, "main.exe"),
                os.path.join(target_directory, "main.elf"))

    # Output topology file
    configuration = Configuration.create(a.args.configuration, a.args)

    with open(os.path.join(target_directory, "topology.txt"),
              "w") as topo_file:
        for (nid, (x, y)) in sorted(configuration.topology.nodes.items(),
                                    key=lambda k: k[0]):
            z = 0
            print(f"node{nid} {x} {y} {z}", file=topo_file)
    def _submit_job(self, a, target_directory):

        # Remove some things to get the name to be shorter
        name = target_directory[len("testbed-"):-len("-real")]
        name = name.replace("ReliableFaultModel__-", "")
        name = name.replace("topology-", "")

        configuration = Configuration.create(a.args.configuration, a.args)

        exe_path = os.path.join(target_directory, "main.exe")
        config_path = os.path.join(target_directory, "flocklab.xml")

        with open(config_path, "w") as config_file:
            self.generate_configuration_xml(
                configuration,
                config_file,
                exe_path,
                name=name,
                duration=self.duration,
            )

        # Check that everything is okay
        command = ["./scripts/flocklab.sh", "-v", config_path]

        print("Checking xml validity:", " ".join(command))
        validator_output = subprocess.check_output(
            " ".join(command), shell=True).decode("utf-8").strip()

        if validator_output != "The file validated correctly.":
            raise RuntimeError(validator_output)

        # Submit the job
        command = ["./scripts/flocklab.sh", "-c", config_path]

        print("Submitting xml job:", " ".join(command), "for a duration of",
              self.duration)
        if self.dry_run:
            print("Dry run complete!")
            return

        print(f"Submitting {name}...")
        subprocess.check_call(" ".join(command), shell=True)
Beispiel #7
0
    def _get_configuration(self):
        arg_converters = {
            'network_size': int,
            'distance': float,
        }

        arg_values = {
            name.replace("_", " "): converter(self.opts[name])
            for (name, converter) in arg_converters.items()
            if name in self.opts
        }

        # Will never have a seed because opts to too early to get the
        # per simulation seed
        arg_values['seed'] = None

        # As we don't have a seed the node_id_order must always be topology
        arg_values['node id order'] = "topology"

        return Configuration.create(self.opts['configuration'], arg_values)
Beispiel #8
0
    def add_job(self, options, name, estimated_time=None):

        if not self.quiet:
            print(name)

            if not self._progress.has_started():
                self._progress.start(self.total_job_size)

        # Create the target directory
        target_directory = name[:-len(".txt")]

        data.util.create_dirtree(target_directory)

        # Get the job arguments

        # If options is a tuple then we have just been given the
        # module name and the parsed arguments.
        if isinstance(options, tuple):
            module, a = options
        else:
            options = shlex.split(options)
            module, argv = options[0], options[1:]

            a = self.parse_arguments(module, argv)

        module_path = module.replace(".", "/")

        # Check that the topology supports the chosen platform
        # Some topologies only support one platform type
        configuration = Configuration.create(a.args.configuration, a.args)

        if hasattr(configuration.topology, "platform"):
            if configuration.topology.platform != self.platform:
                raise RuntimeError(
                    "The topology's platform ({}) does not match the chosen platform ({})"
                    .format(configuration.topology.platform, self.platform))

        # Build the binary

        # These are the arguments that will be passed to the compiler
        build_args = self.build_arguments(a)
        build_args["PLATFORM"] = self.platform

        if not self.quiet:
            print(f"Building for {build_args}")

        build_result = Builder.build_actual(module_path,
                                            self.platform,
                                            enable_fast_serial=False,
                                            **build_args)

        if not self.quiet:
            print(
                f"Build finished with result {build_result}, waiting for a bit..."
            )

        # For some reason, we seemed to be copying files before
        # they had finished being written. So wait a  bit here.
        time.sleep(1)

        if not self.quiet:
            print(f"Copying files to '{target_directory}'")

        # Detect the OS from the presence of one of these files:
        os_of_build = self._detect_os_of_build(module_path)

        files_to_copy = {
            "tinyos": (
                "app.c",
                "ident_flags.txt",
                "main.exe",
                "main.ihex",
                "main.srec",
                "tos_image.xml",
                "wiring-check.xml",
            ),
            "contiki": (
                "main.exe",
                "symbols.h",
                "symbols.c",
            ),
        }
        for name in files_to_copy[os_of_build]:
            try:
                src = os.path.join(module_path, "build", self.platform, name)
                dest = target_directory

                shutil.copy(src, dest)

                #print("Copying {} -> {}".format(src, dest))
            except IOError as ex:
                # Ignore expected fails
                if name not in {"main.srec", "wiring-check.xml"}:
                    print(f"Not copying {name} due to {ex}")

        # Copy any generated class files
        for class_file in glob.glob(os.path.join(module_path, "*.class")):
            try:
                shutil.copy(class_file, target_directory)
            except shutil.Error as ex:
                if str(ex).endswith("are the same file"):
                    continue
                else:
                    raise

        if self.pool is not None:
            target_ihex = os.path.join(target_directory, "main.ihex")

            if not self.quiet:
                print(
                    f"Creating per node id binaries using '{target_ihex}'...")

            def fn(node_id):
                output_ihex = os.path.join(target_directory,
                                           f"main-{node_id}.ihex")
                self.create_tos_node_id_ihex(target_ihex, output_ihex, node_id)

            self.pool.map(fn, configuration.topology.nodes)

        if not self.quiet:
            print("All Done!")

            self._progress.print_progress(self._jobs_executed)

            self._jobs_executed += 1

        return a, module, module_path, target_directory
Beispiel #9
0
def run_simulation(module, a, count=1, print_warnings=False):
    import shlex
    import sys
    import subprocess

    from simulator import Configuration

    if a.args.node_id_order != "topology":
        raise RuntimeError("COOJA does not support a nido other than topology")

    configuration = Configuration.create(a.args.configuration, a.args)

    command = avrora_command(module, a, configuration)

    print("@command:{}".format(command))
    sys.stdout.flush()

    command = shlex.split(command)    

    if a.args.mode == "RAW":
        if count != 1:
            raise RuntimeError("Cannot run avrora multiple times in RAW mode")

        with subprocess.Popen(command, stdout=subprocess.PIPE, universal_newlines=True) as proc:

            proc_iter = iter(proc.stdout.readline, '')

            for line in avrora_iter(proc_iter):
                print(line)

            proc.stdout.close()

            try:
                return_code = proc.wait(timeout=1)

                if return_code:
                    raise subprocess.CalledProcessError(return_code, command)

            except subprocess.TimeoutExpired:
                proc.terminate()

    else:
        if a.args.mode == "SINGLE":
            from simulator.Simulation import OfflineSimulation
        elif a.args.mode == "GUI":
            from simulator.TosVis import GuiOfflineSimulation as OfflineSimulation
        else:
            raise RuntimeError("Unknown mode {}".format(a.args.mode))

        for n in range(count):
            with subprocess.Popen(command, stdout=subprocess.PIPE, universal_newlines=True) as proc:

                proc_iter = iter(proc.stdout.readline, '')

                with OfflineSimulation(module, configuration, a.args, event_log=avrora_iter(proc_iter)) as sim:
                    
                    a.args.attacker_model.setup(sim)

                    try:
                        sim.run()
                    except Exception as ex:
                        import traceback
                        
                        all_args = "\n".join("{}={}".format(k, v) for (k, v) in vars(a.args).items())

                        print("Killing run due to {}".format(ex), file=sys.stderr)
                        print(traceback.format_exc(), file=sys.stderr)
                        print("For parameters:", file=sys.stderr)
                        print("With seed:", sim.seed, file=sys.stderr)
                        print(all_args, file=sys.stderr)

                        # Make sure to kill the avrora java process
                        proc.kill()

                        return 51

                    proc.stdout.close()

                    try:
                        return_code = proc.wait(timeout=1)

                        if return_code:
                            raise subprocess.CalledProcessError(return_code, command)

                    except subprocess.TimeoutExpired:
                        proc.terminate()

                    try:
                        sim.metrics.print_results()

                        if print_warnings:
                            sim.metrics.print_warnings()

                    except Exception as ex:
                        import traceback

                        all_args = "\n".join("{}={}".format(k, v) for (k, v) in vars(a.args).items())

                        print("Failed to print metrics due to: {}".format(ex), file=sys.stderr)
                        print(traceback.format_exc(), file=sys.stderr)
                        print("For parameters:", file=sys.stderr)
                        print("With seed:", sim.seed, file=sys.stderr)
                        print(all_args, file=sys.stderr)

                        # Make sure to kill the avrora java process
                        proc.kill()
                        
                        return 52

    return 0
Beispiel #10
0
def run_one_file(log_file, module, a, count=1, print_warnings=False):
    import copy

    import simulator.Configuration as Configuration
    import simulator.OfflineLogConverter as OfflineLogConverter

    args = copy.deepcopy(a.args)

    # Get the correct Simulation constructor
    if args.mode == "SINGLE":
        from simulator.Simulation import OfflineSimulation
    elif args.mode == "GUI":
        from simulator.TosVis import GuiOfflineSimulation as OfflineSimulation
    else:
        raise RuntimeError(f"Unknown mode {args.mode}")

    configuration = Configuration.create(args.configuration, args)

    print(f"Analysing log file {log_file}", file=sys.stderr)

    with OfflineLogConverter.create_specific(args.log_converter, log_file) as converted_event_log:
        with OfflineSimulation(module, configuration, args, event_log=converted_event_log) as sim:

            args.attacker_model.setup(sim)

            try:
                sim.run()
            except Exception as ex:
                import traceback

                all_args = "\n".join(f"{k}={v}" for (k, v) in vars(args).items())

                print("Killing run due to {}".format(ex), file=sys.stderr)
                print(traceback.format_exc(), file=sys.stderr)
                print("For parameters:", file=sys.stderr)
                print("With seed:", sim.seed, file=sys.stderr)
                print(all_args, file=sys.stderr)
                print("In file: {}".format(log_file), file=sys.stderr)

                return 51

            try:
                sim.metrics.print_results()

                if print_warnings:
                    sim.metrics.print_warnings(sys.stderr)

            except Exception as ex:
                import traceback

                all_args = "\n".join(f"{k}={v}" for (k, v) in vars(args).items())

                print("Failed to print metrics due to: {}".format(ex), file=sys.stderr)
                print(traceback.format_exc(), file=sys.stderr)
                print("For parameters:", file=sys.stderr)
                print("With seed:", sim.seed, file=sys.stderr)
                print(all_args, file=sys.stderr)
                print("In file: {}".format(log_file), file=sys.stderr)
                
                return 52

    return 0
Beispiel #11
0
def create_csc(csc, target_directory, a):
    """Output simulation csc"""
    import os.path
    from xml.sax.saxutils import escape

    from simulator import Configuration

    def pcsc(*args, **kwargs):
        print(*args, file=csc, **kwargs)

    firmware_path = os.path.abspath(os.path.join(target_directory, "main.exe"))

    if not os.path.exists(firmware_path):
        raise RuntimeError(f"The firmware at {firmware_path} is missing")

    pcsc('<?xml version="1.0" encoding="UTF-8"?>')
    pcsc('<!-- Generated at: {} -->'.format(datetime.now()))
    pcsc('<simconf>')
    pcsc('  <project EXPORT="discard">[APPS_DIR]/mrm</project>')
    pcsc('  <project EXPORT="discard">[APPS_DIR]/mspsim</project>')
    pcsc('  <project EXPORT="discard">[APPS_DIR]/avrora</project>')
    #pcsc('  <project EXPORT="discard">[APPS_DIR]/serial_socket</project>')
    #pcsc('  <project EXPORT="discard">[APPS_DIR]/collect-view</project>')
    pcsc('  <project EXPORT="discard">[APPS_DIR]/powertracker</project>')
    pcsc('  <simulation>')
    pcsc('    <title>My simulation</title>')
    pcsc('    <speedlimit>null</speedlimit>')
    pcsc('    <randomseed>{}</randomseed>'.format(a.args.seed))
    pcsc('    <motedelay_us>{}</motedelay_us>'.format(
        int(a.args.latest_node_start_time * 1000000)))
    pcsc('    <radiomedium>')
    pcsc(a.args.radio_model.cooja_csc())
    pcsc('    </radiomedium>')
    pcsc('    <events>')
    pcsc('      <logoutput>40000</logoutput>')
    pcsc('    </events>')
    pcsc('    <motetype>')
    pcsc(a.args.platform.cooja_csc(firmware_path))
    pcsc('    </motetype>')

    # Output topology file
    configuration = Configuration.create(a.args.configuration, a.args)

    for (nid, (x, y)) in sorted(configuration.topology.nodes.items(),
                                key=lambda k: k[0].nid):
        pcsc('    <mote>')
        pcsc('      <breakpoints />')
        pcsc('      <interface_config>')
        pcsc('        org.contikios.cooja.interfaces.Position')
        pcsc('        <x>{}</x>'.format(x))
        pcsc('        <y>{}</y>'.format(y))
        pcsc('        <z>0.0</z>')
        pcsc('      </interface_config>')

        pcsc(a.args.platform.node_interface_configs(nid=nid))

        pcsc('      <motetype_identifier>{}</motetype_identifier>'.format(
            a.args.platform.platform()))
        pcsc('    </mote>')

    pcsc('  </simulation>')

    try:
        seconds_to_run = a.args.safety_period
    except AttributeError:
        slowest_source_period = a.args.source_period if isinstance(
            a.args.source_period, float) else a.args.source_period.slowest()
        seconds_to_run = configuration.size() * 4.0 * slowest_source_period

    # Many algorithms have some sort of setup period, so it is important to allow cooja to consider some time for this
    # Try getting this value from the algorithm itself, otherwise guess 15 seconds
    seconds_to_run += getattr(a, "cycle_accurate_setup_period", 15.0)

    # See: https://github.com/contiki-os/contiki/wiki/Using-Cooja-Test-Scripts-to-Automate-Simulations
    # for documentation on this scripting language

    pcsc('  <plugin>')
    pcsc('    org.contikios.cooja.plugins.ScriptRunner')
    pcsc('    <plugin_config>')
    pcsc('      <script>')
    pcsc(
        escape(f"""
/* Make test automatically timeout after the safety period (milliseconds) */
TIMEOUT({int(seconds_to_run * 1000)}, log.testOK()); /* milliseconds. print last msg at timeout */

// Detect Leds changing on the motes
// Doing this in Cooja is cheaper than doing it on the motes
function LedObserver(node)
{{
    this.node = node;
    this.green = null;
    this.yellow = null;
    this.red = null;
    this.update = function(o, arg)
    {{
        var mmled = o;

        var g = mmled.isGreenOn() ? 1 : 0;  // Led1
        var y = mmled.isRedOn() ? 1 : 0;    // Led0
        var r = mmled.isYellowOn() ? 1 : 0; // Led2

        if (this.green != g || this.red != r || this.yellow != y)
        {{
            this.green = g;
            this.red = r;
            this.yellow = y;

            java.lang.System.err.println(sim.getSimulationTime() + "|LedsCooja:D:" + this.node.getID() + ":None:" + y + "," + g + "," + r);
        }}
    }};
}}

allMotes = sim.getMotes();
for (var i = 0; i < allMotes.length; i++)
{{
    ledObserver = new java.util.Observer(new LedObserver(allMotes[i]));

    allMotes[i].getInterfaces().getLED().addObserver(ledObserver);
}}

while (true)
{{
    java.lang.System.err.println(time + "|" + msg);

    YIELD();
}}
log.testOK(); /* Report test success and quit */
"""))
    pcsc('      </script>')
    pcsc('      <active>true</active>')
    pcsc('    </plugin_config>')
    pcsc('  </plugin>')

    pcsc('</simconf>')
    def _submit_job(self, a, target_directory):

        name = target_directory[len("testbed-"):-len("-real")]
        name = name.replace("/", "-")

        configuration = Configuration.create(a.args.configuration, a.args)

        duration_min = int(math.ceil(self.duration.total_seconds() / 60))

        testbed_name = type(configuration.topology).__name__.lower()

        platform = self._get_platform(configuration.topology.platform)
        profile = "wsn430_with_power"

        if configuration.topology.platform == "wsn430v13":
            print(
                "*********************************************************************"
            )
            print(
                "* WARNING: The CC1101 interrupt line from the radio                 *"
            )
            print(
                "* to the MSP430 CPU is not connected on the wsn430v13               *"
            )
            print(
                "* hardware on the FIT IoT-Lab. This will prevent it from            *"
            )
            print(
                "* sending messages.                                                 *"
            )
            print(
                "* See: https://github.com/iot-lab/iot-lab/wiki/Hardware_Wsn430-node *"
            )
            print(
                "* This website says that the CC2420 is affected, but I have only    *"
            )
            print(
                "* observed this with wsn430v13 and the wsn430v14 seems to work.     *"
            )
            print(
                "*********************************************************************"
            )

        # Need to get a shorter name
        experiment_name = name.replace("ReliableFaultModel__-",
                                       "").replace("topology-", "")

        command = [
            "iotlab-experiment",
            "submit",
            f"--name \"{experiment_name}\"",
            f"--duration {duration_min}",
        ]

        # Send this script to be executed
        # It will start the serial aggregator automatically and
        # gather the output from the nodes
        aggregator_script = "data/testbed/info/fitiotlab/aggregator.sh"

        # If the site supports executing the aggregator script, then just have it run it.
        # Otherwise, we need to find another site to run the script on.
        if configuration.topology.support_script_execution:
            command.append(
                f"--site-association \"{testbed_name},script={aggregator_script}\""
            )
        else:
            raise RuntimeError(
                f"The site {testbed_name} does not support script execution")

        for node in configuration.topology.nodes:
            executable = os.path.join(target_directory, f"main-{node}.ihex")

            if not os.path.isfile(executable):
                raise RuntimeError(
                    f"Could not find '{executable}'. Did you forget to build the binaries with the --generate-per-node-id-binary options?"
                )

            command.append(
                f"--list {testbed_name},{platform},{node},{executable}")

        print(" ".join(command))

        if self.dry_run:
            print("Dry run complete!")
            return

        print(f"Submitting {name} to {testbed_name}...")
        subprocess.check_call(" ".join(command), shell=True)