Пример #1
0
    def addPackets(self, packets, sender):
        """ Add packets and return new Events if any.

        A shortcut for sending PacketEvents and so they do not go through
        the EventHandler

        :param packets: new packets to add
        :return: new Events
        """
        newevents = []

        # If this is the first packet in the buffer, start the LinkTickEvents
        if self.buffer.qsize() == 0 and len(packets) > 0:
            newevents = [
                LinkTickEvent(max(simtimer.simtime, self.freeAt), self,
                              'Link ' + self.id + ' processes a packet')
            ]

        for p in packets:
            if self.buffersizes[sender] + p.size > self.maxbuffersize:
                # Drop em' like its hot
                logger.log('Dropping packet %s from host %s at link %s' %
                           (p.index, p.source, self.id))
                self.stats.addLostPackets(simtimer.simtime, 1)
            else:
                self.buffer.put((p, sender))
                self.totalbuffersize += p.size
                self.buffersizes[sender] += p.size

        self.stats.updateBufferOccupancy(simtimer.simtime,
                                         self.totalbuffersize)

        return newevents
Пример #2
0
    def _processPacketEvent(self, packet_event):
        """ Processes packet events, storing them in the buffer.

        :param packet_event: PacketEvent to process (packet to insert)
        :return: new Events to enqueue
        """
        packet, sender = packet_event.packet, packet_event.sender
        if self.buffersizes[sender] + packet.size > self.maxbuffersize:
            self.stats.addLostPackets(packet_event.timestamp, 1)
            logger.log('Dropping packet %s from host %s at link %s' %
                       (packet.index, str(sender), self.id))
            return []

        self.buffer.put((packet, sender))
        self.totalbuffersize += packet.size
        self.buffersizes[sender] += packet.size
        self.stats.updateBufferOccupancy(simtimer.simtime,
                                         self.totalbuffersize)

        # If this is the first packet in the buffer, start the LinkTickEvents
        if self.buffer.qsize() == 1:
            linkevent = LinkTickEvent(
                max(packet_event.timestamp, self.freeAt), self,
                'Link ' + self.id + ' processes a packet')
            return [linkevent]
        return []
Пример #3
0
    def addRouter(self, node_id, init_time, static_routing):
        """ Adds a router to the list of hosts and to the graph representation

        :param node_id: (optional) specify a node id to use for this node.
        :param init_time: (optional) time the router starts up
        :param static_routing: (optional) specify whether to use static
         or dyanmic routing
        :returns: id of router added
        """
        if self.G.has_node(node_id):
            logger.log("router " + str(node_id) + " is already in the graph.")
            return

        self.G.add_node(node_id, host=0)
        self.nodes[node_id] = Router(node_id, [])

        if not static_routing:
            # if dynamic routing, create a update routing table event
            self.events.append(
                UpdateRoutingTableEvent(
                    init_time,
                    self.nodes[node_id],
                    'Router %s updates routing table' % node_id))

        return node_id
Пример #4
0
    def addPackets(self, packets, sender):
        """ Add packets and return new Events if any.

        A shortcut for sending PacketEvents and so they do not go through
        the EventHandler

        :param packets: new packets to add
        :return: new Events
        """
        newevents = []

        # If this is the first packet in the buffer, start the LinkTickEvents
        if self.buffer.qsize() == 0 and len(packets) > 0:
            newevents = [
                LinkTickEvent(max(simtimer.simtime, self.freeAt), self,
                              'Link ' + self.id + ' processes a packet')]

        for p in packets:
            if self.buffersizes[sender] + p.size > self.maxbuffersize:
                # Drop em' like its hot
                logger.log('Dropping packet %s from host %s at link %s' %
                           (p.index, p.source, self.id))
                self.stats.addLostPackets(simtimer.simtime, 1)
            else:
                self.buffer.put((p, sender))
                self.totalbuffersize += p.size
                self.buffersizes[sender] += p.size

        self.stats.updateBufferOccupancy(simtimer.simtime, self.totalbuffersize)

        return newevents
