示例#1
0
class Link(Reporter):

    left_node = ""
    right_node = ""

    capacity_kbit_per_ms = -1
    kbits_in_each_buffer = -1
    ms_prop_delay = -1

    left_buff = []
    right_buff = []
    sim = ""

    packet_loading = False
    packets_in_flight = 0
    transmission_direction = ""  # left-to-right, right-to-left
    switch_direction_flag = False

    bidirectional_queueing_delay_memory = [-1
                                           ] * constants.QUEUEING_DELAY_WINDOW

    def ms_tx_delay(self, packet):
        return (packet.get_kbits() / self.capacity_kbit_per_ms)  # ms

    def ms_total_delay(self, packet):
        return self.ms_tx_delay(packet) + self.ms_prop_delay  # ms

    # Call Node initialization code, with the Node ID (required unique)
    # Initializes itself
    # Inputs: rate (Mbps), Delay (ms), size (KB)
    # We need to standardize units to kbit/ms, kbits, and ms
    def __init__(self, identity, left, right, rate, delay, size):
        Reporter.__init__(self, identity)
        self.left_node = left
        self.right_node = right

        # Need to standardize units to kbit/ms, kbits, and ms
        self.capacity_kbit_per_ms = float(
            rate)  # 1000 Kilobits in a Megabit, 1000 ms in a s
        self.ms_prop_delay = float(delay)  # Already standardized
        self.kbits_in_each_buffer = 8.0 * float(
            size
        )  # 8 = conversion from BYTE to BIT, ignore 1024 vs 1000 convention

        self.left_buff = LinkBuffer(self.kbits_in_each_buffer)
        self.right_buff = LinkBuffer(self.kbits_in_each_buffer)

        self.bidirectional_queueing_delay_memory = [
            -1
        ] * constants.QUEUEING_DELAY_WINDOW

    def set_event_simulator(self, sim):
        self.sim = sim
        self.left_buff.set_event_simulator(sim)
        self.left_buff.set_my_link(self)
        self.left_buff.set_my_direction(constants.LTR)
        self.right_buff.set_event_simulator(sim)
        self.right_buff.set_my_link(self)
        self.right_buff.set_my_direction(constants.RTL)

    def get_left(self):
        return self.left_node

    def get_right(self):
        return self.right_node

    def get_rate(self):
        return self.capacity_kbit_per_ms

    def get_delay(self):
        return self.ms_prop_delay

    def get_buff(self):
        return self.kbits_in_each_buffer

    # return time average of queueing delay buffer
    def get_occupancy(self):
        '''
		for v in self.bidirectional_queueing_delay_memory:
			sys.stderr.write("QD: %0.3e\n"%v)
		'''
        return self.average_delay_buffer()

    def average_delay_buffer(self):
        delay = 0.0
        cnt = 0.0
        for v in self.bidirectional_queueing_delay_memory:
            if v >= 0:
                delay += v
                cnt += 1.0
        delay /= cnt
        return delay

    # reset packet loading, decide how to transfer_next_packet
    def packet_transmitted(self, packet):
        self.packet_loading = False
        self.sim.request_event(\
         Handle_Packet_Propagation(packet, self.get_id(),\
         self.sim.get_current_time() + self.ms_prop_delay))
        self.packets_in_flight += 1
        self.transfer_next_packet()

    # decrement packets in flight counter, decide how to transfer_next_packet
    def packet_propagated(self):
        self.packets_in_flight -= 1
        self.transfer_next_packet()

    # load packet-to-send to the appropriate buffer, then decide how to
    # transfer it
    def send(self, packet, sender_id):
        notDroppedFlag = True
        if sender_id == self.left_node:
            notDroppedFlag = self.left_buff.enqueue(packet)
            self.transfer_next_packet()
        elif sender_id == self.right_node:
            notDroppedFlag = self.right_buff.enqueue(packet)
            self.transfer_next_packet()
        else:
            raise ValueError('Packet received by Link %s \
				from unknown Node %s' % (self.ID, sender_id))

        if (not notDroppedFlag):
            print "\nDEBUG: (in link) packets dropped : %s, packet %d\n" % (
                self.get_id(), packet.get_ID())
            if constants.MEASUREMENT_ENABLE:
                print constants.MEASURE_PACKET_LOSS((packet.get_flow(),\
                       packet.get_type(),\
                       packet.get_ID(),\
                       self.sim.get_current_time()))

    def transfer_next_packet(self):
        if (not self.packet_loading) and (self.packets_in_flight == 0):

            lt = self.left_buff.get_head_timestamp() \
               if self.left_buff.can_dequeue() else -1
            rt = self.right_buff.get_head_timestamp() \
               if self.right_buff.can_dequeue() else -1

            if (lt >= 0) or (rt >= 0):
                if (lt >= 0) and (rt >= 0):
                    if self.switch_direction_flag:
                        # there are packets on both sides,
                        # and it's time to switch link direction
                        self.switch_direction_flag = False
                        if (self.transmission_direction == constants.LTR):
                            self.transmission_direction = constants.RTL
                            packet_to_transmit, queue_delay = self.right_buff.dequeue(
                            )
                            packet_to_transmit.set_curr_dest(self.get_left())
                        else:
                            self.transmission_direction = constants.LTR
                            packet_to_transmit, queue_delay = self.left_buff.dequeue(
                            )
                            packet_to_transmit.set_curr_dest(self.get_right())
                    elif (lt < rt):
                        # Start loading Packet from head of left buffer into channel
                        self.transmission_direction = constants.LTR
                        packet_to_transmit, queue_delay = self.left_buff.dequeue(
                        )
                        packet_to_transmit.set_curr_dest(self.get_right())
                    else:
                        # Start loading Packet from head of right buffer into channel
                        self.transmission_direction = constants.RTL
                        packet_to_transmit, queue_delay = self.right_buff.dequeue(
                        )
                        packet_to_transmit.set_curr_dest(self.get_left())
                elif (lt >= 0):
                    # Start loading Packet from head of left buffer into channel
                    self.transmission_direction = constants.LTR
                    packet_to_transmit, queue_delay = self.left_buff.dequeue()
                    packet_to_transmit.set_curr_dest(self.get_right())
                else:
                    # Start loading Packet from head of right buffer into channel
                    self.transmission_direction = constants.RTL
                    packet_to_transmit, queue_delay = self.right_buff.dequeue()
                    packet_to_transmit.set_curr_dest(self.get_left())

                self.packet_loading = True
                completion_time = \
                 self.sim.get_current_time() + self.ms_tx_delay(packet_to_transmit)

                self.sim.request_event(\
                 Handle_Packet_Transmission( packet_to_transmit,\
                        self.get_id(),\
                         completion_time))

                self.bidirectional_queueing_delay_memory.pop(0)
                self.bidirectional_queueing_delay_memory.append(queue_delay)
            else:
                pass

        elif (not self.packet_loading) and (self.packets_in_flight > 0):
            lt = self.left_buff.get_head_timestamp() \
             if self.left_buff.can_dequeue() else -1
            rt = self.right_buff.get_head_timestamp() \
             if self.right_buff.can_dequeue() else -1
            self.attempt_to_transmit_in_same_direction(lt, rt)

        else:
            pass

    # lt, rt are left and right heads-of-buffer timestamps
    def attempt_to_transmit_in_same_direction(self, lt, rt):
        # if there are any more to send in the current direction,
        # can they get there before the timestamp of the head of the
        # other buffer?
        if self.transmission_direction == constants.RTL:
            buff = self.right_buff
            curr_dest = self.get_left()
            t1 = lt
            t2 = rt
        else:
            buff = self.left_buff
            curr_dest = self.get_right()
            t1 = rt
            t2 = lt

        if t2 >= 0:
            proposed_receive_time = self.sim.get_current_time() + \
             self.ms_total_delay(buff.see_head_packet())
            if ((t1 >= 0) and (proposed_receive_time < t1)) or (t1 < 0):
                packet_to_transmit, queue_delay = buff.dequeue()
                packet_to_transmit.set_curr_dest(curr_dest)
                self.packet_loading = True
                completion_time = self.sim.get_current_time() + \
                 self.ms_tx_delay(packet_to_transmit)
                self.sim.request_event(\
                 Handle_Packet_Transmission( packet_to_transmit,\
                       self.get_id(),\
                        completion_time))

                self.bidirectional_queueing_delay_memory.pop(0)
                self.bidirectional_queueing_delay_memory.append(queue_delay)

            else:
                self.switch_direction_flag = True
