Beispiel #1
0
class Node:
    def __init__(self, env, id, gen, routing_controller):
        self.env = env
        self.id = id
        self.in_packets = simpy.Store(self.env, capacity=1)
        self.outgoing_ports = {}
        self.port_monitors = {}
        self.links = {}
        self.env.process(self.run())
        self.gen = gen
        self.packet_generator = None
        self.routing_controller = self._connect_to_controller(
            routing_controller)
        self.packet_sink = PacketSink(env=self.env,
                                      rec_arrivals=True,
                                      id="{}_ps".format(self.id))
        self.packets_rec = 0
        self.packets_sent_to_port = 0  #Packets sent to a port but still ave to go trough the queue
        self.route_time = 0

    def _connect_to_controller(self, controller):
        controller.register_node(self.id)
        return controller

    def set_packet_generator(self, lbd, possible_destinations=None):
        self.packet_generator = self._create_packet_generator(
            lbd, possible_destinations)
        self.packet_generator.out = self
        return self.packet_generator

    def _create_packet_generator(self, lbd, possible_destinations):
        def dstdist(gen, possible_destinations):
            if possible_destinations is None:
                return None
            else:
                return gen.choice(possible_destinations)

        def next_packet_time(gen, lbd):
            return gen.exponential(lbd)

        def packet_size():
            return 100

        dstdist_partial = partial(dstdist, self.gen, possible_destinations)
        next_packet_time_partial = partial(next_packet_time, self.gen, lbd)
        return PacketGenerator(env=self.env,
                               id="{}_pg".format(self.id),
                               adist=next_packet_time_partial,
                               sdist=packet_size,
                               dstdist=dstdist_partial)

    def _get_port_id(self, dst_node_id):
        return "{}_{}".format(self.id, dst_node_id)

    def _get_link_id(self, dst_node_id):
        return "link_{}_{}".format(self.id, dst_node_id)

    def _add_outgoing_port(self, dst_node, rate, qlimit):
        outgoing_port_id = self._get_port_id(dst_node.id)
        port = self._create_switchport(rate,
                                       qlimit,
                                       outgoing_port_id=outgoing_port_id)
        self.outgoing_ports[outgoing_port_id] = port
        return port

    def _create_switchport(self, rate, qlimit, outgoing_port_id):
        return SwitchPort(self.env,
                          rate=rate,
                          qlimit=qlimit,
                          limit_bytes=False,
                          id=outgoing_port_id)

    def _create_link(self, dst_node, propagation_delay, linkid):
        link = Link(env=self.env,
                    id=linkid,
                    propagation_delay=propagation_delay,
                    dst_node=dst_node)
        return link

    def _add_link(self, dst_node, propagation_delay):
        linkid = self._get_link_id(dst_node.id)
        link = self._create_link(dst_node, propagation_delay, linkid)
        self.links[linkid] = link
        return link

    def _add_connection(self, dst_node, rate, qlimit, propagation_delay):
        new_port = self._add_outgoing_port(dst_node, rate, qlimit)
        new_link = self._add_link(dst_node, propagation_delay)
        new_port.out = new_link
        self.routing_controller.register_connection(self.id, new_port.id)

        return new_port

    def add_connection(self, dst_node, rate, qlimit, monitor_rate,
                       propagation_delay):
        new_port = self._add_connection(dst_node=dst_node,
                                        rate=rate,
                                        qlimit=qlimit,
                                        propagation_delay=propagation_delay)
        new_port_monitor = self._add_portmonitor(new_port, monitor_rate)

        return new_port

    def _add_portmonitor(self, port, monitor_rate):
        outgoing_port_id = port.id
        portmonitor = self._create_portmonitor(port, monitor_rate)
        self.port_monitors[outgoing_port_id] = portmonitor
        return portmonitor

    def _create_portmonitor(self, port, monitor_rate):
        pmdist = self._get_pmdist(monitor_rate)
        return PortMonitor(self.env, port, dist=pmdist)

    def _get_pmdist(self, monitor_rate):
        def dist(gen, lbd):
            return gen.exponential(lbd)

        dist_partial = partial(dist, self.gen, monitor_rate)

        return dist_partial

    def _route(self, packet):
        outgoing_port_id = self.routing_controller.route_packet(
            nodeid=self.id,
            outgoing_ports=list(self.outgoing_ports.keys()),
            stats=self._get_stats_to_controller(),
            packet=packet)
        outgoing_port = self.get_outgoing_port(outgoing_port_id)
        return outgoing_port

    def get_queue_port(self, portid):
        port = self.get_outgoing_port(portid)
        return len(port.store.items)

    def get_queues(self):
        queues_dict = {k: self.get_queue_port(k) for k in self.outgoing_ports}
        return queues_dict

    def get_portmonitor(self, portid):
        return self.port_monitors[portid]

    def get_outgoing_port(self, portid):
        return self.outgoing_ports[portid]

    def _get_stats_to_controller(self):
        stats = {}
        stats["queue_size"] = self.get_queues()
        return stats

    def run(self):
        while True:
            packet = (yield self.in_packets.get())
            outgoing_port = self._route(packet)
            print("Sending packet from " + self.id + " to port " +
                  outgoing_port.id)
            outgoing_port.put(packet)
            self.packets_sent_to_port += 1

    def put(self, packet):
        self.packets_rec += 1
        logger.debug(
            f"Packet received in {self.__class__.__name__} {self.id} at {self.env.now}: "
            + str(packet))
        if packet.dst == self.id:
            return self.packet_sink.put(packet)
        else:
            return self.in_packets.put(packet)
