Ejemplo n.º 1
0
    def test_handle_nack_on_await_data(self):
        """Test handle nack on the name of awaiting data"""
        computation_name = Name("/func/f1")
        computation_name += "_(/test/data,/data/test)"
        computation_name += "NFN"
        computation_interest = Interest(computation_name)

        computation_entry = NFNComputationTableEntry(computation_name)
        computation_str, prepended = self.nfn_layer.parser.network_name_to_nfn_str(
            computation_name)
        computation_entry.ast = self.nfn_layer.parser.parse(computation_str)
        computation_entry.interest = computation_interest
        self.nfn_layer.computation_table.append_computation(computation_entry)
        self.assertEqual(self.nfn_layer.computation_table.get_container_size(),
                         1)

        self.nfn_layer.computation_table.add_awaiting_data(
            computation_name, Name("/test/data"))
        self.assertEqual(
            len(
                self.nfn_layer.computation_table.get_computation(
                    computation_name).awaiting_data), 1)

        self.nfn_layer.handleNack(
            1,
            Nack(Name("/test/data"),
                 NackReason.NO_CONTENT,
                 interest=Interest(Name("/test/data"))))
        res = self.nfn_layer.queue_to_lower.get(timeout=2.0)
        self.assertEqual(
            res[1],
            Nack(computation_name,
                 NackReason.NO_CONTENT,
                 interest=computation_interest))
        self.assertEqual(self.nfn_layer.computation_table.get_container(), [])
Ejemplo n.º 2
0
    def test_handle_nack_on_computation_name(self):
        """Test handle nack on the name of the original computation"""
        computation_name = Name("/func/f1")
        computation_name += "_(/test/data,/data/test)"
        computation_name += "NFN"
        computation_interest = Interest(computation_name)

        computation_entry = NFNComputationTableEntry(computation_name)
        computation_str, prepended = self.nfn_layer.parser.network_name_to_nfn_str(
            computation_name)
        computation_entry.ast = self.nfn_layer.parser.parse(computation_str)
        computation_entry.interest = computation_interest
        self.nfn_layer.computation_table.append_computation(computation_entry)
        self.assertEqual(self.nfn_layer.computation_table.get_container_size(),
                         1)
        self.nfn_layer.handleNack(
            1,
            Nack(computation_name,
                 NackReason.COMP_PARAM_UNAVAILABLE,
                 interest=computation_interest))
        res = self.nfn_layer.queue_to_lower.get(timeout=2.0)
        self.assertEqual(
            res[1],
            Nack(computation_name,
                 NackReason.COMP_PARAM_UNAVAILABLE,
                 interest=computation_interest))
        self.assertEqual(self.nfn_layer.computation_table.get_container(), [])
Ejemplo n.º 3
0
    def compute(self, interest: Interest):
        """Compute a result, when all data are available
        :param interest: The original interest message to be handled (can be taken from computation table)
        """
        self.logger.info("Start computation: " + str(interest.name))
        params = []
        entry = self.computation_table.get_computation(interest.name)
        if entry is None:
            return
        self.computation_table.remove_computation(interest.name)
        if entry.comp_state == NFNComputationState.WRITEBACK:
            name = self.parser.nfn_str_to_network_name(entry.rewrite_list[0])
            res = entry.available_data[name]
            data = Content(entry.original_name, res)
            #self.queue_to_lower.put([entry.id, data])
            self.handleContent(entry.id, data)
            return
        function_name = Name(entry.ast._element)
        function_code = entry.available_data.get(function_name)
        if function_code is None:
            self.queue_to_lower.put([entry.id, Nack(entry.original_name, NackReason.COMP_PARAM_UNAVAILABLE,
                                                    interest=entry.interest)])
            return
        executor: BaseNFNExecutor = self.executors.get(self.get_nf_code_language(function_code))
        if executor is None:
            self.queue_to_lower.put([entry.id,
                                     Nack(entry.original_name, NackReason.COMP_EXCEPTION, interest=entry.interest)])
        for e in entry.ast.params:
            if isinstance(e, AST_Name):
                param = entry.available_data.get(Name(e._element))
                if param is None:
                    self.queue_to_lower.put([entry.id, Nack(entry.original_name, NackReason.COMP_PARAM_UNAVAILABLE,
                                                            interest=entry.interest)])
                    return
                params.append(param)
            elif isinstance(e, AST_FuncCall):
                search_name = Name()
                search_name += str(e)
                search_name += "NFN"
                params.append(entry.available_data[search_name])
            elif not isinstance(e.type, AST):
                params.append(e.type(e._element))

        res = executor.execute(function_code=function_code, params=params)
        if res is None:
            self.queue_to_lower.put([entry.id,
                                     Nack(entry.original_name, NackReason.COMP_EXCEPTION, interest=entry.interest)])
        content_res: Content = Content(entry.original_name, str(res)) #TODO typed results
        self.logger.info("Finish Computation: " + str(content_res.name))
        #self.computation_table.push_data(content_res)
        #self.queue_to_lower.put([entry.id, content_res])
        self.handleContent(entry.id, content_res)
