def __init__(self, address, links=None): """ Constructor for Host :param address: unique address of this Node :param links: list of Links (objects) this Node is connected to """ super(self.__class__, self).__init__(address, links) self.flows = dict() self.flowrecipients = dict() self.stats = HostStats(address)
class Host(Node): """ Represents a host in a network This class represents a host in a network that is able to receive and send data""" def __init__(self, address, links=None): """ Constructor for Host :param address: unique address of this Node :param links: list of Links (objects) this Node is connected to """ super(self.__class__, self).__init__(address, links) self.flows = dict() self.flowrecipients = dict() self.stats = HostStats(address) def addLink(self, link): """ Overwrites default add link to check for single link """ if not self.links: self.links.append(link) else: print "Node " + str(self.address) + " already has a link!" # todo: raise some type of error instead def addFlow(self, flow): """ Add a Flow that this Host is sending. """ self.flows[flow.flowId] = flow def addFlowRecipient(self, flowrecipient): """ Add a Flow that this Host is receiving. """ self.flowrecipients[flowrecipient.flowId] = flowrecipient 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 _processOtherEvent(self, event): """ Processes non-packet events """ if isinstance(event, UpdateFlowEvent): return self._processUpdateFlowEvent(event) else: raise NotImplementedError( 'Handling of %s not implemented' % event.__class__) def _processUpdateFlowEvent(self, updateflowevent): """ Check up on the Flow, e.g. for timeouts :param updateflowevent: UpdateFlowEvent to process :return: new Events to enqueue """ f = self.flows[updateflowevent.flowId] t = updateflowevent.timestamp # Send packets newpackets, rto = f.checkTimeout(t) packetEvents = \ [PacketEvent(t, self, self.links[0], p, 'Flow %s, packet %s from host %s to link %s' % (f.flowId, p.index, self.address, self.links[0].id)) for p in newpackets] packetEvents.append( UpdateFlowEvent(t + rto, self, f.flowId, 'Check for timeout on flow %s' % f.flowId)) return packetEvents
class Host(Node): """ Represents a host in a network This class represents a host in a network that is able to receive and send data""" def __init__(self, address, links=None): """ Constructor for Host :param address: unique address of this Node :param links: list of Links (objects) this Node is connected to """ super(self.__class__, self).__init__(address, links) self.flows = dict() self.flowrecipients = dict() self.stats = HostStats(address) def addLink(self, link): """ Overwrites default add link to check for single link """ if not self.links: self.links.append(link) else: print "Node " + str(self.address) + " already has a link!" # todo: raise some type of error instead def addFlow(self, flow): """ Add a Flow that this Host is sending. """ self.flows[flow.flowId] = flow def addFlowRecipient(self, flowrecipient): """ Add a Flow that this Host is receiving. """ self.flowrecipients[flowrecipient.flowId] = flowrecipient 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 _processOtherEvent(self, event): """ Processes non-packet events """ if isinstance(event, UpdateFlowEvent): return self._processUpdateFlowEvent(event) else: raise NotImplementedError('Handling of %s not implemented' % event.__class__) def _processUpdateFlowEvent(self, updateflowevent): """ Check up on the Flow, e.g. for timeouts :param updateflowevent: UpdateFlowEvent to process :return: new Events to enqueue """ f = self.flows[updateflowevent.flowId] t = updateflowevent.timestamp # Send packets newpackets, rto = f.checkTimeout(t) packetEvents = \ [PacketEvent(t, self, self.links[0], p, 'Flow %s, packet %s from host %s to link %s' % (f.flowId, p.index, self.address, self.links[0].id)) for p in newpackets] packetEvents.append( UpdateFlowEvent(t + rto, self, f.flowId, 'Check for timeout on flow %s' % f.flowId)) return packetEvents