class Node(object):
    def __init__(self, id, env, gen):
        self.env = env
        self.id = id
        self.packet_generator = None
        self.output_ports = {}
        self.port_monitors = {}
        self.routes = {}
        self.routing_algo = None
        self.env.process(self.run())
        self.packet_sink = PacketSink(env=self.env,
                                      rec_arrivals=True,
                                      id="{}_ps".format(self.id))
        self.gen = gen

        self.incoming_packets = simpy.Store(self.env, capacity=1)
        self.packets_received = 0
        self.packets_sent = 0

    def set_routing_algo(self):
        # put this router into the controller controller.setNode(self.id)
        self.routing_algo = RoutingAlgorithm(gen=self.gen, node=self)

    def set_packet_generator(self, lbd, possible_destinations):
        def dstdist(gen, possible_destinations):
            if possible_destinations is None:
                return None
            else:
                return gen.choice(possible_destinations)

        def next_packet_time(gen, lbd):
            return gen.exponential(lbd)

        packet_dst = partial(dstdist, self.gen, possible_destinations)
        next_pkt_time = partial(next_packet_time, self.gen, lbd)
        self.packet_generator = PacketGenerator(env=self.env,
                                                id="{}_pg".format(self.id),
                                                adist=next_pkt_time,
                                                sdist=100,
                                                dstdist=packet_dst)

        ## LOOK AT THIS AGAIN - might want to consider putting it into a switch port
        self.packet_generator.out = self

    def get_port_id(self, dst_node_id):
        return "{}_{}".format(self.id, dst_node_id)

    def get_link_id(self, dst_node_id):
        return "{}_{}".format(self.id, dst_node_id)

    def add_connection(self,
                       dst_node,
                       rate,
                       qlimit,
                       monitor_rate,
                       propagation_delay,
                       bidirectional=False):
        port_id = self.get_port_id(dst_node.id)
        new_port = SwitchPort(self.env,
                              rate=rate,
                              qlimit=qlimit,
                              limit_bytes=False,
                              id=port_id)
        self.output_ports[port_id] = new_port

        link_id = self.get_link_id(dst_node.id)
        new_link = Link(self.env,
                        id=link_id,
                        delay=propagation_delay,
                        dst=dst_node,
                        src=self.id,
                        switch_port=new_port)
        self.routes[link_id] = new_link

        new_port.out = new_link

        def dist(gen, lbd):
            return gen.exponential(lbd)

        port_monitor_id = new_port.id
        dist_partial = partial(dist, self.gen, monitor_rate)
        port_monitor = PortMonitor(self.env, port=new_port, dist=dist_partial)
        self.port_monitors[port_monitor_id] = port_monitor

        if bidirectional:
            dst_node.add_connection(self, rate, qlimit, monitor_rate,
                                    propagation_delay)

    def route(self, packet):
        return self.routing_algo.route_packet(packet)

    def put(self, packet):
        self.packets_received += 1
        if packet.dst == self.id:
            self.packet_sink.put(packet)
        else:
            self.incoming_packets.put(packet)

    def run(self):
        while True:
            packet = yield (self.incoming_packets.get())
            outgoing_port = self.route(packet)
            if self.routes[outgoing_port.id].up:
                # Increment counter in packet
                packet.incrementHops()
                packet.incrementRouteWeight(self.routes[outgoing_port.id].cost)
                packet.decrement_ttl()

                outgoing_port.put(packet)
                self.packets_sent += 1