Ejemplo n.º 4
0
 def data_from_lower(self, to_lower: multiprocessing.Queue, to_higher: multiprocessing.Queue, data):
     packet_id = data[0]
     packet = data[1]
     if 'THUNK' in str(packet.name):
         self.queue_to_higher.put(data)
         return
     if isinstance(packet, Interest):
         self.logger.info("Reveived Interest from lower... " + str(packet.name))
         if len(packet.name.components) > 2 and packet.name.string_components[-2] == 'KEEPALIVE':
             self.logger.info("Interest is keep alive")
             if self.computation_table is None:
                 return
             nfn_name = self.remove_keep_alive_from_name(packet.name)
             self.logger.info("NFN name is: " + str(nfn_name))
             self.logger.info("#Running Computations: " + str(self.computation_table.is_comp_running(nfn_name)))
             comp = self.computation_table.get_computation(nfn_name)
             if comp is not None or self.computation_table.is_comp_running(nfn_name) or nfn_name in self.running_computations:
                 to_lower.put([packet_id, Content(packet.name)])
             else:
                 to_lower.put([packet_id, Nack(packet.name, NackReason.COMP_NOT_RUNNING, interest=packet)]) #todo is it working with a nack?
             return
         elif len(packet.name.components) > 0 and packet.name.components[-1] == b'NFN':
             self.running_computations.append(packet.name)
             to_higher.put(data)
         else:
             to_higher.put(data)
     elif (isinstance(packet, Content) or isinstance(packet, Nack)) and len(packet.name.components) > 2 and packet.name.string_components[-2] == 'KEEPALIVE':
         if isinstance(packet, Content):
             self.logger.info("Received KEEP ALIVE reply, updating timestamps")
             entry = self.message_dict.get_entry(packet.name)
             if entry:
                 self.logger.info("Old Timestamp was: " + str(entry.timestamp))
                 self.message_dict.update_timestamp(packet.name) #update timestamp for the R2C message
                 self.logger.info("Timestamp is now: " + str(self.message_dict.get_entry(packet.name).timestamp))
             return
         if isinstance(packet, Nack):
             original_name = self.remove_keep_alive_from_name(packet.name)
             self.message_dict.remove_entry(packet.name)
             self.message_dict.remove_entry(original_name)
             self.queue_to_higher.put([packet_id, Nack(original_name, reason=NackReason.COMP_NOT_RUNNING,
                                                       interest=Interest(original_name))])
     elif isinstance(packet, Content) or isinstance(packet, Nack): #R2C Content or Nack, remove entry and give to higher layer
         entry = self.message_dict.get_entry(packet.name)
         if entry is not None:
             self.logger.info("Removing entry from Keep Alive Dict")
             self.message_dict.remove_entry(packet.name)
             keepalive_name = self.add_keep_alive_from_name(packet.name)
             self.message_dict.remove_entry(keepalive_name)
         to_higher.put(data) #TODO R2C nack not handled correctly?
Ejemplo n.º 5
0
    def handle_interest_from_lower(self, face_id: int, interest: Interest, to_lower: multiprocessing.Queue):
        self.logger.info("Incoming interest: " + interest.name.to_string())
        # incoming interest is nfn expression
        if interest.name.string_components[-1] == "NFN":
            try:
                parser = DefaultNFNParser()
                nfn_str, prepended_name = parser.network_name_to_nfn_str(interest.name)
                ast = parser.parse(nfn_str)
                # assert that valid publish expression
                if is_publish_expression(ast):
                    # store to database
                    data_name = ast.params[0]._element
                    payload = ast.params[1]._element
                    try:
                        payload = base64.b64decode(payload[7:])
                        self.logger.info("Payload is base64 encoded. Decoded.")
                    except:
                        self.logger.info("Invalid publish expression. The payload could not be decoded.")
                        nack = Nack(interest.name, reason=NackReason.COMP_NOT_PARSED, interest=interest)
                        self.queue_to_lower.put([face_id, nack])

                    self.cs.add_content_object(Content(data_name, payload))
                    self.logger.info("Add to database: " + data_name)
                    # reply confirmation
                    confirmation = Content(interest.name, "ok")
                    to_lower.put([face_id, confirmation])

                else:
                    self.logger.info("Invalid publish expression. Wrong format.")
                    nack = Nack(interest.name, reason=NackReason.COMP_NOT_PARSED, interest=interest)
                    self.queue_to_lower.put([face_id, nack])

            except:
                self.logger.info("Invalid publish expression.")
                nack = Nack(interest.name, reason=NackReason.COMP_NOT_PARSED, interest=interest)
                self.queue_to_lower.put([face_id, nack])

        # incoming interest is data request
        else:
            db_entry = self.cs.find_content_object(interest.name)
            if db_entry is not None:
                self.logger.info("Found in database")
                to_lower.put([face_id, db_entry.content])
                return
            else:
                self.logger.info("Not found in database")
                nack = Nack(interest.name, NackReason.NO_CONTENT, interest)
                to_lower.put([face_id, nack])
                return