Пример #5
0
    def _timeout(self, timestamp):
        """ Internal function that is called to handle timeouts

        :param timestamp: time that this occurs
        """
        if not self.done and timestamp > self.nextTimeout:
            logger.log('TIMED OUT!')

            self.cwnd = 1
            self.canum = 0
            self.fastrecovery = False

            self.lastRepSent = max(self.lastRepSent, self.nextSend)
            self.nextSend = self.lastAck
            self.nextTimeout = timestamp + 2 * self.srtt
Пример #6
0
    def _timeout(self, timestamp):
        """ Internal function that is called to handle timeouts

        :param timestamp: time that this occurs
        """
        if not self.done and timestamp > self.nextTimeout:
            logger.log('TIMED OUT!')

            self.cwnd = 1
            self.canum = 0
            self.fastrecovery = False

            self.lastRepSent = max(self.lastRepSent, self.nextSend)
            self.nextSend = self.lastAck
            self.nextTimeout = timestamp + 2 * self.srtt
Пример #7
0
    def _processPacketEvent(self, event):
        """ Processes packet events

        Puts response packets (ACK, routing table updates) in link

        Returns new Events to enqueue (e.g. LinkTickEvent)

        :param event: PacketEvent to process
        :return: new Events to enqueue
        """
        packet = event.packet
        timestamp = event.timestamp
        newPackets = []
        # Record arrival of new packet
        if isinstance(packet, Packet):
            self.stats.addBytesRecieved(timestamp, packet.size)

        # Handle routing table update requests
        if isinstance(event.packet, RoutingRequestPacket):
            logger.log('Routing table packet for host %s' % self.address)
            newPacket = RoutingPacket(
                self.address, event.packet.source,
                routingTable={self.address: [self.address, 0]})
            newPackets.append(newPacket)

        # Packet is ACK, update Flow accordingly
        elif isinstance(event.packet, AckPacket):
            assert packet.dest == self.address
            assert packet.flowId in self.flows
            newPackets = self.flows[packet.flowId].receiveAckPacket(
                packet, event.timestamp)
            for p in newPackets:
                logger.log('Flow %s, packet %s from host %s to link %s' %
                           (p.flowId, p.index,
                            self.address, self.links[0].id))

        # Treat packet as data packet, return appropriate ACK
        elif isinstance(event.packet, DataPacket):
            assert packet.dest == self.address
            assert packet.flowId in self.flowrecipients

            newPacket = self.flowrecipients[
                packet.flowId].receiveDataPacket(packet, event.timestamp)
            logger.log('ACK %s for flow %s from host %s to link %s' %
                       (newPacket.index, newPacket.flowId,
                        self.address, self.links[0].id))
            newPackets.append(newPacket)

        # Else we don't know what to do
        else:
            raise NotImplementedError(
                'Handling of %s not implemented' % event.packet.__class__)

        # Record new packets
        for p in newPackets:
            self.stats.addBytesSent(timestamp, p.size)

        return self.links[0].addPackets(newPackets, self)
Пример #8
0
    def _processPacketEvent(self, event):
        """ Processes packet events

        Puts response packets (ACK, routing table updates) in link

        Returns new Events to enqueue (e.g. LinkTickEvent)

        :param event: PacketEvent to process
        :return: new Events to enqueue
        """
        packet = event.packet
        timestamp = event.timestamp
        newPackets = []
        # Record arrival of new packet
        if isinstance(packet, Packet):
            self.stats.addBytesRecieved(timestamp, packet.size)

        # Handle routing table update requests
        if isinstance(event.packet, RoutingRequestPacket):
            logger.log('Routing table packet for host %s' % self.address)
            newPacket = RoutingPacket(
                self.address,
                event.packet.source,
                routingTable={self.address: [self.address, 0]})
            newPackets.append(newPacket)

        # Packet is ACK, update Flow accordingly
        elif isinstance(event.packet, AckPacket):
            assert packet.dest == self.address
            assert packet.flowId in self.flows
            newPackets = self.flows[packet.flowId].receiveAckPacket(
                packet, event.timestamp)
            for p in newPackets:
                logger.log('Flow %s, packet %s from host %s to link %s' %
                           (p.flowId, p.index, self.address, self.links[0].id))

        # Treat packet as data packet, return appropriate ACK
        elif isinstance(event.packet, DataPacket):
            assert packet.dest == self.address
            assert packet.flowId in self.flowrecipients

            newPacket = self.flowrecipients[packet.flowId].receiveDataPacket(
                packet, event.timestamp)
            logger.log('ACK %s for flow %s from host %s to link %s' %
                       (newPacket.index, newPacket.flowId, self.address,
                        self.links[0].id))
            newPackets.append(newPacket)

        # Else we don't know what to do
        else:
            raise NotImplementedError('Handling of %s not implemented' %
                                      event.packet.__class__)

        # Record new packets
        for p in newPackets:
            self.stats.addBytesSent(timestamp, p.size)

        return self.links[0].addPackets(newPackets, self)
