Esempio n. 1
0
File: Fetch.py Progetto: s3lph/PiCN
    def __init__(self,
                 ip: str,
                 port: int,
                 log_level=255,
                 encoder: BasicEncoder = None,
                 autoconfig: bool = False,
                 interfaces=None):

        # create encoder and chunkifyer
        if encoder is None:
            self.encoder = SimpleStringEncoder(log_level=log_level)
        else:
            encoder.set_log_level(log_level)
            self.encoder = encoder
        self.chunkifyer = SimpleContentChunkifyer()

        # initialize layers
        synced_data_struct_factory = PiCNSyncDataStructFactory()
        synced_data_struct_factory.register("faceidtable", FaceIDDict)
        synced_data_struct_factory.create_manager()
        faceidtable = synced_data_struct_factory.manager.faceidtable()

        if interfaces is None:
            interfaces = [UDP4Interface(0)]
        else:
            interfaces = interfaces

        # create layers
        self.linklayer = BasicLinkLayer(interfaces,
                                        faceidtable,
                                        log_level=log_level)
        self.packetencodinglayer = BasicPacketEncodingLayer(
            self.encoder, log_level=log_level)
        self.chunklayer = BasicChunkLayer(self.chunkifyer, log_level=log_level)

        self.lstack: LayerStack = LayerStack(
            [self.chunklayer, self.packetencodinglayer, self.linklayer])

        self.autoconfig = autoconfig
        if autoconfig:
            self.autoconfiglayer: AutoconfigClientLayer = AutoconfigClientLayer(
                self.linklayer)
            self.lstack.insert(self.autoconfiglayer,
                               on_top_of=self.packetencodinglayer)

        # setup communication
        if port is None:
            self.fid = self.linklayer.faceidtable.get_or_create_faceid(
                AddressInfo(ip, 0))
        else:
            self.fid = self.linklayer.faceidtable.get_or_create_faceid(
                AddressInfo((ip, port), 0))

        # send packet
        self.lstack.start_all()
Esempio n. 2
0
 def test_insert_bottom(self):
     toplayer: LayerProcess = BasicPacketEncodingLayer()
     newlayer: LayerProcess = BasicPacketEncodingLayer()
     lstack: LayerStack = LayerStack([toplayer])
     lstack.insert(newlayer, below_of=toplayer)
     self.assertEqual(2, len(lstack.layers))
     self.assertEqual(toplayer, lstack.layers[0])
     self.assertEqual(newlayer, lstack.layers[1])
     self.assertEqual(toplayer.queue_to_lower, newlayer.queue_from_higher)
     self.assertEqual(toplayer.queue_from_lower, newlayer.queue_to_higher)
     self.assertEqual(lstack.queue_to_lower, newlayer.queue_to_lower)
     self.assertEqual(lstack.queue_from_lower, newlayer.queue_from_lower)
Esempio n. 3
0
    def __init__(self,
                 ip: str,
                 port: int,
                 high_level_name: Name,
                 log_level=255):
        """

        :param ip:
        :param port:
        :param high_level_name:
        :param log_level:
        """
        """
        Create stack of layers for fetch tool (UDP only)
        :param ip: IP address of entry node to network
        :param port: Port address of entry node to network
        :param high_level_name: Name of high-level object to fetch 
        :param log_level: Log level
        """
        # create encoder
        self.encoder = NdnTlvEncoder()

        # create datastruct
        synced_data_struct_factory1 = PiCNSyncDataStructFactory()
        synced_data_struct_factory1.register("faceidtable", FaceIDDict)
        synced_data_struct_factory1.create_manager()
        faceidtable = synced_data_struct_factory1.manager.faceidtable()

        # create layers

        self.link_layer = BasicLinkLayer([UDP4Interface(0)],
                                         faceidtable,
                                         log_level=log_level)
        self.packet_encoding_layer = BasicPacketEncodingLayer(
            self.encoder, log_level=log_level)
        self.fetch_layer = FetchLayer(log_level)

        self.layer_stack: LayerStack = LayerStack(
            [self.fetch_layer, self.packet_encoding_layer, self.link_layer])

        # setup face
        self.face_id = self.link_layer.faceidtable.get_or_create_faceid(
            AddressInfo((ip, port), 0))

        # start all layers in the stack
        self.layer_stack.start_all()

        # trigger fetch
        self.fetch_layer.trigger_fetching(high_level_name, self.face_id)