Ejemplo n.º 6
0
    def test_handle_nack_on_rewritten_computation_further_rewrite(self):
        """Test if a Nack message is handled correctly for a rewritten computation, when there is a further rewrite"""
        self.nfn_layer.fib.add_fib_entry(Name('/test'), 1, True)
        self.nfn_layer.fib.add_fib_entry(Name('/data'), 1, True)

        computation_name = Name("/func/f1")
        computation_name += "_(/test/data,/data/test)"
        computation_name += "NFN"
        computation_interest = Interest(computation_name)

        computation_entry = NFNComputationTableEntry(computation_name)
        computation_str, prepended = self.nfn_layer.parser.network_name_to_nfn_str(
            computation_name)
        computation_entry.ast = self.nfn_layer.parser.parse(computation_str)
        computation_entry.interest = computation_interest
        self.nfn_layer.computation_table.append_computation(computation_entry)

        nack_name = Name("/test/data")
        nack_name += "/func/f1(_,/data/test)"
        nack_name += "NFN"

        self.nfn_layer.forwarding_descision(computation_interest)
        res = self.nfn_layer.queue_to_lower.get(timeout=2.0)
        self.assertEqual(res[1], Interest(nack_name))
        self.assertEqual(
            self.nfn_layer.computation_table.get_computation(
                computation_name).comp_state, NFNComputationState.REWRITE)
        self.assertEqual(
            len(
                self.nfn_layer.computation_table.get_computation(
                    computation_name).rewrite_list), 2)
        self.assertEqual(
            self.nfn_layer.computation_table.get_computation(
                computation_name).rewrite_list, [
                    "/func/f1(%/test/data%,/data/test)",
                    "/func/f1(/test/data,%/data/test%)"
                ])

        self.nfn_layer.handleNack(
            res[1],
            Nack(nack_name,
                 NackReason.COMP_PARAM_UNAVAILABLE,
                 interest=Interest(nack_name)))

        second_request_name = Name("/data/test")
        second_request_name += "/func/f1(/test/data,_)"
        second_request_name += "NFN"

        res = self.nfn_layer.queue_to_lower.get(timeout=2.0)
        self.assertEqual(res[1], Interest(second_request_name))
        self.assertEqual(self.nfn_layer.computation_table.get_container_size(),
                         1)
        self.assertEqual(
            len(
                self.nfn_layer.computation_table.get_computation(
                    computation_name).rewrite_list), 1)
        self.assertEqual(
            self.nfn_layer.computation_table.get_computation(
                computation_name).rewrite_list,
            ["/func/f1(/test/data,%/data/test%)"])
Ejemplo n.º 7
0
    def _send_forwarder_solicitation(self, retry: int):

        autoconf: Interest = Interest(_AUTOCONFIG_FORWARDERS_PREFIX)

        for i in self._bc_interfaces:
            interface = self._linklayer.interfaces[i]
            if not isinstance(interface, UDP4Interface):
                # Autoconfig currently only supported for UDP over IPv4
                continue
            interface: UDP4Interface = interface
            bcaddr: str = interface.get_broadcast_address()
            if bcaddr is not None:
                addr_info = AddressInfo((bcaddr, self._bc_port), i)
                autoconf_fid = self._linklayer.faceidtable.get_or_create_faceid(
                    addr_info)
                self.queue_to_lower.put([autoconf_fid, autoconf])

        # Schedule re-broadcast of the forwarder solicitation interest, which will recursively call this function.
        if self._solicitation_timeout is not None and retry > 1:
            self._solicitation_timer = threading.Timer(
                self._solicitation_timeout,
                self._send_forwarder_solicitation,
                kwargs={'retry': retry - 1})
            self._solicitation_timer.start()
        elif retry <= 1:
            # If all forwarder solicitations timed out, send a Nack packet upwards for each held interest.
            for interest in self._held_interests:
                nack = Nack(interest.name, NackReason.NO_ROUTE, interest)
                self.queue_to_higher.put([None, nack])
            self._held_interests = []