Beispiel #3
0
class Node(object):

    def __init__(self, id, env, gen):
        self.env = env
        self.id = id
        self.packet_generator = None
        self.gen = gen
        self.routes = {}
        self.routing_algorithm = None
        self.network = None
        self.env.process(self.run())

        self.packet_sink = PacketSink(env=self.env, rec_arrivals=True)
        self.packets_to_send = simpy.Store(self.env, capacity=1)
        self.packets_forwarded = 0
        self.packets_not_acknowledged = []

        self.switch_port = SwitchPort(env=self.env, rate=20, qlimit=64, limit_bytes=False, id=self.id)
        self.switch_port.out = self.packets_to_send
        #self.port_monitor = PortMonitor(env, self.switch_port, dist=1)

    def set_network(self, network):
        """ Set the network in which the node is placed in
        :param network: network
        :return: None
        """
        self.network = network
        return

    def set_routing_algorithm(self, controller="RL"):
        """Set routing algorithm for this node
        :param controller:
        :return:
        """
        if controller == "random":
            self.routing_algorithm = RandomRouting(gen=self.gen, node=self, graph=self.network)
        elif controller == "dijkstra":
            self.routing_algorithm = Dijkstra(graph=self.network, node=self)
        elif controller == "RL":
            self.routing_algorithm = RLRouting(node=self, graph=self.network)
        else:
            pass

    def route(self, packet):
        """Query the rooting algorithm for a link to route the packet to
        :param packet:
        :return:
        """
        return self.routing_algorithm.route_packet(packet)

    def set_packet_generator(self, lbd, possible_destinations):
        """
        :param lbd:
        :param possible_destinations:
        :return:
        """
        def dst_dist(gen, destinations):
            if destinations is None:
                return None
            else:
                return gen.choice(destinations)

        def next_packet_time(gen, lbd_):
            return gen.exponential(lbd_)

        packet_dst = partial(dst_dist, self.gen, possible_destinations)
        next_pkt_time = partial(next_packet_time, self.gen, lbd)
        self.packet_generator = PacketGenerator(env=self.env, id="{}_pg".format(self.id), adist=next_pkt_time, sdist=100, dstdist=packet_dst)

        ## LOOK AT THIS AGAIN - might want to consider putting it into a switch port
        self.packet_generator.out = self.packets_to_send

    def get_port_id(self, dst_node_id):
        return "{}_{}".format(self.id, dst_node_id)

    def get_link_id(self, dst_node):
        return "{}_{}".format(self.id, dst_node.id)

    def add_connection(self, dst_node, rate, qlimit, monitor_rate, propagation_delay, bidirectional=True):
        """Add a new connection to this node given the following set of parameters
        :param dst_node:
        :param rate:
        :param qlimit:
        :param monitor_rate:
        :param propagation_delay:
        :param bidirectional:
        :return:
        """
        link_id = self.get_link_id(dst_node)
        new_link = Link(self.env, id=link_id, cost=propagation_delay, dst=dst_node, src=self)
        self.routes[link_id] = new_link

        if bidirectional:
            new_link_reverse = dst_node.add_connection(self, rate=rate, qlimit=qlimit, monitor_rate=monitor_rate, propagation_delay=propagation_delay, bidirectional=False)
            return [new_link, new_link_reverse[0]]

        return [new_link]

    def id_str_to_num(self):
        return int(self.id.strip("n"))

    def get_neighbours(self):
        """Get neighbours of this node
        :return: list of neighbouring nodes sorted by id
        """
        neighbours = []
        neighbour_debug = []
        neighbour_id = self.get_neighbour_id()

        for name in neighbour_id:
            link_name = "{}_{}".format(self.id, name)
            neighbours.append(self.routes[link_name].dst)
            neighbour_debug.append(link_name)

        #print("debug " + str(neighbour_debug))
        return neighbours

    def get_neighbour_id(self):
        """Get all id's of neighbours of this node
        :return: sorted list of of neighbour ids
        """
        neighbour_id = []

        for link in self.routes.values():
            if link.src.id == self.id:
                neighbour = link.dst
            else:
                neighbour = link.src
            neighbour_id.append(neighbour.id)

        neighbour_id.sort()
        return neighbour_id

    def is_neighbour(self, node):
        """Check if a certain node is a neighbour of this node
        :param node: Node name (str) to be searched for among the neighbours
        :return: Boolean indicating if the node is found
        """
        if node == self:
            return False

        for link in self.routes.values():
            if link.dst == node or link.src == node:
                return True
        return False

    def get_link(self, node):
        return self.routes["{}_{}".format(self.id, node.id)]

    def clear_packets(self):
        """Clear all packets from the node's switch port
        :return: None
        """
        while len(self.packets_to_send.items) is not 0:
            packet = self.packets_to_send.get()
            del packet
        self.switch_port.clear_packets()
        #del self.switch_port
        #self.switch_port = SwitchPort(env=self.env, rate=20, qlimit=64, limit_bytes=False, id=self.id)

    def send_acknowledgement(self, packet):
        pkt = AcknowledgementPacket(time=self.env.now, src=self.id, dst=packet.src, id=packet.id, size=1)
        print("creating ack packet with dst" + str(pkt.dst))
        self.put(pkt)

    def put(self, packet):
        """Called by objects that wants to put a packet into this node
        :param packet: Packet object
        :return: None
        """
        if not isinstance(packet, Packet):
            return
        previous_node = packet.current_node
        packet.set_current_node(self)
        if packet.dst == self.id:

            if isinstance(packet, AcknowledgementPacket):
                self.packets_not_acknowledged.remove("n{}".format(packet.acknowledgement_id.strip("ack")))
            else:
                self.packet_sink.put(packet)
                # self.send_acknowledgement(packet)
        else:
            self.switch_port.put(packet)
            if packet.src == self.id:
                self.packets_not_acknowledged.append(packet.id)

        if previous_node is not None:
            print("Packet " + str(packet.id) + " put from node " + str(previous_node.id) + " into node " + str(self.id))
        else:
            print("Packet " + str(packet.id) + " put into node " + str(self.id))

    def run(self):
        """Simpy process: constantly runs and creates events that are put into the event queue
        :return: None
        """
        while True:
            packet = yield (self.packets_to_send.get())
            outgoing_port = self.route(packet)
            if outgoing_port is not None and self.routes[outgoing_port.id].state:
                packet.increment_hops()
                packet.incrementRouteWeight(self.routes[outgoing_port.id].cost)
                packet.total_traffic += self.routes[outgoing_port.id].traffic
                packet.decrement_ttl(self.env.now)
                packet.path.append([outgoing_port.dst.id, self.routes[outgoing_port.id].cost])
                outgoing_port.put(packet)
                self.packets_forwarded += 1
            elif outgoing_port is None:
                self.put(packet)
            else:
                pass