Esempio n. 4
0
 def test_create_multiple(self):
     toplayer: LayerProcess = BasicPacketEncodingLayer()
     middlelayer: LayerProcess = BasicPacketEncodingLayer()
     bottomlayer: LayerProcess = BasicPacketEncodingLayer()
     lstack: LayerStack = LayerStack([toplayer, middlelayer, bottomlayer])
     self.assertEqual(3, len(lstack.layers))
     self.assertEqual(4, len(lstack.queues))
     self.assertEqual(toplayer.queue_to_lower,
                      middlelayer.queue_from_higher)
     self.assertEqual(toplayer.queue_from_lower,
                      middlelayer.queue_to_higher)
     self.assertEqual(middlelayer.queue_to_lower,
                      bottomlayer.queue_from_higher)
     self.assertEqual(middlelayer.queue_from_lower,
                      bottomlayer.queue_to_higher)
     self.assertNotEqual(toplayer.queue_to_lower,
                         bottomlayer.queue_from_higher)
     self.assertNotEqual(toplayer.queue_from_lower,
                         bottomlayer.queue_to_higher)
Esempio n. 5
0
 def test_insert_between(self):
     toplayer: LayerProcess = BasicPacketEncodingLayer()
     bottomlayer: LayerProcess = BasicPacketEncodingLayer()
     newlayer: LayerProcess = BasicPacketEncodingLayer()
     lstack: LayerStack = LayerStack([toplayer, bottomlayer])
     lstack.insert(newlayer, on_top_of=bottomlayer)
     self.assertEqual(3, len(lstack.layers))
     self.assertEqual(toplayer, lstack.layers[0])
     self.assertEqual(newlayer, lstack.layers[1])
     self.assertEqual(bottomlayer, lstack.layers[2])
     self.assertEqual(toplayer.queue_to_lower, newlayer.queue_from_higher)
     self.assertEqual(toplayer.queue_from_lower, newlayer.queue_to_higher)
     self.assertEqual(bottomlayer.queue_to_higher,
                      newlayer.queue_from_lower)
     self.assertEqual(bottomlayer.queue_from_higher,
                      newlayer.queue_to_lower)
     self.assertNotEqual(toplayer.queue_to_lower,
                         bottomlayer.queue_from_higher)
     self.assertNotEqual(toplayer.queue_from_lower,
                         bottomlayer.queue_to_higher)