Ejemplo n.º 8
0
 def test_Encoder_encode_decode_nack(self):
     """Test the nack decoding of Encoder"""
     interest = Interest("/data/test")
     n = Nack("/data/test", NackReason.NO_CONTENT, interest=interest)
     en = self.encoder1.encode(n)
     dn = self.encoder1.decode(en)
     self.assertTrue(n == dn)
Ejemplo n.º 9
0
    def get_chunks_available(self, packet: Packet):
        """
        Check if chunks are available for a given name.
        Return a content object containing the names of the available chunks, or NACK
        """
        chunks_available = []
        name = self.unpack(packet.name)
        request_entry = self.get_request_entry(name)
        cs_entry = self.cs.find_content_object(name)

        if request_entry is not None:
            chunks_available = [
                str(chunk.name) for chunk in request_entry.chunks
            ]

        elif cs_entry:
            chunks_available.append("complete;")

        if chunks_available:
            chunks_available = Content(packet.name, ";".join(chunks_available))
            if len(chunks_available.content) > self.chunk_size:
                meta_data, chunks = self.chunkifyer.chunk_data(
                    chunks_available)
                meta_data.extend(chunks)
                for data in meta_data:
                    self.cs.remove_content_object(data.name)
                    self.cs.add_content_object(data)
                return meta_data[0]
            else:
                return chunks_available

        return Nack(packet.name, NackReason.NO_CONTENT, packet)
Ejemplo n.º 10
0
 def return_nack(self, packet_id, interest: Interest):
     self.queue_to_lower.put([
         packet_id,
         Nack(interest.name,
              reason=NackReason.COMP_NOT_RUNNING,
              interest=interest)
     ])  # TODO -- choose an appropriate NACK reason
Ejemplo n.º 11
0
    def test_keep_alive_ageing_no_reply(self):
        """test ageing with keepalive with no keep alive reply"""
        self.timeoutPreventionLayer.ageing()

        interest = Interest("/test/func/_()/NFN")
        keepalive = Interest("/test/func/_()/KEEPALIVE/NFN")
        self.timeoutPreventionLayer.queue_from_higher.put([1, interest])

        res1 = self.timeoutPreventionLayer.queue_to_lower.get(timeout=2.0)
        self.assertEqual(res1, [1, interest])
        e1 = self.timeoutPreventionLayer.message_dict.get_entry(interest.name)
        self.assertTrue(e1 is not None)
        e2 = self.timeoutPreventionLayer.message_dict.get_entry(keepalive.name)
        self.assertTrue(e2 is not None)

        res2 = self.timeoutPreventionLayer.queue_to_lower.get(timeout=2.0)
        self.assertEqual(res2, [1, interest])

        res3 = self.timeoutPreventionLayer.queue_to_lower.get(timeout=2.0)
        self.assertEqual(res3, [1, keepalive])

        res4 = self.timeoutPreventionLayer.queue_to_lower.get(timeout=2.0)
        self.assertEqual(res4, [1, interest])

        res5 = self.timeoutPreventionLayer.queue_to_lower.get(timeout=2.0)
        self.assertEqual(res5, [1, keepalive])

        self.assertTrue(self.timeoutPreventionLayer.queue_to_lower.empty())

        res7 = self.timeoutPreventionLayer.queue_to_higher.get(timeout=2.0)
        self.assertEqual(res7, [1, Nack(name=interest.name, reason=NackReason.COMP_NOT_RUNNING, interest=interest)])
Ejemplo n.º 12
0
    def test_multicast_and_nack_handling_with_retransmit(self):
        """Test if a multicast works, and if the nack counter for the multicast works"""

        i1 = Interest("/test/data")
        n1 = Nack(i1.name, NackReason.NO_CONTENT, i1)

        self.icn_layer.start_process()

        self.icn_layer.fib.add_fib_entry(i1.name, [2, 3])

        self.icn_layer.queue_from_lower.put([1, i1])

        d1 = self.icn_layer.queue_to_lower.get(timeout=2.0)
        d2 = self.icn_layer.queue_to_lower.get(timeout=2.0)

        self.assertEqual([2, i1], d1)
        self.assertEqual([3, i1], d2)

        self.icn_layer.queue_from_lower.put([3, n1])
        self.assertTrue(self.icn_layer.queue_to_lower.empty())

        self.icn_layer.ageing()
        d3 = self.icn_layer.queue_to_lower.get(timeout=2.0)
        self.assertEqual([2, i1], d3)

        self.icn_layer.queue_from_lower.put([2, n1])
        d4 = self.icn_layer.queue_to_lower.get(timeout=2.0)
        self.assertEqual([1, n1], d4)