Beispiel #4
0
class Node(object):
    def __init__(self, id, env, gen):
        self.env = env
        self.id = id
        self.packet_generator = None
        self.gen = gen
        self.routes = {}
        self.routing_algorithm = None
        self.network = None
        self.env.process(self.run())
        self.packet_sink = PacketSink(env=self.env, rec_arrivals=True)
        self.packets_to_send = simpy.Store(self.env, capacity=1)
        self.packets_sent = 0

        self.switch_port = SwitchPort(env=env,
                                      rate=500,
                                      qlimit=64,
                                      limit_bytes=False,
                                      id=self.id)
        self.switch_port.out = self.packets_to_send
        #self.port_monitor = PortMonitor(env, self.switch_port, dist=1)

    def set_network(self, network):
        """
        Set the network in which the node is placed in
        :param network:
        :return:
        """
        self.network = network

    def set_routing_algo(self, controller):
        # put this router into the controller controller.setNode(self.id)
        if controller == "random":
            self.routing_algorithm = RandomRouting(gen=self.gen,
                                                   node=self,
                                                   graph=self.network)
        elif controller == "dijkstra":
            self.routing_algorithm = Dijkstra(graph=self.network, node=self)
        else:
            pass

    def route(self, packet):
        return self.routing_algorithm.route_packet(packet)

    def set_packet_generator(self, lbd, possible_destinations):
        def dst_dist(gen, destinations):
            if destinations is None:
                return None
            else:
                return gen.choice(destinations)

        def next_packet_time(gen, lbd_):
            return gen.exponential(lbd_)

        packet_dst = partial(dst_dist, self.gen, possible_destinations)
        next_pkt_time = partial(next_packet_time, self.gen, lbd)
        self.packet_generator = PacketGenerator(env=self.env,
                                                id="{}_pg".format(self.id),
                                                adist=next_pkt_time,
                                                sdist=100,
                                                dstdist=packet_dst)

        ## LOOK AT THIS AGAIN - might want to consider putting it into a switch port
        self.packet_generator.out = self.packets_to_send

    def get_port_id(self, dst_node_id):
        return "{}_{}".format(self.id, dst_node_id)

    def get_link_id(self, dst_node):
        return "{}_{}".format(self.id, dst_node.id)

    def add_connection(self,
                       dst_node,
                       rate,
                       qlimit,
                       monitor_rate,
                       propagation_delay,
                       bidirectional=True):
        """
        Add a new connection to this node given the following set of parameters
        :param dst_node:
        :param rate:
        :param qlimit:
        :param monitor_rate:
        :param propagation_delay:
        :param bidirectional:
        :return:
        """
        link_id = self.get_link_id(dst_node)
        new_link = Link(self.env,
                        id=link_id,
                        cost=propagation_delay,
                        dst=dst_node,
                        src=self.id)
        self.routes[link_id] = new_link

        if bidirectional:
            new_link_reverse = dst_node.add_connection(self,
                                                       rate,
                                                       qlimit,
                                                       monitor_rate,
                                                       propagation_delay,
                                                       bidirectional=False)
            return [new_link, new_link_reverse[0]]

        return [new_link]

    def is_neighbour(self, node):
        """
        Check if a certain node is a neighbour of this node
        :param node: Node name (str) to be searched for among the neighbours
        :return: Boolean indicating if the node is found
        """
        if node == self:
            return False

        for link in self.routes.values():
            if link.dst == node or link.src == node:
                return True
        return False

    def get_link_weight(self, node):
        pass

    def clear_packets(self):
        """
        Clear all packets from the node's switch port
        :return:
        """
        self.switch_port.clear_packets()

    def put(self, packet):
        if not isinstance(packet, Packet):
            return

        packet.set_current_node(self)
        if packet.dst == self.id:
            self.packet_sink.put(packet)
        else:
            self.switch_port.put(packet)
        print("Packet " + str(packet.id) + " put into node " + str(self.id))

    def run(self):
        while True:
            packet = yield (self.packets_to_send.get())
            outgoing_port = self.route(packet)
            if outgoing_port is not None and self.routes[
                    outgoing_port.id].state:
                # Increment counter in packet
                packet.increment_hops()
                packet.incrementRouteWeight(self.routes[outgoing_port.id].cost)
                packet.decrement_ttl()

                outgoing_port.put(packet)
                self.packets_sent += 1