Esempio n. 6
0
    def setUp(self):
        synced_data_struct_factory = PiCNSyncDataStructFactory()
        synced_data_struct_factory.register('cs', ContentStoreMemoryExact)
        synced_data_struct_factory.register('pit',
                                            PendingInterstTableMemoryExact)
        synced_data_struct_factory.register(
            'fib', ForwardingInformationBaseMemoryPrefix)
        synced_data_struct_factory.register('faceidtable', FaceIDDict)
        synced_data_struct_factory.create_manager()
        # Set up forwarder
        cs = synced_data_struct_factory.manager.cs()
        pit = synced_data_struct_factory.manager.pit()
        fib = synced_data_struct_factory.manager.fib()
        prefixes = [(Name('/test/prefix/repos'), True)]
        # Auto-assign port
        forwarder_interface = UDP4Interface(0)
        forwarder_fidtable = synced_data_struct_factory.manager.faceidtable()
        forwarder_linklayer = BasicLinkLayer([forwarder_interface],
                                             forwarder_fidtable)
        forwarder_port = forwarder_interface.get_port()
        forwarder_encoder = NdnTlvEncoder()
        icnlayer = BasicICNLayer()
        icnlayer.cs = cs
        icnlayer.pit = pit
        icnlayer.fib = fib
        forwarder_autoconfiglayer = AutoconfigServerLayer(
            forwarder_linklayer, registration_prefixes=prefixes)
        forwarder_autoconfiglayer.fib = fib
        self.forwarder = LayerStack([
            icnlayer, forwarder_autoconfiglayer,
            BasicPacketEncodingLayer(forwarder_encoder), forwarder_linklayer
        ])

        # Set up repo
        repository = MockRepository(Name('/thisshouldbechanged'))
        repo_chunkifyer = SimpleContentChunkifyer()
        repo_chunklayer = BasicChunkLayer(repo_chunkifyer)
        repo_encoder = NdnTlvEncoder()
        # Auto-assign port
        repo_interface = UDP4Interface(0)
        repo_fidtable = synced_data_struct_factory.manager.faceidtable()
        repo_linklayer = BasicLinkLayer([repo_interface], repo_fidtable)
        repo_port = repo_interface.get_port()
        self.repo = LayerStack([
            BasicRepositoryLayer(repository), repo_chunklayer,
            AutoconfigRepoLayer('testrepo', repo_linklayer, repository,
                                '127.0.0.1', forwarder_port),
            BasicPacketEncodingLayer(repo_encoder), repo_linklayer
        ])

        # Set up fetch client
        client_chunkifyer = SimpleContentChunkifyer()
        client_chunklayer = BasicChunkLayer(client_chunkifyer)
        client_encoder = NdnTlvEncoder()
        client_interface = UDP4Interface(0)
        client_fidtable = synced_data_struct_factory.manager.faceidtable()
        client_linklayer = BasicLinkLayer([client_interface], client_fidtable)
        self.client = LayerStack([
            client_chunklayer,
            AutoconfigClientLayer(client_linklayer, bcport=forwarder_port),
            BasicPacketEncodingLayer(client_encoder), client_linklayer
        ])
Esempio n. 7
0
class AutoConfigFullStackTestSimulation(object):
    def setUp(self):
        synced_data_struct_factory = PiCNSyncDataStructFactory()
        synced_data_struct_factory.register('cs', ContentStoreMemoryExact)
        synced_data_struct_factory.register('pit',
                                            PendingInterstTableMemoryExact)
        synced_data_struct_factory.register(
            'fib', ForwardingInformationBaseMemoryPrefix)
        synced_data_struct_factory.register('faceidtable', FaceIDDict)
        synced_data_struct_factory.create_manager()
        # Set up forwarder
        cs = synced_data_struct_factory.manager.cs()
        pit = synced_data_struct_factory.manager.pit()
        fib = synced_data_struct_factory.manager.fib()
        prefixes = [(Name('/test/prefix/repos'), True)]
        # Auto-assign port
        forwarder_interface = UDP4Interface(0)
        forwarder_fidtable = synced_data_struct_factory.manager.faceidtable()
        forwarder_linklayer = BasicLinkLayer([forwarder_interface],
                                             forwarder_fidtable)
        forwarder_port = forwarder_interface.get_port()
        forwarder_encoder = NdnTlvEncoder()
        icnlayer = BasicICNLayer()
        icnlayer.cs = cs
        icnlayer.pit = pit
        icnlayer.fib = fib
        forwarder_autoconfiglayer = AutoconfigServerLayer(
            forwarder_linklayer, registration_prefixes=prefixes)
        forwarder_autoconfiglayer.fib = fib
        self.forwarder = LayerStack([
            icnlayer, forwarder_autoconfiglayer,
            BasicPacketEncodingLayer(forwarder_encoder), forwarder_linklayer
        ])

        # Set up repo
        repository = MockRepository(Name('/thisshouldbechanged'))
        repo_chunkifyer = SimpleContentChunkifyer()
        repo_chunklayer = BasicChunkLayer(repo_chunkifyer)
        repo_encoder = NdnTlvEncoder()
        # Auto-assign port
        repo_interface = UDP4Interface(0)
        repo_fidtable = synced_data_struct_factory.manager.faceidtable()
        repo_linklayer = BasicLinkLayer([repo_interface], repo_fidtable)
        repo_port = repo_interface.get_port()
        self.repo = LayerStack([
            BasicRepositoryLayer(repository), repo_chunklayer,
            AutoconfigRepoLayer('testrepo', repo_linklayer, repository,
                                '127.0.0.1', forwarder_port),
            BasicPacketEncodingLayer(repo_encoder), repo_linklayer
        ])

        # Set up fetch client
        client_chunkifyer = SimpleContentChunkifyer()
        client_chunklayer = BasicChunkLayer(client_chunkifyer)
        client_encoder = NdnTlvEncoder()
        client_interface = UDP4Interface(0)
        client_fidtable = synced_data_struct_factory.manager.faceidtable()
        client_linklayer = BasicLinkLayer([client_interface], client_fidtable)
        self.client = LayerStack([
            client_chunklayer,
            AutoconfigClientLayer(client_linklayer, bcport=forwarder_port),
            BasicPacketEncodingLayer(client_encoder), client_linklayer
        ])

    def tearDown(self):
        self.forwarder.stop_all()
        self.repo.stop_all()
        self.client.stop_all()

    def run_simulation(self):
        self.forwarder.start_all()
        time.sleep(1.0)
        self.repo.start_all()
        time.sleep(1.0)
        self.client.start_all()
        time.sleep(5.0)

        # Send an interest with a fixed name, let autoconfig figure out where to get the data from
        name = Name('/test/prefix/repos/testrepo/testcontent')
        interest = Interest(name)
        self.client.queue_from_higher.put([None, interest])
        try:
            data = self.client.queue_to_higher.get(timeout=20.0)
        except queue.Empty:
            self.fail()

        if isinstance(
                data[1], Content
        ) and data[1].name == name and data[1].content == "testcontent":
            print("Simulation successful")
        else:
            print("Error")
