Esempio n. 1
0
class Simulator(object):

    def __init__(self, network_file_path, configs):
        self.configs = configs
        self.file_path = network_file_path

        # Initialize the event manager
        self.mgr = EventManager()
        self.collector = DataCollector()

        # Read network in from file.
        with open(file_path, 'r') as yaml_file:
            network = yaml.load(yaml_file)

        # Initialize the network components
        self.hosts = {}
        for host_name in network['hosts']:
            self.hosts[host_name] = Host(host_name, self, self.collector)

        self.routers = {}
        if 'routers' in network:
            for router_name in network['routers']:
                self.routers[router_name] = Router(router_name, self)

        self.flows = {}
        for flow_dict in network['flows']:
            flow_name = flow_dict.keys()[0]
            flow_desc = flow_dict[flow_name]

            self.flows[flow_name] = Flow(
                flow_name,
                self,
                self.collector,
                self.hosts[flow_desc['source']] ,
                self.hosts[flow_desc['destination']],
                flow_desc['amount'],
                flow_desc['start']
            )

        self.links = {}
        host_prefixes = ['H', 'S', 'T']
        for link_dict in network['links']:
            link_name = link_dict.keys()[0]
            link_desc = link_dict[link_name]

            aname = link_desc['anode']
            bname = link_desc['bnode']

            ahost = self.hosts[aname] \
                if aname[0] in host_prefixes else self.routers[aname]
            bhost = self.hosts[bname] \
                if bname[0] in host_prefixes else self.routers[bname]

            link = Link(
                link_name,
                self,
                self.collector,
                link_desc['rate'] / 8.0,
                link_desc['delay'],
                link_desc['buffer'],
                link_desc['buffer'],
                ahost,
                bhost
            )

            self.links[link_name] = link

            ahost.set_link(link)
            bhost.set_link(link)

            self.mgr.add_event(0.0, link.calculate_throughput, [])

        # Add initial events for each of the flows
        for flow in self.flows.values():
            self.mgr.add_event(flow.start_t, flow.send_packet, [])

            if not configs['tcpreno']:
                self.mgr.add_event(flow.start_t, flow.tcp_fast_update, [])

        # Initialize the routing tables
        for router in self.routers.values():
            router.init_routing_table()

        if len(self.routers) > 0:
            self.mgr.add_event(0.0, self.routers['R1'].send_rout_packet, [])
            self.mgr.add_event(self.mgr.t + configs['dynamic_routing_step'],
                               self.start_dynamic_routing, [])

    def get_data(self):
        """Telling all of the objects to report their data."""

        for flow in self.flows.values():
            self.mgr.add_event(0.0, flow.report_rates, [0.1, 0, 0])
            self.mgr.add_event(0.0, flow.report_link_rates, [0.2, {}])

        for link in self.links.values():
            self.mgr.add_event(0.0, link.report_occupancy, [0.1])
            self.mgr.add_event(0.0, link.report_dropped, [0.1])
            self.mgr.add_event(0.0, link.report_throughput, [0.5])

        for host in self.hosts.values():
            self.mgr.add_event(0.0, host.report_rates, [0.1, 0, 0])

    def start_dynamic_routing(self):
        # Initialize the routing tables and send out routing packets
        for router in self.routers.values():
            router.init_routing_table(temp_table=True)
            router.start_dynamic_routing()
            router.send_rout_packet(True)

        self.mgr.add_event(self.mgr.t + self.configs['dynamic_routing_step'],
                           self.start_dynamic_routing, [])

    def check_done_dynamic_routing(self):
        time_step = 0.01
        num_not_done = 0

        for router in self.routers.values():
            if not router.done_d_routing:
                num_not_done += 1

        if num_not_done == 0:
            for router in self.routers.values():
                router.finish_dynamic_routing()

            for link in self.links.values():
                link.time_through_link_update()

    def run(self):

        # Starting data collection
        self.get_data()

        while self.mgr.has_events():
            (t, event, args) = self.mgr.pop_event()
            self.mgr.t = t
            event(*args)

            # Check if all our flows have terminated
            flows_not_done = len(self.flows)
            for flow in self.flows.values():
                if flow.last_acknowledged == flow.max_seq:
                    flows_not_done -= 1

            if flows_not_done == 0:
                break

        print 'Done with all events at time: {}'.format(self.mgr.t)

    def plot(self):
        # Get only the file_name
        file_name = self.file_path.split("/")[-1].rstrip(".yml")

        # Print the plots to pdf
        plot_dir = "plots/"

        # Whether or not its reno or fast
        if self.configs['tcpreno']:
            mode = '_reno'
        else:
            mode = '_fast'

        # Pdf page
        pp = PdfPages(plot_dir + file_name + mode + '.pdf')

        print 'Plotting to {}'.format(plot_dir + file_name + mode + '.pdf')

        collecs = self.collector.collection.keys()
        collecs.sort()

        for g in collecs:
            self.collector.graph_data(pp, g, g)

        if file_name =='testcase0':
            # The congestion window for the flow
            self.collector.graph_data(pp, 'F1 Congestion Window', 'F1_cwnd')

        elif file_name == 'testcase1':
            # The congestion window for the flow
            self.collector.graph_data(pp, 'F1 Congestion Window', 'F1_cwnd')

            # The link rates of L1 and L2
            self.collector.combine_graphs(
                pp, 'Test Case 1 Link Rates',
                ['F1_L1_rate', 'F1_L2_rate'],
                labels=['L1', 'L2']
            )

            # The link rates of L3 and L4
            self.collector.combine_graphs(
                pp,
                'Test Case 1 Link Rates',
                ['F1_L3_rate', 'F1_L4_rate'],
                labels=['L3', 'L4']
            )

        elif file_name == 'testcase2':
            self.collector.combine_graphs(
                pp,
                'Test Case 2 Flow Congestion Windows',
                ['F1_cwnd', 'F2_cwnd', 'F3_cwnd'],
                labels=['F1', 'F2', 'F3']
            )

            self.collector.combine_graphs(
                pp,
                'Test Case 2 Buffer Occupancy',
                ['L1_a_occupancy', 'L2_a_occupancy', 'L3_a_occupancy'],
                labels=['L1a', 'L2a', 'L3a']
            )

        pp.close()