Ejemplo n.º 13
0
 def handle_interest_from_higher(self, face_id: int, interest: Interest,
                                 to_lower: multiprocessing.Queue,
                                 to_higher: multiprocessing.Queue):
     self.logger.info("Handling Interest (from higher): " +
                      str(interest.name) + "; Face ID: " + str(face_id))
     cs_entry = self.cs.find_content_object(interest.name)
     if cs_entry is not None:
         self.queue_to_higher.put([face_id, cs_entry.content])
         return
     pit_entry = self.pit.find_pit_entry(interest.name)
     self.pit.add_pit_entry(interest.name,
                            face_id,
                            interest,
                            local_app=True)
     if pit_entry:
         fib_entry = self.fib.find_fib_entry(
             interest.name, incoming_faceids=pit_entry.faceids)
     else:
         fib_entry = self.fib.find_fib_entry(interest.name)
     if fib_entry is not None:
         self.pit.add_used_fib_entry(interest.name, fib_entry)
         to_lower.put([fib_entry.faceid, interest])
     else:
         self.logger.info("No FIB entry, sending Nack: " +
                          str(interest.name))
         nack = Nack(interest.name, NackReason.NO_ROUTE, interest=interest)
         if pit_entry is not None:  # if pit entry is available, consider it, otherwise assume interest came from higher
             for i in range(0, len(pit_entry.faceids)):
                 if pit_entry._local_app[i]:
                     to_higher.put([face_id, nack])
                     #    else:
                     #       to_lower.put([pit_entry._faceids[i], nack])
         else:
             to_higher.put([face_id, nack])
Ejemplo n.º 14
0
 def handle_interest(self, face_id: int, interest: Interest,
                     to_lower: multiprocessing.Queue):
     """
     Handle incoming interest
     :param face_id: ID of incoming face
     :param interest: Interest
     :param to_lower: Queue to lower layer
     :return: None
     """
     cache_entry = self.cache.find_content_object(interest.name)
     if cache_entry is not None:
         self.logger.info("Found in cache")
         to_lower.put([face_id, cache_entry.content])
         return
     else:
         if self.generate_data(interest.name) is False:
             nack = Nack(interest.name,
                         NackReason.NO_CONTENT,
                         interest=interest)
             to_lower.put([face_id, nack])
             self.logger.info("Object not in repo")
             return
         else:
             self.logger.info("Not found in cache, successfully generated")
             manifest = self.cache.find_content_object(
                 interest.name).content
             to_lower.put([face_id, manifest])
             return
Ejemplo n.º 15
0
    def test_multicast_and_nack_handling(self):
        """Test if a multicast works, and if the nack counter for the multicast works"""

        i1 = Interest("/test/data")
        n1 = Nack(i1.name, NackReason.NO_CONTENT, i1)

        self.icn_layer.start_process()

        self.icn_layer.fib.add_fib_entry(i1.name, [2,3,4])

        self.icn_layer.queue_from_lower.put([1, i1])

        d1 = self.icn_layer.queue_to_lower.get(timeout=2.0)
        self.assertEqual([2, i1], d1)

        self.assertTrue(self.icn_layer.queue_to_lower.empty())


        self.icn_layer.queue_from_lower.put([2, n1])
        d2 = self.icn_layer.queue_to_lower.get(timeout=4.0)
        print(d2)
        self.assertEqual([3, i1], d2)

        self.assertTrue(self.icn_layer.queue_to_lower.empty())

        self.icn_layer.queue_from_lower.put([3, n1])
        try:
            d3 = self.icn_layer.queue_to_lower.get(timeout=4.0)
        except:
            self.fail()
        print(d3)
        self.assertEqual([4, i1], d3)
Ejemplo n.º 16
0
 def decode(self, wire_data) -> Packet:
     """
     NDN TLV wire format packet to python object (PiCN's internal representation)
     :param wire_data: Packet in wire format (NDN TLV representation)
     :return: Packet in PiCN's internal representation
     """
     # print("got %d bytes to decode" % len(wire_data))
     if(self.is_content(wire_data)):
         self.logger.info("Decode content object")
         try:
             (name, payload) = self.decode_data(wire_data)
             return Content(name, payload, wire_data)
         except:
             self.logger.info("Decoding failed (malformed packet)")
             return UnknownPacket(wire_format=wire_data)
     if(self.is_interest(wire_data)):
         self.logger.info("Decode interest")
         try:
             name = self.decode_interest(wire_data)
             return Interest(name, wire_data)
         except:
             self.logger.info("Decoding failed (malformed packet)")
             return UnknownPacket(wire_format=wire_data)
     if(self.is_nack(wire_data)):
         self.logger.info("Decode NACK")
         try:
             (name, reason) = self.decode_nack(wire_data)
             return Nack(name, reason, None, wire_format=wire_data)
         except:
             self.logger.info("Decoding failed (malformed packet)")
             return UnknownPacket(wire_format=wire_data)
     else:
         self.logger.info("Decode failed (unknown packet type)")
         return UnknownPacket(wire_format=wire_data)
