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
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 []
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
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
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
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)
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)
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
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 []
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 []
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 []