def _process_queue(self): """ Runs a thread for processing the packets in the packet queue. """ while True: packet = self._packet_queue.get() if not packet: # Stop the network self._stop_thread = True break # Artificially delay the network if self.delay > 0: time.sleep(self.delay) # Simulate packet loss packet_drop_var = random.random() if packet_drop_var > (1 - self.packet_drop_rate): Logger.get_instance().log("PACKET DROPPED") if packet.payload_type == Constants.QUANTUM: packet.payload.release() continue sender, receiver = packet.sender, packet.receiver if packet.payload_type == Constants.QUANTUM: if not self._route_quantum_info(sender, receiver, [packet.payload]): continue try: if packet.protocol == Constants.RELAY and not self.use_hop_by_hop: full_route = packet.route route = full_route[full_route.index(sender):] else: if packet.protocol == Constants.REC_EPR: route = self.get_classical_route(sender, receiver) else: route = self.get_classical_route(sender, receiver) if len(route) < 2: raise Exception('No route exists') elif len(route) == 2: if packet.protocol != Constants.RELAY: if packet.protocol == Constants.REC_EPR: host_sender = self.get_host(sender) q = host_sender \ .backend \ .create_EPR(host_sender.host_id, receiver, q_id=packet.payload['q_id'], block=packet.payload['blocked']) host_sender.add_epr(receiver, q) self.ARP[receiver].rec_packet(packet) else: self.ARP[receiver].rec_packet(packet.payload) else: if packet.protocol == Constants.REC_EPR: q_id = packet.payload['q_id'] blocked = packet.payload['blocked'] q_route = self.get_quantum_route(sender, receiver) if self.use_ent_swap: DaemonThread(self._entanglement_swap, args=(sender, receiver, q_route, q_id, packet.seq_num, blocked)) else: DaemonThread(self._establish_epr, args=(sender, receiver, q_id, packet.seq_num, blocked)) else: network_packet = self._encode(route, packet) self.ARP[route[1]].rec_packet(network_packet) except nx.NodeNotFound: Logger.get_instance().error( "route couldn't be calculated, node doesn't exist") except ValueError: Logger.get_instance().error( "route couldn't be calculated, value error") except Exception as e: Logger.get_instance().error('Error in network: ' + str(e))
def _entanglement_swap(self, sender, receiver, route, q_id, o_seq_num, blocked): """ Performs a chain of entanglement swaps with the hosts between sender and receiver to create a shared EPR pair between sender and receiver. Args: sender (Host): Sender of the EPR pair receiver (Host): Receiver of the EPR pair route (list): Route between the sender and receiver q_id (str): Qubit ID of the sent EPR pair o_seq_num (int): The original sequence number blocked (bool): If the pair being distributed is blocked or not """ host_sender = self.get_host(sender) def establish_epr(net, s, r): if not net.shares_epr(s, r): self.get_host(s).send_epr(r, q_id, await_ack=True) else: old_id = self.get_host(s).change_epr_qubit_id(r, q_id) net.get_host(r).change_epr_qubit_id(route[i], q_id, old_id) # Create EPR pairs on the route, where all EPR qubits have the id q_id threads = [] for i in range(len(route) - 1): threads.append( DaemonThread(establish_epr, args=(self, route[i], route[i + 1]))) for t in threads: t.join() for i in range(len(route) - 2): host = self.get_host(route[i + 1]) q = host.get_epr(route[0], q_id, wait=10) if q is None: print("Host is %s" % host.host_id) print("Search host is %s" % route[0]) print("Search id is %s" % q_id) print("EPR storage is") print(host.EPR_store) Logger.get_instance().error('Entanglement swap failed') return data = { 'q': q, 'eq_id': q_id, 'node': sender, 'o_seq_num': o_seq_num, 'type': Constants.EPR } if route[i + 2] == route[-1]: data = { 'q': q, 'eq_id': q_id, 'node': sender, 'ack': True, 'o_seq_num': o_seq_num, 'type': Constants.EPR } host.send_teleport(route[i + 2], None, await_ack=True, payload=data, generate_epr_if_none=False) # Change in the storage that the EPR qubit is shared with the receiver q2 = host_sender.get_epr(route[1], q_id=q_id) host_sender.add_epr(receiver, q2, q_id, blocked) Logger.get_instance().log( 'Entanglement swap was successful for pair with id ' + q_id + ' between ' + sender + ' and ' + receiver)