示例#2
0
class Link(Reporter):

	left_node = ""
	right_node = ""
	
	capacity_kbit_per_ms = -1 
	kbits_in_each_buffer = -1 	
	ms_prop_delay = -1
	
	left_buff = []
	right_buff = []
	sim = ""

	packet_loading = False
	packets_in_flight = 0
	transmission_direction = "" # left-to-right, right-to-left
	switch_direction_flag = False

	bidirectional_queueing_delay_memory = [-1] * constants.QUEUEING_DELAY_WINDOW

	def ms_tx_delay (self, packet): 
		return (packet.get_kbits() / self.capacity_kbit_per_ms) # ms

	def ms_total_delay (self, packet): 
		return self.ms_tx_delay(packet) + self.ms_prop_delay # ms
	
	# Call Node initialization code, with the Node ID (required unique)
	# Initializes itself
	# Inputs: rate (Mbps), Delay (ms), size (KB)
	# We need to standardize units to kbit/ms, kbits, and ms
	def __init__(self, identity, left, right, rate, delay, size):
		Reporter.__init__(self, identity)				
		self.left_node = left
		self.right_node = right

		# Need to standardize units to kbit/ms, kbits, and ms		
		self.capacity_kbit_per_ms = float(rate)				# 1000 Kilobits in a Megabit, 1000 ms in a s
		self.ms_prop_delay = float(delay)					# Already standardized
		self.kbits_in_each_buffer = 8.0 * float(size) 		# 8 = conversion from BYTE to BIT, ignore 1024 vs 1000 convention

		self.left_buff = LinkBuffer(self.kbits_in_each_buffer)
		self.right_buff = LinkBuffer(self.kbits_in_each_buffer)

		self.bidirectional_queueing_delay_memory = [-1] * constants.QUEUEING_DELAY_WINDOW

	def set_event_simulator (self, sim):
		self.sim = sim
		self.left_buff.set_event_simulator(sim)
		self.left_buff.set_my_link(self)
		self.left_buff.set_my_direction(constants.LTR)
		self.right_buff.set_event_simulator(sim)
		self.right_buff.set_my_link(self)
		self.right_buff.set_my_direction(constants.RTL)

	def get_left(self):
		return self.left_node

	def get_right(self):
		return self.right_node

	def get_rate(self):
		return self.capacity_kbit_per_ms

	def get_delay(self):
		return self.ms_prop_delay

	def get_buff(self):
		return self.kbits_in_each_buffer

	# return time average of queueing delay buffer
	def get_occupancy(self):		
		'''
		for v in self.bidirectional_queueing_delay_memory:
			sys.stderr.write("QD: %0.3e\n"%v)
		'''
		return self.average_delay_buffer()

	def average_delay_buffer(self):
		delay = 0.0
		cnt = 0.0
		for v in self.bidirectional_queueing_delay_memory:
			if v >= 0:
				delay += v
				cnt += 1.0
		delay /= cnt
		return delay

	# reset packet loading, decide how to transfer_next_packet
	def packet_transmitted (self, packet):
		self.packet_loading = False		
		self.sim.request_event(\
			Handle_Packet_Propagation(packet, self.get_id(),\
			self.sim.get_current_time() + self.ms_prop_delay))
		self.packets_in_flight += 1
		self.transfer_next_packet()

	# decrement packets in flight counter, decide how to transfer_next_packet
	def packet_propagated (self):
		self.packets_in_flight -= 1
		self.transfer_next_packet()

	# load packet-to-send to the appropriate buffer, then decide how to 
	# transfer it
	def send (self, packet, sender_id):				
		notDroppedFlag = True
		if sender_id == self.left_node:			
			notDroppedFlag = self.left_buff.enqueue(packet)
			self.transfer_next_packet()
		elif sender_id == self.right_node:
			notDroppedFlag = self.right_buff.enqueue(packet)
			self.transfer_next_packet()
		else:
			raise ValueError ('Packet received by Link %s \
				from unknown Node %s' % (self.ID, sender_id) )
		
		if (not notDroppedFlag):	
			print "\nDEBUG: (in link) packets dropped : %s, packet %d\n" % (self.get_id(), packet.get_ID())
			if constants.MEASUREMENT_ENABLE: 
				print constants.MEASURE_PACKET_LOSS((packet.get_flow(),\
											packet.get_type(),\
											packet.get_ID(),\
											self.sim.get_current_time()))

	def transfer_next_packet (self):
		if (not self.packet_loading) and (self.packets_in_flight == 0):
			
			lt = self.left_buff.get_head_timestamp() \
						if self.left_buff.can_dequeue() else -1
			rt = self.right_buff.get_head_timestamp() \
						if self.right_buff.can_dequeue() else -1			
			
			if (lt >= 0) or (rt >= 0):				
				if (lt >= 0) and (rt >= 0):
					if self.switch_direction_flag:
						# there are packets on both sides,
						# and it's time to switch link direction
						self.switch_direction_flag = False
						if (self.transmission_direction == constants.LTR):
							self.transmission_direction = constants.RTL
							packet_to_transmit, queue_delay = self.right_buff.dequeue()
							packet_to_transmit.set_curr_dest(self.get_left())
						else:
							self.transmission_direction = constants.LTR
							packet_to_transmit, queue_delay = self.left_buff.dequeue()
							packet_to_transmit.set_curr_dest(self.get_right())
					elif (lt < rt):
						# Start loading Packet from head of left buffer into channel
						self.transmission_direction = constants.LTR
						packet_to_transmit, queue_delay = self.left_buff.dequeue()
						packet_to_transmit.set_curr_dest(self.get_right())
					else:
						# Start loading Packet from head of right buffer into channel
						self.transmission_direction = constants.RTL
						packet_to_transmit, queue_delay = self.right_buff.dequeue()
						packet_to_transmit.set_curr_dest(self.get_left())
				elif (lt >= 0):
					# Start loading Packet from head of left buffer into channel				
					self.transmission_direction = constants.LTR
					packet_to_transmit, queue_delay = self.left_buff.dequeue()
					packet_to_transmit.set_curr_dest(self.get_right())
				else:
					# Start loading Packet from head of right buffer into channel					
					self.transmission_direction = constants.RTL
					packet_to_transmit, queue_delay = self.right_buff.dequeue()
					packet_to_transmit.set_curr_dest(self.get_left())

				self.packet_loading = True
				completion_time = \
					self.sim.get_current_time() + self.ms_tx_delay(packet_to_transmit)
				
				self.sim.request_event(\
					Handle_Packet_Transmission(	packet_to_transmit,\
												self.get_id(),\
					 							completion_time))

				self.bidirectional_queueing_delay_memory.pop(0)
				self.bidirectional_queueing_delay_memory.append(queue_delay)
			else:
				pass

		elif (not self.packet_loading) and (self.packets_in_flight > 0):
			lt = self.left_buff.get_head_timestamp() \
				if self.left_buff.can_dequeue() else -1			
			rt = self.right_buff.get_head_timestamp() \
				if self.right_buff.can_dequeue() else -1
			self.attempt_to_transmit_in_same_direction (lt, rt)

		else:
			pass

	# lt, rt are left and right heads-of-buffer timestamps
	def attempt_to_transmit_in_same_direction (self, lt, rt):		
		# if there are any more to send in the current direction,
		# can they get there before the timestamp of the head of the
		# other buffer?
		if self.transmission_direction == constants.RTL:
			buff = self.right_buff
			curr_dest = self.get_left()
			t1 = lt
			t2 = rt
		else:
			buff = self.left_buff
			curr_dest = self.get_right()
			t1 = rt
			t2 = lt

		if t2 >= 0:	
			proposed_receive_time = self.sim.get_current_time() + \
				self.ms_total_delay(buff.see_head_packet())
			if ((t1 >= 0) and (proposed_receive_time < t1)) or (t1 < 0):	
				packet_to_transmit, queue_delay = buff.dequeue()
				packet_to_transmit.set_curr_dest(curr_dest)
				self.packet_loading = True
				completion_time = self.sim.get_current_time() + \
					self.ms_tx_delay(packet_to_transmit)
				self.sim.request_event(\
					Handle_Packet_Transmission(	packet_to_transmit,\
											self.get_id(),\
				 							completion_time))

				self.bidirectional_queueing_delay_memory.pop(0)
				self.bidirectional_queueing_delay_memory.append(queue_delay)

			else:
				self.switch_direction_flag = True