Source

imalse / core / ns3 / experiment / experiment.py

"""

This file contains code that describes the netns3 experiment for imalse

"""

import ns3
from util.util import abstract_method, get_availabe_scenarios, load_scenario

class ImalseExperiment(object):
    """ 
    
    This is the base class for all imalse experiments.
    For testing purposes, just select the first node as server, the second
    node as BotMaster, all other nodes are clients.
    
    """
    server_id_set = [0]
    botmaster_id_set = [1]
    client_id_set = [2, 3, 4]

    @property
    def id_set(self):
        """Return the id's of all the nodes present in the network."""
        return self.server_id_set + self.botmaster_id_set + self.client_id_set

    def initparser(self, parser):
        """Default argument parser."""
        scenario_ops = get_availabe_scenarios()
        parser.add_option('-s', '--scenario', dest="scenario",
                default='ddos_ping_flooding',
                help='specify the scenario you want to execute. Scenarios available are: %s'%(scenario_ops),
                )

    def _init(self):
        """This methods should be implemented by the child class.""" 
        pass
    def setup(self):
        """This methods should be implemented by the child class.""" 
        pass

    def get_node(self, i):
        """Get ith node."""
        abstract_method()

    @property
    def node_num(self):
        """Get the amount of nodes. Should be implemented by a child class."""
        abstract_method()

    def node_run(self, node, *args, **kwargs):
        """Run a command on a specific node."""
        node.cmd_set.trigger(*args, **kwargs)

    def start_nodes(self):
        """
        
        Specify when the nodes should start. The server should always start
        first followed by the clients which can connect with the server. When
        the clients have established a connection the botmaster van be started.
        
        """
        
        for i in self.server_id_set:
            print 'node [%i] type [%s] start at [%f]s'%(i, 'server', 0)
            self.event(0, self.node_run, self.get_node(i), 'start')

        t = 0
        for i in self.client_id_set:
            t += 2
            print 'node [%i] type [%s] start at [%f]s'%(i, 'client', t)
            self.event(t, self.node_run, self.get_node(i), 'start')
        
        for i in self.botmaster_id_set:
            print 'node [%i] type [%s] start at [%f]s'%(i, 'BotMaster', t+2)
            self.event(t+2, self.node_run, self.get_node(i), 'start')

    def install_cmds(self, srv_addr=None):
        """
        
        Install the three different command sets on the nodes according to 
        their type. It is possible to manually set the server address.
        
        Depending on the scenario. The target hostname should equal the server 
        node or an unused node, due to the fact that all internet traffic is 
        contained in the simulated network.
        
        """
        scen = load_scenario(self.options.scenario)
        BOTMASTER_DESC = scen.config.Botmaster()
        SERVER_DESC = scen.config.Server()
        CLIENT_DESC = scen.config.Client()
                
        try:            
            if self.target_id is not None:                
                if self.get_node(self.target_id).NODE_TYPE == 'sim_ns3':
                    target_ip = self.get_node(self.target_id).GetObject(ns3.TypeId.LookupByName("ns3::Ipv4")).GetAddress(1, 0).GetLocal()            
                    BOTMASTER_DESC.command.hostname = str(target_ip)
                elif self.get_node(self.target_id).NODE_TYPE == 'real_ns3':
                    BOTMASTER_DESC.command.hostname = BOTMASTER_DESC.server_address
        except AttributeError:
            try:
                BOTMASTER_DESC.command.hostname = BOTMASTER_DESC.server_address
            except AttributeError:
                pass
        
        if srv_addr is not None:
            BOTMASTER_DESC.server_address = srv_addr
            SERVER_DESC.server_address = srv_addr
            CLIENT_DESC.server_address = srv_addr     
                               
        for i in xrange(self.node_num):
            if i in self.botmaster_id_set:
                cmd = scen.BotMaster(BOTMASTER_DESC)
            elif i in self.server_id_set:
                cmd = scen.ServerCMD(SERVER_DESC)
            elif i in self.client_id_set:
                cmd = scen.ClientCMD(CLIENT_DESC)
            else:
                continue
            cmd.install(self.get_node(i))

    def get_server_addr(self):
        """Get all the server addresses."""
        addr_set = []
        for i in self.server_id_set:
            ipv4Addr = self.get_node(i).GetObject(ns3.TypeId.LookupByName("ns3::Ipv4")).GetAddress(1, 0)
            addr_set.append(ipv4Addr)
        return addr_set

    def get_server_nodes(self):
        """Get all the server nodes."""
        return [self.get_node(i) for i in self.server_id_set]

    def set_server_info(self):
        """Only set server information for simulated nodes"""
        server_addr_set = self.get_server_addr()
        server_set = self.get_server_nodes()
        for i in xrange(self.node_num):            
            if self.get_node(i).NODE_TYPE.startswith('real'):
                continue
            self.get_node(i).server_addr_set = server_addr_set
            self.get_node(i).server_set = server_set

    def print_srv_addr(self):
        """Print the address of the server."""
        for i in self.server_id_set:
            ipv4Addr = self.get_node(i).GetObject(ns3.TypeId.LookupByName("ns3::Ipv4")).GetAddress(1, 0)
            print 'The server addr of server [%i ]: '%(i), ipv4Addr