Esempio n. 8
0
    def __init__(self,
                 port=9000,
                 log_level=255,
                 encoder: BasicEncoder = None,
                 interfaces: List[BaseInterface] = None,
                 executors: BaseNFNExecutor = None,
                 ageing_interval: int = 3,
                 use_thunks=False):
        # debug level
        logger = Logger("NFNForwarder", log_level)
        logger.info("Start PiCN NFN Forwarder on port " + str(port))

        # packet encoder
        if encoder is None:
            self.encoder = SimpleStringEncoder(log_level=log_level)
        else:
            encoder.set_log_level(log_level)
            self.encoder = encoder

    # setup data structures
        synced_data_struct_factory = PiCNSyncDataStructFactory()
        synced_data_struct_factory.register("cs", ContentStoreMemoryExact)
        synced_data_struct_factory.register(
            "fib", ForwardingInformationBaseMemoryPrefix)
        synced_data_struct_factory.register("pit",
                                            PendingInterstTableMemoryExact)
        synced_data_struct_factory.register("faceidtable", FaceIDDict)

        synced_data_struct_factory.register("computation_table",
                                            NFNComputationList)
        synced_data_struct_factory.register("timeoutprevention_dict",
                                            TimeoutPreventionMessageDict)
        if use_thunks:
            synced_data_struct_factory.register("thunktable", ThunkList)
            synced_data_struct_factory.register("plantable", PlanTable)

        synced_data_struct_factory.create_manager()

        cs = synced_data_struct_factory.manager.cs()
        fib = synced_data_struct_factory.manager.fib()
        pit = synced_data_struct_factory.manager.pit()
        faceidtable = synced_data_struct_factory.manager.faceidtable()

        self.parser = DefaultNFNParser()
        if use_thunks:
            thunktable = synced_data_struct_factory.manager.thunktable()
            plantable = synced_data_struct_factory.manager.plantable(
                self.parser)

        #setup chunkifier
        self.chunkifier = SimpleContentChunkifyer()

        # default interface
        if interfaces is not None:
            self.interfaces = interfaces
            mgmt_port = port
        else:
            interfaces = [UDP4Interface(port)]
            mgmt_port = interfaces[0].get_port()

        # initialize layers
        self.linklayer = BasicLinkLayer(interfaces,
                                        faceidtable,
                                        log_level=log_level)
        self.packetencodinglayer = BasicPacketEncodingLayer(
            self.encoder, log_level=log_level)
        self.icnlayer = BasicICNLayer(log_level=log_level,
                                      ageing_interval=ageing_interval)
        self.chunklayer = BasicChunkLayer(self.chunkifier, log_level=log_level)

        # setup nfn
        self.icnlayer._interest_to_app = True
        if executors is None:
            self.executors = {"PYTHON": NFNPythonExecutor()}
        else:
            self.executors = executors
        self.r2cclient = TimeoutR2CHandler()
        comp_table = synced_data_struct_factory.manager.computation_table(
            self.r2cclient, self.parser)
        self.nfnlayer = BasicNFNLayer(cs,
                                      fib,
                                      pit,
                                      faceidtable,
                                      comp_table,
                                      self.executors,
                                      self.parser,
                                      self.r2cclient,
                                      log_level=log_level)
        if use_thunks:
            self.thunk_layer = BasicThunkLayer(cs,
                                               fib,
                                               pit,
                                               faceidtable,
                                               thunktable,
                                               plantable,
                                               self.parser,
                                               log_level=log_level)
            self.nfnlayer.optimizer = ThunkPlanExecutor(
                cs, fib, pit, faceidtable, plantable)

        timeoutprevention_dict = synced_data_struct_factory.manager.timeoutprevention_dict(
        )
        self.timeoutpreventionlayer = BasicTimeoutPreventionLayer(
            timeoutprevention_dict, comp_table, pit=pit, log_level=log_level)

        if use_thunks:
            self.lstack: LayerStack = LayerStack([
                self.nfnlayer, self.chunklayer, self.timeoutpreventionlayer,
                self.thunk_layer, self.icnlayer, self.packetencodinglayer,
                self.linklayer
            ])
        else:
            self.lstack: LayerStack = LayerStack([
                self.nfnlayer, self.chunklayer, self.timeoutpreventionlayer,
                self.icnlayer, self.packetencodinglayer, self.linklayer
            ])

        self.icnlayer.cs = cs
        self.icnlayer.fib = fib
        self.icnlayer.pit = pit

        # mgmt
        self.mgmt = Mgmt(self.icnlayer.cs,
                         self.icnlayer.fib,
                         self.icnlayer.pit,
                         self.linklayer,
                         mgmt_port,
                         self.stop_forwarder,
                         log_level=log_level)