Ejemplo n.º 17
0
 def handleNack(self, packet_id: int, nack: Nack):
     """Handles a Nack
     :param packet_id: id of the computation
     :param nack: nack that arrived
     """
     remove_list = []
     for e in self.computation_table.get_container():
         self.computation_table.remove_computation(e.original_name)
         #check next rewrite if current is nack-ed TODO this is a code duplication with ageing in ComputationTableEntry
         if e.comp_state == NFNComputationState.REWRITE and\
                 e.rewrite_list != [] and\
                 nack.name == self.parser.nfn_str_to_network_name(e.rewrite_list[0]):
             e.rewrite_list.pop(0)
             if e.rewrite_list == []:
                 remove_list.append(e.original_name)
             else:
                 request = Interest(self.parser.nfn_str_to_network_name(e.rewrite_list[0]))
                 self.queue_to_lower.put([e.id, request])
         #check if nack-ed data were required.
         elif nack.name == e.original_name:
             remove_list.append(e.original_name)
         else:
             for a in e.awaiting_data:
                 if nack.name == a.name:
                     remove_list.append(e.original_name)
         self.computation_table.append_computation(e)
     #remove all computation that are nack-ed and forward nack
     for r in remove_list:
         e = self.computation_table.get_computation(r)
         self.computation_table.remove_computation(r)
         new_nack = Nack(e.original_name, nack.reason, interest=e.interest)
         self.queue_to_lower.put([e.id, new_nack])
         self.handleNack(e.id, new_nack)
Ejemplo n.º 18
0
 def data_from_lower(self, to_lower: multiprocessing.Queue,
                     to_higher: multiprocessing.Queue, data: Packet):
     self.logger.info("Got Data from lower")
     if self._repository is None:
         return
     faceid = data[0]
     packet = data[1]
     if isinstance(
             packet, Interest
     ):  # TODO: Can I check here for connector interest and return session key?
         if self._repository.is_content_available(packet.name):
             c = self._repository.get_content(packet.name)
             self.queue_to_lower.put([faceid, c])
             self.logger.info("Found content object, sending down")
             return
         elif self._propagate_interest is True:  # TODO: What does this do? --> Used for NDN.
             self.queue_to_lower.put([faceid, packet])
             return
         else:
             self.logger.info(
                 "No matching data, dropping interest, sending nack")
             nack = Nack(packet.name,
                         NackReason.NO_CONTENT,
                         interest=packet)
             to_lower.put([faceid, nack])
             return
     if isinstance(packet, Content):
         pass
Ejemplo n.º 19
0
 def ageing(self):
     """Ageing the data structs"""
     try:
         self.logger.debug("Ageing")
         #PIT ageing
         retransmits, removed_pit_entries = self.pit.ageing()
         for pit_entry in retransmits:
             fib_entry = self.fib.find_fib_entry(
                 pit_entry.name, pit_entry.fib_faces_already_used,
                 pit_entry.faceids)
             if not fib_entry:
                 continue
             for fid in fib_entry.faceid:
                 if not self.pit.test_faceid_was_nacked(
                         pit_entry.name, fid):
                     self.queue_to_lower.put([fid, pit_entry.interest])
         for pit_entry in removed_pit_entries:
             if not pit_entry:
                 continue
             for fid, local in zip(pit_entry.faceids, pit_entry.local_app):
                 if local is True:
                     self.queue_to_higher.put([
                         fid,
                         Nack(pit_entry.name, NackReason.PIT_TIMEOUT,
                              pit_entry.interest)
                     ])
         #CS ageing
         self.cs.ageing()
     except Exception as e:
         self.logger.warning("Exception during ageing: " + str(e))
         pass
     finally:
         t = threading.Timer(self._ageing_interval, self.ageing)
         t.setDaemon(True)
         t.start()
Ejemplo n.º 20
0
 def test_none_thunk_nack_from_higher(self):
     """test that a normal nack is forwared from higher to lower"""
     nack = Nack("/test/data",
                 NackReason.NO_CONTENT,
                 interest=Interest("/test/data"))
     self.thunklayer.queue_from_higher.put([1, nack])
     res = self.thunklayer.queue_to_lower.get(timeout=2)
     self.assertEqual(res, [1, nack])