Пример #9
0
    def step(self):
        """ Processes one Event from the queue, corresponding to one 'tick'.

        If the queue is empty, this will raise an Empty error.
        :param realtime: [optional] Set to true to simulate in real time
        :param slowdown: [optional] factor to slow down the simulation. Half the simulation rate with .5
        :return: The Event that was just processed.
        """
        # When we get an object from the queue, do not block if empty.
        # Simply raise an Empty exception. This may be changed later.
        event = self._queue.get(block=False)
        simtimer.simtime = event.timestamp

        # Log each event
        logger.log('[%10.3f][%15s] %s' %
                   (event.timestamp, event.__class__, event.logMessage))

        # enqueue new events
        newevents = event.eventObject.processEvent(event)
        for e in newevents:
            self._queue.put(e)
        self.time = event.timestamp
        return event
Пример #10
0
    def step(self):
        """ Processes one Event from the queue, corresponding to one 'tick'.

        If the queue is empty, this will raise an Empty error.
        :param realtime: [optional] Set to true to simulate in real time
        :param slowdown: [optional] factor to slow down the simulation. Half the simulation rate with .5
        :return: The Event that was just processed.
        """
        # When we get an object from the queue, do not block if empty.
        # Simply raise an Empty exception. This may be changed later.
        event = self._queue.get(block=False)
        simtimer.simtime = event.timestamp

        # Log each event
        logger.log('[%10.3f][%15s] %s' %
                   (event.timestamp, event.__class__, event.logMessage))

        # enqueue new events
        newevents = event.eventObject.processEvent(event)
        for e in newevents:
            self._queue.put(e)
        self.time = event.timestamp
        return event
Пример #11
0
    def _processPacketEvent(self, packet_event):
        """ Processes packet events, storing them in the buffer.

        :param packet_event: PacketEvent to process (packet to insert)
        :return: new Events to enqueue
        """
        packet, sender = packet_event.packet, packet_event.sender
        if self.buffersizes[sender] + packet.size > self.maxbuffersize:
            self.stats.addLostPackets(packet_event.timestamp, 1)
            logger.log('Dropping packet %s from host %s at link %s' %
                       (packet.index, str(sender), self.id))
            return []

        self.buffer.put((packet, sender))
        self.totalbuffersize += packet.size
        self.buffersizes[sender] += packet.size
        self.stats.updateBufferOccupancy(simtimer.simtime, self.totalbuffersize)

        # If this is the first packet in the buffer, start the LinkTickEvents
        if self.buffer.qsize() == 1:
            linkevent = LinkTickEvent(max(packet_event.timestamp, self.freeAt),
                                      self, 'Link ' + self.id + ' processes a packet')
            return [linkevent]
        return []
Пример #12
0
    def addRouter(self, node_id, init_time, static_routing):
        """ Adds a router to the list of hosts and to the graph representation

        :param node_id: (optional) specify a node id to use for this node.
        :param init_time: (optional) time the router starts up
        :param static_routing: (optional) specify whether to use static
         or dyanmic routing
        :returns: id of router added
        """
        if self.G.has_node(node_id):
            logger.log("router " + str(node_id) + " is already in the graph.")
            return

        self.G.add_node(node_id, host=0)
        self.nodes[node_id] = Router(node_id, [])

        if not static_routing:
            # if dynamic routing, create a update routing table event
            self.events.append(
                UpdateRoutingTableEvent(
                    init_time, self.nodes[node_id],
                    'Router %s updates routing table' % node_id))

        return node_id