Esempio n. 9
0
 def test_create_empty(self):
     with self.assertRaises(ValueError):
         lstack: LayerStack = LayerStack([])
Esempio n. 10
0
 def test_create_single(self):
     layer: LayerProcess = LayerProcess()
     lstack: LayerStack = LayerStack([layer])
     self.assertEqual(1, len(lstack.layers))
     self.assertEqual(0, len(lstack.queues))
def measure_repo_hopping(run: int,
                         routing_interval: float,
                         hopping_interval: float,
                         lease_time: float,
                         edge_traverse: bool = False):
    testname = f'repo_hopping{"_edge_traverse" if edge_traverse else ""}'
    print(
        f'{testname} routing interval={routing_interval}, hopping interval={hopping_interval}, lease time='
        + f'{lease_time}, run {run}')
    global repo, lock, running
    manager = multiprocessing.Manager()
    autoconfig_edgeprefix: List[Tuple[Name, bool]] = [(Name('/edge'), False)]
    nodes: Dict[int, ICNForwarder] = dict()
    ports: Dict[int, Tuple[str, int]] = dict()
    edgeports: List[int] = list()

    # Initialize core nodes
    for c in [00, 10, 20, 30]:
        nodes[c] = ICNForwarder(9000 + c,
                                encoder=NdnTlvEncoder(),
                                routing=True,
                                peers=[])
        ports[c] = nodes[c].linklayer.sock.getsockname()
    # Initialize edge nodes
    for e in [11, 12, 13, 21, 22, 23, 31, 32, 33]:
        nodes[e] = ICNForwarder(9000 + e,
                                encoder=NdnTlvEncoder(),
                                routing=True,
                                peers=[],
                                autoconfig=True)
        ports[e] = nodes[e].linklayer.sock.getsockname()
        edgeports.append(ports[e][1])

    # Assign routing peers after the OS assigned UDP ports. Each node knows the nodes one layer "beneath" itself
    # in above graph as its routing peers.
    nodes[00].routinglayer._peers = [ports[10], ports[20], ports[30]]
    nodes[10].routinglayer._peers = [ports[11], ports[12], ports[13]]
    nodes[20].routinglayer._peers = [ports[21], ports[22], ports[23]]
    nodes[30].routinglayer._peers = [ports[31], ports[32], ports[33]]

    # Set up faces and static FIB of core00 node.
    fid00to10: int = nodes[00].linklayer.get_or_create_fid(ports[10],
                                                           static=True)
    fid00to20: int = nodes[00].linklayer.get_or_create_fid(ports[20],
                                                           static=True)
    fid00to30: int = nodes[00].linklayer.get_or_create_fid(ports[30],
                                                           static=True)
    fib00: BaseForwardingInformationBase = nodes[00].data_structs['fib']
    if edge_traverse:
        fib00.add_fib_entry(Name('/edge'), fid00to10, static=True)
        fib00.add_fib_entry(Name('/edge'), fid00to20, static=True)
        fib00.add_fib_entry(Name('/edge'), fid00to30, static=True)
    nodes[00].data_structs['fib'] = fib00
    nodes[00].data_structs['rib'] = TreeRoutingInformationBase(
        manager, shortest_only=False)

    # Set up faces and static FIB of core10 node.
    fid10to11: int = nodes[10].linklayer.get_or_create_fid(ports[11],
                                                           static=True)
    fid10to12: int = nodes[10].linklayer.get_or_create_fid(ports[12],
                                                           static=True)
    fid10to13: int = nodes[10].linklayer.get_or_create_fid(ports[13],
                                                           static=True)
    fib10: BaseForwardingInformationBase = nodes[10].data_structs['fib']
    if edge_traverse:
        fib10.add_fib_entry(Name('/edge'), fid10to11, static=True)
        fib10.add_fib_entry(Name('/edge'), fid10to12, static=True)
        fib10.add_fib_entry(Name('/edge'), fid10to13, static=True)
    nodes[10].data_structs['fib'] = fib10
    nodes[10].data_structs['rib'] = TreeRoutingInformationBase(
        manager, shortest_only=False)

    # Set up faces and static FIB of core20 node.
    fid20to21: int = nodes[20].linklayer.get_or_create_fid(ports[21],
                                                           static=True)
    fid20to22: int = nodes[20].linklayer.get_or_create_fid(ports[22],
                                                           static=True)
    fid20to23: int = nodes[20].linklayer.get_or_create_fid(ports[23],
                                                           static=True)
    fib20: BaseForwardingInformationBase = nodes[20].data_structs['fib']
    if edge_traverse:
        fib20.add_fib_entry(Name('/edge'), fid20to21, static=True)
        fib20.add_fib_entry(Name('/edge'), fid20to22, static=True)
        fib20.add_fib_entry(Name('/edge'), fid20to23, static=True)
    nodes[20].data_structs['fib'] = fib20
    nodes[20].data_structs['rib'] = TreeRoutingInformationBase(
        manager, shortest_only=False)

    # Set up faces and static FIB of core30 node.
    fid30to31: int = nodes[30].linklayer.get_or_create_fid(ports[31],
                                                           static=True)
    fid30to32: int = nodes[30].linklayer.get_or_create_fid(ports[32],
                                                           static=True)
    fid30to33: int = nodes[30].linklayer.get_or_create_fid(ports[33],
                                                           static=True)
    fib30: BaseForwardingInformationBase = nodes[30].data_structs['fib']
    if edge_traverse:
        fib30.add_fib_entry(Name('/edge'), fid30to31, static=True)
        fib30.add_fib_entry(Name('/edge'), fid30to32, static=True)
        fib30.add_fib_entry(Name('/edge'), fid30to33, static=True)
    nodes[30].data_structs['fib'] = fib30
    nodes[30].data_structs['rib'] = TreeRoutingInformationBase(
        manager, shortest_only=False)

    for node in [00, 10, 20, 30]:
        nodes[node].routinglayer._ageing_interval = routing_interval

    # Set up network edge autoconfig.
    for e in [11, 12, 13, 21, 22, 23, 31, 32, 33]:
        nodes[
            e].autoconfiglayer._service_registration_prefixes = autoconfig_edgeprefix
        nodes[e].routinglayer._ageing_interval = routing_interval
        nodes[e].autoconfiglayer._service_registration_timeout = timedelta(
            seconds=lease_time)

    forwarders = list(nodes.values())
    random.shuffle(forwarders)
    for n in forwarders:
        n.start_forwarder()
        sleep(0.05)

    imr = SimpleMemoryRepository(Name('/edge/hoppingrepo'), manager)
    n = 600
    for i in range(n):
        imr.add_content(Name(f'/edge/hoppingrepo/{i}'), f'content {i}')

    def repo_hop():
        global repo, edge_index, lock, running
        if repo is not None:
            repo.linklayer.sock.close()
            dumpster.append(repo)
        with lock:
            if not running:
                return
        repo = ICNDataRepository(None,
                                 Name('/hoppingrepo'),
                                 0,
                                 encoder=NdnTlvEncoder(),
                                 autoconfig=True,
                                 autoconfig_routed=True)
        repo.repolayer._repository = imr
        edge_index = (edge_index + 1) % len(edgeports)
        repo.autoconfiglayer._broadcast_port = edgeports[edge_index]
        repo.start_repo()
        threading.Timer(hopping_interval, repo_hop).start()

    repo_hop()

    class DurationTaggingLayer(LayerProcess):
        def __init__(self):
            super().__init__('DurationTaggingLayer')
            self._names: Dict[Name, datetime] = dict()

        def data_from_lower(self, to_lower: multiprocessing.Queue,
                            to_higher: multiprocessing.Queue, data):
            fid, packet = data
            if packet.name in self._names:
                to_higher.put([
                    fid, packet, (datetime.utcnow() -
                                  self._names[packet.name]).total_seconds()
                ])
                del self._names[packet.name]
            else:
                to_higher.put([fid, packet, None])

        def data_from_higher(self, to_lower: multiprocessing.Queue,
                             to_higher: multiprocessing.Queue, data):
            fid, packet = data
            self._names[packet.name] = datetime.utcnow()
            to_lower.put(data)

    linklayer = UDP4LinkLayer(port=0)
    fetch_fid = linklayer.create_new_fid(ports[00], True)
    fetch = LayerStack([
        DurationTaggingLayer(),
        BasicChunkLayer(),
        BasicPacketEncodingLayer(NdnTlvEncoder()), linklayer
    ])
    end_time = datetime.utcnow()
    fetch.start_all()
    for i in range(n):
        fetch.queue_from_higher.put(
            [fetch_fid, Interest(Name(f'/edge/hoppingrepo/{i}'))])
        end_time += timedelta(milliseconds=100)
        delay = (end_time - datetime.utcnow()).total_seconds()
        if delay > 0:
            sleep(delay)
    satisfied_interests: Dict[int, bool] = dict()
    satisfied_interests_outoforder: Dict[int, bool] = dict()
    maxreceived = -1
    avgduration = 0
    while not fetch.queue_to_higher.empty():
        _, data, duration = fetch.queue_to_higher.get()
        if isinstance(data, Content) and data.content.startswith('content '):
            _, i = data.content.split(' ', 1)
            i = int(i)
            satisfied_interests_outoforder[i] = True
            avgduration += duration
            if i <= maxreceived:
                continue
            maxreceived = i
            satisfied_interests[i] = True
    success = len(satisfied_interests)
    success_outoforder = len(satisfied_interests_outoforder)
    os.makedirs('raw', exist_ok=True)
    filename = f'raw/{now}_{testname}.csv'
    with open(filename, 'a') as f:
        f.write(
            f'{routing_interval},{hopping_interval},{lease_time},{success / n},{success_outoforder / n},{avgduration / success if success > 0 else 0.0}\n'
        )
    print(f'Wrote data to file {filename}')
    fetch.stop_all()
    for f in nodes.values():
        f.stop_forwarder()
    if repo is not None:
        repo.stop_repo()
    for r in dumpster:
        r.stop_repo()
    with lock:
        running = False