Ejemplo n.º 21
0
 def get_matching_content_from_packed_name(self, packet: Packet):
     """Return either the content matching the unpacked name or NACK"""
     name_in = self.unpack(packet.name)
     if name_in in self._chunk_table:
         matching_content = self._chunk_table.get(name_in)[0]
         matching_content.name = packet.name
         return matching_content
     else:
         return Nack(packet.name, NackReason.NO_CONTENT, packet)
Ejemplo n.º 22
0
    def test_keep_alive_request_no_comp_running(self):
        """test replying a incoming keep alive request if no comp running"""
        keep_alive = Interest("/test/func/_()/KEEPALIVE/NFN")
        nack = Nack(keep_alive.name, reason=NackReason.COMP_NOT_RUNNING, interest=keep_alive)

        self.timeoutPreventionLayer.queue_from_lower.put([3, keep_alive])
        self.assertTrue(self.timeoutPreventionLayer.queue_to_higher.empty())
        res = self.timeoutPreventionLayer.queue_to_lower.get(timeout=2.0)
        self.assertEqual(res, [3, nack])
Ejemplo n.º 23
0
 def test_nack_from_lower(self):
     """Test nack from lower"""
     self.chunkLayer.start_process()
     nack1 = Nack("/test/data", NackReason.NO_CONTENT, None)
     self.chunkLayer.queue_from_lower.put([1, nack1])
     try:
         data = self.chunkLayer.queue_to_higher.get(timeout=2.0)
     except:
         self.fail()
     self.assertEqual(data[0], 1)
     self.assertEqual(data[1], nack1)
Ejemplo n.º 24
0
 def test_nack_from_lower_message_dict_entry(self):
     """test nack from lower WITH message dict entry"""
     nack = Nack("/test/data", interest=Interest("/test/data"), reason=NackReason.CONGESTION)
     self.timeoutPreventionLayer.message_dict.create_entry(nack.name, 1)
     e = self.timeoutPreventionLayer.message_dict.get_entry(nack.name)
     self.assertTrue(e is not None)
     self.timeoutPreventionLayer.queue_from_lower.put([1, nack])
     res = self.timeoutPreventionLayer.queue_to_higher.get(timeout=2.0)
     self.assertEqual([1, nack], res)
     e = self.timeoutPreventionLayer.message_dict.get_entry(nack.name)
     self.assertTrue(e is None)
Ejemplo n.º 25
0
 def test_nack_prefix(self):
     """Test if repo returns Nack if nprefix not matching"""
     self.repositoryLayer.start_process()
     i1 = Interest("/data/test/f1")
     n1 = Nack(i1.name, NackReason.NO_CONTENT, interest=i1)
     self.repositoryLayer.queue_from_lower.put([0, i1])
     try:
         data = self.repositoryLayer.queue_to_lower.get(timeout=2.0)
     except:
         self.fail()
     self.assertEqual(n1, data[1])
Ejemplo n.º 26
0
    def ageing(self):
        if self.queue_to_lower._closed or self.queue_to_higher._closed:
            return
        timestamp = time.time()
        try:
            removes = []
            container = self.message_dict.get_container()
            for name in container:
                entry = self.message_dict.get_entry(name)
                if len(name.components) > 2 and name.string_components[-2] == "KEEPALIVE":

                    if entry.timestamp + self.timeout_interval < timestamp:
                        self.logger.info("Remove Keep Alvie Job because of timeout. Timestamp is: " + str(entry.timestamp) + " Now is: " + str(timestamp))
                        removes.append(name)
                        if name in self.running_computations:
                            self.running_computations.remove(name)
                        original_name = self.remove_keep_alive_from_name(name)
                        removes.append(original_name)
                        if original_name in self.running_computations:
                            self.running_computations.remove(original_name)
                        nack = Nack(name=original_name, reason=NackReason.COMP_NOT_RUNNING, interest=Interest(name))
                        self.queue_to_higher.put([entry.packetid, nack])
                    else:
                        self.queue_to_lower.put([entry.packetid, Interest(name=name)])
                else:
                    if name.components[-1] != b'NFN' and entry.timestamp + self.timeout_interval < time.time():
                        removes.append(name)
                        nack = Nack(name=name, reason=NackReason.COMP_PARAM_UNAVAILABLE, interest=Interest(name))
                        self.queue_to_higher.put([entry.packetid, nack])
                    else:
                        self.queue_to_lower.put([entry.packetid, Interest(name=name)])
            for n in removes:
                self.message_dict.remove_entry(n)
                if self.pit is not None:
                    self.pit.remove_pit_entry(n)
        except Exception as e:
            self.logger.warning("Exception during ageing: " + str(e))
            return
        t = threading.Timer(self.ageing_interval, self.ageing)
        t.setDaemon(True)
        t.start()
