classPacket(object): """ A very simple class that represents a packet. This packet will run through a queue at a switch output port. We use a float to represent the size of the packet in bytes so that we can compare to ideal M/M/1 queues. Parameters ---------- time : float the time the packet arrives at the output queue. size : float the size of the packet in bytes id : int an identifier for the packet src, dst : int identifiers for source and destination flow_id : int small integer that can be used to identify a flow """ def__init__(self, time, size, id, src="a", dst="z", flow_id=0): self.time = time self.size = size self.id = id self.src = src self.dst = dst self.flow_id = flow_id
classPacketGenerator(object): """ Generates packets with given inter-arrival time distribution. Set the "out" member variable to the entity to receive the packet. Parameters ---------- env : simpy.Environment the simulation environment adist : function a no parameter function that returns the successive inter-arrival times of the packets sdist : function a no parameter function that returns the successive sizes of the packets initial_delay : number Starts generation after an initial delay. Default = 0 finish : number Stops generation at the finish time. Default is infinite """ def__init__(self, env, id, adist, sdist, initial_delay=0, finish=float("inf"), flow_id=0): self.id = id self.env = env self.adist = adist self.sdist = sdist self.initial_delay = initial_delay self.finish = finish self.out = None self.packets_sent = 0 self.action = env.process(self.run()) # starts the run() method as a SimPy process self.flow_id = flow_id
defrun(self): """The generator function used in simulations. """ yield self.env.timeout(self.initial_delay) while self.env.now < self.finish: # wait for next transmission yield self.env.timeout(self.adist()) self.packets_sent += 1 p = Packet(self.env.now, self.sdist(), self.packets_sent, src=self.id, flow_id=self.flow_id) self.out.put(p)
classPacketSink(object): """ Receives packets and collects delay information into the waits list. You can then use this list to look at delay statistics. Parameters ---------- env : simpy.Environment the simulation environment debug : boolean if true then the contents of each packet will be printed as it is received. rec_arrivals : boolean if true then arrivals will be recorded absolute_arrivals : boolean if true absolute arrival times will be recorded, otherwise the time between consecutive arrivals is recorded. rec_waits : boolean if true waiting time experienced by each packet is recorded selector: a function that takes a packet and returns a boolean used for selective statistics. Default none. """ def__init__(self, env, rec_arrivals=False, absolute_arrivals=False, rec_waits=True, debug=False, selector=None): self.store = simpy.Store(env) self.env = env self.rec_waits = rec_waits self.rec_arrivals = rec_arrivals self.absolute_arrivals = absolute_arrivals self.waits = [] self.arrivals = [] self.debug = debug self.packets_rec = 0 self.bytes_rec = 0 self.selector = selector self.last_arrival = 0.0
defput(self, pkt): ifnot self.selector or self.selector(pkt): now = self.env.now if self.rec_waits: self.waits.append(self.env.now - pkt.time) if self.rec_arrivals: if self.absolute_arrivals: self.arrivals.append(now) else: self.arrivals.append(now - self.last_arrival) self.last_arrival = now self.packets_rec += 1 self.bytes_rec += pkt.size if self.debug: print(pkt)
classSwitchPort(object): """ Models a switch output port with a given rate and buffer size limit in bytes. Set the "out" member variable to the entity to receive the packet. Parameters ---------- env : simpy.Environment the simulation environment rate : float the bit rate of the port qlimit : integer (or None) a buffer size limit in bytes or packets for the queue (including items in service). limit_bytes : If true, the queue limit will be based on bytes if false the queue limit will be based on packets. """ def__init__(self, env, rate, qlimit=None, limit_bytes=True, debug=False): self.store = simpy.Store(env) self.rate = rate self.env = env self.out = None self.packets_rec = 0 self.packets_drop = 0 self.qlimit = qlimit self.limit_bytes = limit_bytes self.byte_size = 0# Current size of the queue in bytes self.debug = debug self.busy = 0# Used to track if a packet is currently being sent self.action = env.process(self.run()) # starts the run() method as a SimPy process
classPortMonitor(object): """ A monitor for an SwitchPort. Looks at the number of items in the SwitchPort in service + in the queue and records that info in the sizes[] list. The monitor looks at the port at time intervals given by the distribution dist. Parameters ---------- env : simpy.Environment the simulation environment port : SwitchPort the switch port object to be monitored. dist : function a no parameter function that returns the successive inter-arrival times of the packets """ def__init__(self, env, port, dist, count_bytes=False): self.port = port self.env = env self.dist = dist self.count_bytes = count_bytes self.sizes = [] self.action = env.process(self.run())
defrun(self): whileTrue: yield self.env.timeout(self.dist()) if self.count_bytes: total = self.port.byte_size else: total = len(self.port.store.items) + self.port.busy self.sizes.append(total)