Esempio n. 1
0
    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))
Esempio n. 2
0
    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)