Ejemplo n.º 27
0
    def handle_interest_from_higher(self, face_id: int, interest: Interest,
                                    to_lower: multiprocessing.Queue,
                                    to_higher: multiprocessing.Queue):
        self.logger.info("Handling Interest (from higher): " +
                         str(interest.name) + "; Face ID: " + str(face_id))
        cs_entry = self.cs.find_content_object(interest.name)
        if cs_entry is not None:
            self.queue_to_higher.put([face_id, cs_entry.content])
            return
        pit_entry = self.pit.find_pit_entry(interest.name)

        if pit_entry:
            self.pit.add_interested_face(interest.name, face_id)
            fib_entry = self.fib.find_fib_entry(
                interest.name, incoming_faceids=pit_entry.faceids)
        else:
            fib_entry = self.fib.find_fib_entry(interest.name)

        if fib_entry is not None:
            self.pit.set_number_of_forwards(interest.name, 0)
            pit_occupancy = self.pit.occupancy_available_faces_per_name(
                fib_entry)
            sorted_pit_occupancy = sorted(pit_occupancy.items(),
                                          key=lambda kv: kv[1])
            faces_sorted_by_occupancy = list(
                map(lambda kv: kv[0], sorted_pit_occupancy))

            for fid in faces_sorted_by_occupancy:
                try:
                    if not self.pit.test_faceid_was_nacked(interest.name, fid):
                        self.pit.add_pit_entry(interest.name,
                                               face_id,
                                               fid,
                                               interest,
                                               local_app=True)
                        self.pit.increase_number_of_forwards(interest.name)
                        self.pit.add_used_fib_face(interest.name, [fid])
                        to_lower.put([fid, interest])
                        break
                except:
                    pass
        else:
            self.logger.info("No FIB entry, sending Nack: " +
                             str(interest.name))
            nack = Nack(interest.name, NackReason.NO_ROUTE, interest=interest)
            if pit_entry is not None:  # if pit entry is available, consider it, otherwise assume interest came from higher
                for i in range(0, len(pit_entry.faceids)):
                    if pit_entry._local_app[i]:
                        to_higher.put([face_id, nack])
                    else:
                        to_lower.put([pit_entry._faceids[i], nack])
            else:
                to_higher.put([face_id, nack])
Ejemplo n.º 28
0
 def test_Nack_Creation_no_wireformat(self):
     """Test the creation of a nack object message with no wireformat given"""
     name: Name = Name("/test/data")
     i1: Interest = Interest(name)
     n1: Nack = Nack(name, NackReason.NO_ROUTE, interest=i1)
     enc_n1 = self.encoder.encode(n1)
     self.assertEqual(enc_n1[0], 0x64)
     self.assertEqual(enc_n1[3], 0x03)
     self.assertEqual(enc_n1[4], 0x20)
     self.assertFalse(self.encoder.is_interest(enc_n1))
     self.assertFalse(self.encoder.is_content(enc_n1))
     self.assertTrue(self.encoder.is_nack(enc_n1))
     dec_n1 = self.encoder.decode(enc_n1)
     self.assertEqual(dec_n1, n1)
Ejemplo n.º 29
0
 def get_matching_content(self, packet: Packet):
     """Return either the content matching the packet name or NACK"""
     name_in = self.unpack(packet.name)
     cs_entry = self.cs.find_content_object(name_in)
     if name_in in self._chunk_table:
         matching_content = self._chunk_table.get(name_in)[0]
         matching_content.name = packet.name
         return matching_content
     elif cs_entry:
         matching_content = cs_entry.content
         matching_content.name = packet.name
         return matching_content
     else:
         return Nack(packet.name, NackReason.NO_CONTENT, packet)
Ejemplo n.º 30
0
 def test_ICNLayer_issue_nack_no_content_no_fib_from_lower(self):
     """Test if ICN Layer issues Nack if no content and no fib entry is available from lower"""
     self.icn_layer.start_process()
     interest = Interest("/test/data")
     nack = Nack(interest.name, NackReason.NO_ROUTE, interest=interest)
     self.icn_layer.queue_from_lower.put([1, interest])
     try:
         data = self.icn_layer.queue_to_lower.get(timeout=2.0)
     except:
         self.fail()
     fid = data[0]
     packet = data[1]
     self.assertEqual(fid, 1)
     self.assertEqual(packet, nack)