Пример #13
0
    def _processPacketEvent(self, event):
        """ Process a PacketEvent

        Timestamp is not changed because there is no
        delay through the router.

        :param packet_event: PacketEvent to process
        :return: new Events to enqueue
        """

        # Data packet, forward to correct link
        if isinstance(event.packet, DataPacket) or \
                isinstance(event.packet, AckPacket):
            nextLink = self.getRoute(event.packet.dest)
            if nextLink:
                logger.log('Router %s forwards packet to %s' %
                           (self.address, nextLink.id))
                return nextLink.addPackets([event.packet], self)
            else:
                logger.log('Router %s dropped packet %s' %
                           (self.address, event.packet.index))

        # Received routing table information, update table
        elif isinstance(event.packet, RoutingPacket):
            neighborTable = event.packet.routingTable
            link = event.sender
            cost = link.cost()

            # overwrite previous
            self.link_table[link] = dict()
            for dest in neighborTable:
                # split horizon to avoid cycles
                if neighborTable[dest][0] != link:
                    self.link_table[link][dest] = neighborTable[dest][1] + cost

            # add dests to routing_table
            for dest in self.link_table[link]:
                if dest not in self.routing_table:
                    self.routing_table[dest] = (link,
                                                self.link_table[link][dest])

            # reset all and recalculate
            for dest in self.routing_table:
                self.routing_table[dest] = (None, 999999)
                for link in self.link_table:
                    if dest in self.link_table[link] and self.link_table[link][
                            dest] < self.routing_table[dest][1]:
                        self.routing_table[dest] = (
                            link, self.link_table[link][dest])

        # Received routing table request
        elif isinstance(event.packet, RoutingRequestPacket):
            # process request for routing table
            logger.log('Routing table packet for router %s' % self.address)
            return event.sender.addPackets([
                RoutingPacket(self.address,
                              event.packet.source,
                              routingTable=self.routing_table)
            ], self)

        # Else we don't know what to do
        else:
            raise NotImplementedError('Handling of %s not implemented' %
                                      event.packet.__class__)

        return []
Пример #14
0
    def _processPacketEvent(self, event):
        """ Process a PacketEvent

        Timestamp is not changed because there is no
        delay through the router.

        :param packet_event: PacketEvent to process
        :return: new Events to enqueue
        """

        # Data packet, forward to correct link
        if isinstance(event.packet, DataPacket) or \
                isinstance(event.packet, AckPacket):
            nextLink = self.getRoute(event.packet.dest)
            if nextLink:
                logger.log('Router %s forwards packet to %s' %
                           (self.address, nextLink.id))
                return nextLink.addPackets([event.packet], self)
            else:
                logger.log('Router %s dropped packet %s' %
                           (self.address, event.packet.index))

        # Received routing table information, update table
        elif isinstance(event.packet, RoutingPacket):
            neighborTable = event.packet.routingTable
            link = event.sender
            cost = link.cost()

            # overwrite previous
            self.link_table[link] = dict()
            for dest in neighborTable:
                # split horizon to avoid cycles
                if neighborTable[dest][0] != link:
                    self.link_table[link][dest] = neighborTable[dest][1] + cost

            # add dests to routing_table
            for dest in self.link_table[link]:
                if dest not in self.routing_table:
                    self.routing_table[dest] = (link, self.link_table[link][dest])

            # reset all and recalculate
            for dest in self.routing_table:
                self.routing_table[dest] = (None, 999999)
                for link in self.link_table:
                    if dest in self.link_table[link] and self.link_table[link][dest] < self.routing_table[dest][1]:
                        self.routing_table[dest] = (link, self.link_table[link][dest])

        # Received routing table request
        elif isinstance(event.packet, RoutingRequestPacket):
            # process request for routing table
            logger.log('Routing table packet for router %s' % self.address)
            return event.sender.addPackets(
                [RoutingPacket(self.address, event.packet.source,
                               routingTable=self.routing_table)], self)

        # Else we don't know what to do
        else:
            raise NotImplementedError(
                'Handling of %s not implemented' % event.packet.__class__)

        return []