def test_get_functions(self): """Test the getting functions of the faceidtable""" r1 = self.faceidtable.get_address_info(3) self.assertIsNone(r1) r2 = self.faceidtable.get_face_id(AddressInfo("127.0.0.1", 1)) self.assertIsNone(r2) faceid1 = 3 addr_info1 = AddressInfo("127.0.0.1", 1) self.faceidtable.add(faceid1, addr_info1) faceid2 = 7 addr_info2 = AddressInfo("192.168.2.1", 2) self.faceidtable.add(faceid2, addr_info2) r3 = self.faceidtable.get_face_id(addr_info1) self.assertEqual(r3, 3) r4 = self.faceidtable.get_address_info(r3) self.assertEqual(r4, addr_info1) r5 = self.faceidtable.get_address_info(faceid2) self.assertEqual(r5, addr_info2) r6 = self.faceidtable.get_face_id(addr_info2) self.assertEqual(r6, faceid2)
def test_adding_entry_to_FaceIDTable(self): """test adding entries to the face table""" faceid1 = 3 addr_info1 = AddressInfo("127.0.0.1", "Interface") self.faceidtable.add(faceid1, addr_info1) self.assertEqual(self.faceidtable.addrinfo_to_faceid.get(addr_info1), faceid1) self.assertEqual(self.faceidtable.faceid_to_addrinfo.get(faceid1), addr_info1) self.assertEqual(len(self.faceidtable.addrinfo_to_faceid), 1) self.assertEqual(len(self.faceidtable.faceid_to_addrinfo), 1) faceid2 = 7 addr_info2 = AddressInfo("192.168.2.1", "Ethernet") self.faceidtable.add(faceid2, addr_info2) self.assertEqual(self.faceidtable.addrinfo_to_faceid.get(addr_info2), faceid2) self.assertEqual(self.faceidtable.faceid_to_addrinfo.get(faceid2), addr_info2) self.assertEqual(self.faceidtable.addrinfo_to_faceid.get(addr_info1), faceid1) self.assertEqual(self.faceidtable.faceid_to_addrinfo.get(faceid1), addr_info1) self.assertEqual(len(self.faceidtable.addrinfo_to_faceid), 2) self.assertEqual(len(self.faceidtable.faceid_to_addrinfo), 2)
def _setup_mobile_nodes(self): """configure the mobile nodes""" for node in self._mobile_nodes: node.forwarder = ICNForwarder( 0, encoder=SimpleStringEncoder(), routing=True, interfaces=[ self._simulation_bus.add_interface(f"car{node.node_id}") ]) node.fetch = Fetch( f"car{node.node_id}", None, 255, SimpleStringEncoder(), interfaces=[ self._simulation_bus.add_interface(f"ftcar{node.node_id}") ]) node.mgmt_tool = MgmtClient( node.forwarder.mgmt.mgmt_sock.getsockname()[1]) for stationary_node in self._stationary_nodes: car_face_id = node.forwarder.linklayer.faceidtable.get_or_create_faceid( AddressInfo(f"rsu{stationary_node.node_id}", 0)) self.to_rsu_faces[stationary_node.node_id][ node.node_id] = car_face_id rsu_face_id = node.forwarder.linklayer.faceidtable.get_or_create_faceid( AddressInfo(f"car{stationary_node.node_id}", 0)) self.to_car_faces[stationary_node.node_id][ node.node_id] = rsu_face_id
def test_NFNForwarder_compute_param_two_nodes(self): """Test a simple forwarding scenario with one additional node forwarding the data""" self.forwarder1.start_forwarder() self.forwarder2.start_forwarder() # client <---> node1 <---> node2 # create faces fid1 = self.forwarder1.linklayer.faceidtable.get_or_create_faceid( AddressInfo(("127.0.0.1", self.forwarder2_port), 0)) fid2 = self.forwarder2.linklayer.faceidtable.get_or_create_faceid( AddressInfo(("127.0.0.1", self.forwarder1_port), 0)) # register prefixes self.forwarder1.icnlayer.fib.add_fib_entry(Name("/lib/func"), [fid1], True) self.forwarder2.icnlayer.fib.add_fib_entry(Name("/test"), [fid2], True) # add function testMgmtSock1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) testMgmtSock1.connect(("127.0.0.1", self.forwarder2_port)) testMgmtSock1.send( "GET /icnlayer/newcontent/%2Flib%2Ffunc%2Ff1:PYTHON\nf\ndef f(a):\n return a.upper() HTTP/1.1\r\n\r\n" .encode()) data = testMgmtSock1.recv(1024) testMgmtSock1.close() self.assertEqual( data.decode(), "HTTP/1.1 200 OK \r\n Content-Type: text/html \r\n\r\n newcontent OK\r\n" ) # add content testMgmtSock2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) testMgmtSock2.connect(("127.0.0.1", self.forwarder1_port)) testMgmtSock2.send( "GET /icnlayer/newcontent/%2Ftest%2Fdata%2Fobject:HelloWorld HTTP/1.1\r\n\r\n" .encode()) data = testMgmtSock2.recv(1024) testMgmtSock2.close() self.assertEqual( data.decode(), "HTTP/1.1 200 OK \r\n Content-Type: text/html \r\n\r\n newcontent OK\r\n" ) # create interest name = Name("/lib/func/f1") name += "_(/test/data/object)" name += "NFN" encoded_interest = self.encoder.encode(Interest(name)) # send interest self.testSock.sendto(encoded_interest, ("127.0.0.1", self.forwarder1_port)) # receive content self.testSock.settimeout(3) encoded_content, addr = self.testSock.recvfrom(8192) time.sleep(0.1) content: Content = self.encoder.decode(encoded_content) self.assertEqual("HELLOWORLD", content.content) self.assertEqual(name, content.name) time.sleep(15) self.assertEqual(self.forwarder1.icnlayer.pit.get_container_size(), 0)
def _setup_connections_for_stationary_nodes(self): """configure the connections """ loop_variable = 0 for node in self._stationary_nodes: if loop_variable == 0: # setup first RSU faceid_rsu_1st = node.nfn_forwarder.linklayer.faceidtable.get_or_create_faceid( AddressInfo("rsu" + str(1), 0)) node.nfn_forwarder.icnlayer.fib.add_fib_entry( Name("/nR"), [faceid_rsu_1st]) elif loop_variable == (len(self._stationary_nodes) - 1): # setup last RSU faceid_rsu_last = node.nfn_forwarder.linklayer.faceidtable.get_or_create_faceid( AddressInfo("rsu" + str(loop_variable - 2), 0)) node.nfn_forwarder.icnlayer.fib.add_fib_entry( Name("/nL"), [faceid_rsu_last]) else: faceid_node_left = node.nfn_forwarder.linklayer.faceidtable.get_or_create_faceid( AddressInfo("rsu" + str(loop_variable - 1), 0)) faceid_node_right = node.nfn_forwarder.linklayer.faceidtable.get_or_create_faceid( AddressInfo("rsu" + str(loop_variable + 1), 0)) node.nfn_forwarder.icnlayer.fib.add_fib_entry( Name("/nL"), [faceid_node_left]) node.nfn_forwarder.icnlayer.fib.add_fib_entry( Name("/nR"), [faceid_node_right]) loop_variable = +1
def ll_mgmt(self, command, params, replysock): # newface expects /linklayer/newface/ip:port if (command == "newface"): ip, port, if_num = params.split(":", 2) if port != 'None': port = int(port) if_num = int(if_num) if if_num >= len(self._linklayer.interfaces): replysock.send( f"Interface Number {if_num} does not exit on node".encode( )) return if port != 'None': fid = self._linklayer.faceidtable.get_or_create_faceid( AddressInfo((ip, port), if_num)) else: fid = self._linklayer.faceidtable.get_or_create_faceid( AddressInfo(ip, if_num)) reply = "HTTP/1.1 200 OK \r\n Content-Type: text/html \r\n\r\n newface OK:" + str( fid) + "\r\n" replysock.send(reply.encode()) self.logger.info("New Face added " + ip + "|" + str(port) + ", FaceID: " + str(fid)) else: self.unknown_command(replysock) return
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()
def test_sending_and_receiving_pacets_three_nodes(self): """Testing sending/receiving packets with three nodes""" self.linklayer1.start_process() self.linklayer2.start_process() self.linklayer3.start_process() fid1_2 = self.linklayer1.faceidtable.get_or_create_faceid(AddressInfo(("127.0.0.1", self.udp4interface2.get_port()), self.linklayer1.interfaces.index(self.udp4interface1))) fid1_3 = self.linklayer1.faceidtable.get_or_create_faceid(AddressInfo(("127.0.0.1", self.udp4interface3.get_port()), self.linklayer1.interfaces.index(self.udp4interface1))) fid2_1 = self.linklayer2.faceidtable.get_or_create_faceid(AddressInfo(("127.0.0.1", self.udp4interface1.get_port()), self.linklayer2.interfaces.index(self.udp4interface2))) fid3_1 = self.linklayer3.faceidtable.get_or_create_faceid(AddressInfo(("127.0.0.1", self.udp4interface1.get_port()), self.linklayer3.interfaces.index(self.udp4interface3))) fid3_2 = self.linklayer3.faceidtable.get_or_create_faceid(AddressInfo(("127.0.0.1", self.udp4interface2.get_port()), self.linklayer3.interfaces.index(self.udp4interface3))) for i in range(1, 100): str1 = "Node1" + str(i) str2 = "Node2" + str(i) str3 = "Node3" + str(i) # Node 1 ---> Node 2 self.linklayer1.queue_from_higher.put([fid1_2, str1.encode()]) try: data1_2 = self.linklayer2.queue_to_higher.get(timeout=2.0) except: self.fail() # Node 1 ---> Node 3 self.linklayer1.queue_from_higher.put([fid1_3, str1.encode()]) try: data1_3 = self.linklayer3.queue_to_higher.get(timeout=2.0) except: self.fail() # Node 2 ---> Node 1 self.linklayer2.queue_from_higher.put([fid2_1, str2.encode()]) try: data2_1 = self.linklayer1.queue_to_higher.get(timeout=2.0) except: self.fail() # Node 3 ---> Node 1 self.linklayer3.queue_from_higher.put([fid3_1, str3.encode()]) try: data3_1 = self.linklayer1.queue_to_higher.get(timeout=2.0) except: self.fail() # Node 3 ---> Node 2 self.linklayer3.queue_from_higher.put([fid3_2, str3.encode()]) try: data3_2 = self.linklayer2.queue_to_higher.get(timeout=2.0) except: self.fail() self.assertEqual(data1_2[1].decode(), str1) self.assertEqual(data1_3[1].decode(), str1) self.assertEqual(data2_1[1].decode(), str2) self.assertEqual(data3_1[1].decode(), str3) self.assertEqual(data3_2[1].decode(), str3)
def test_interest_passed_down_after_advertisement(self): """ Test that held interests are passed downwards once a forwarder advertisement with a matching route is received. """ waittime = 3.0 self.autoconflayer.start_process() # Create some test interests, two with the advertised prefix, and one with another foobar = Interest(Name('/foo/bar')) foobaz = Interest(Name('/foo/bar')) barfoo = Interest(Name('/bar/foo')) self.queue_from_higher.put([None, foobar]) self.queue_from_higher.put([None, foobaz]) self.queue_from_higher.put([None, barfoo]) # Catch all data the autoconfig layer sends downwards for 3 seconds deadline = datetime.utcnow() + timedelta(seconds=waittime) tolower = [] while datetime.utcnow() < deadline: try: data = self.queue_to_lower.get(timeout=waittime / 10) tolower.append(data) except queue.Empty: pass # Make sure the broadcast face was actually created and get its face id bcfid = self.faceidtable.get_or_create_faceid( AddressInfo(('127.255.255.255', 4242), 0)) self.assertIsNotNone(bcfid) # Make sure a forwarder solicitation was sent downwards solictiation = Interest(Name('/autoconfig/forwarders')) self.assertIn([bcfid, solictiation], tolower) # Create a forwarder advertisement and pass it to the autoconfig layer advertisement = Content(Name('/autoconfig/forwarders'), 'udp4://127.13.37.42:1234\nr:/foo\n') self.queue_from_lower.put([bcfid, advertisement]) # Catch all data the autoconfig layer sends downwards for 3 seconds deadline = datetime.utcnow() + timedelta(seconds=waittime) tolower = [] while datetime.utcnow() < deadline: try: data = self.queue_to_lower.get(timeout=waittime / 10) tolower.append(data) except queue.Empty: pass # Make sure the face to the forwarder was actually created and get its face id fwdfid = self.faceidtable.get_face_id( AddressInfo(('127.13.37.42', 1234), 0)) self.assertIsNotNone(fwdfid) # Make sure the two interests with matching prefixes were passed downwards self.assertIn([fwdfid, foobar], tolower) self.assertIn([fwdfid, foobaz], tolower) self.assertNotIn([fwdfid, barfoo], tolower)
def test_mgmt_multiple_new_face(self): """Test the mgmt interace to create multiple new faces with deduplication""" self.linklayer.start_process() self.mgmt.start_process() self.testMgmtSock1.connect(("127.0.0.1", self.linklayerport)) self.testMgmtSock1.send( "GET /linklayer/newface/127.0.0.1:9000:0 HTTP/1.1\r\n\r\n".encode( )) data = self.testMgmtSock1.recv(1024) self.testMgmtSock1.close() self.assertEqual( data.decode(), "HTTP/1.1 200 OK \r\n Content-Type: text/html \r\n\r\n newface OK:0\r\n" ) self.testMgmtSock2.connect(("127.0.0.1", self.linklayerport)) self.testMgmtSock2.send( "GET /linklayer/newface/127.0.0.1:8000:0 HTTP/1.1\r\n\r\n".encode( )) data = self.testMgmtSock2.recv(1024) self.testMgmtSock2.close() self.assertEqual( data.decode(), "HTTP/1.1 200 OK \r\n Content-Type: text/html \r\n\r\n newface OK:1\r\n" ) self.testMgmtSock3.connect(("127.0.0.1", self.linklayerport)) self.testMgmtSock3.send( "GET /linklayer/newface/127.0.0.1:9000:0 HTTP/1.1\r\n\r\n".encode( )) data = self.testMgmtSock3.recv(1024) self.testMgmtSock3.close() self.assertEqual( data.decode(), "HTTP/1.1 200 OK \r\n Content-Type: text/html \r\n\r\n newface OK:0\r\n" ) self.assertEqual(self.linklayer.faceidtable.get_num_entries(), 2) self.assertEqual( self.linklayer.faceidtable.get_face_id( AddressInfo(("127.0.0.1", 9000), 0)), 0) self.assertEqual( self.linklayer.faceidtable.get_face_id( AddressInfo(("127.0.0.1", 8000), 0)), 1)
def test_add_face_mgmt_client(self): """Test adding a face using the mgmtclient""" self.linklayer.start_process() self.mgmt.start_process() data = self.mgmt_client.add_face("127.0.0.1", 9000, 0) self.assertEqual( data, "HTTP/1.1 200 OK \r\n Content-Type: text/html \r\n\r\n newface OK:0\r\n" ) self.assertEqual(self.linklayer.faceidtable.get_num_entries(), 1) self.assertEqual(self.linklayer.faceidtable.get_address_info(0), AddressInfo(("127.0.0.1", 9000), 0)) self.assertEqual( self.linklayer.faceidtable.get_face_id( AddressInfo(("127.0.0.1", 9000), 0)), 0)
def test_service_registration_global_only(self): self.faceidtable.add(42, AddressInfo(('127.42.42.42', 9000), 0)) waittime = 5 self.autoconflayer._register_local = False self.autoconflayer._register_global = True self.autoconflayer.start_process() # Receive forwarder solicitation bface, _ = self.queue_to_lower.get() # Send forwarder advertisement forwarders = Content(Name('/autoconfig/forwarders'), 'udp4://127.42.42.42:9000\nr:/global\npl:/test\npg:/routed\n') self.queue_from_lower.put([42, forwarders]) # Receive service registration # Catch all data the autoconfig layer sends downwards for 5 seconds data = [] timeout = datetime.utcnow() + timedelta(seconds=waittime) while datetime.utcnow() < timeout: try: data.append(self.queue_to_lower.get(timeout=waittime/10)) except queue.Empty: pass self.assertEqual(1, len(data)) fid, data = data[0] self.assertEqual(42, fid) self.assertIsInstance(data, Interest) registration_name = Name('/autoconfig/service') registration_name += 'udp4://127.0.1.1:1337' registration_name += 'routed' registration_name += 'testrepo' self.assertEqual(registration_name, data.name)
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 = []
def test_register_service_twice_different_addr_nack(self): """Test registration of a second service with a different address under the same name; should be refused""" self.autoconflayer.start_process() # Send first service registration rname = Name('/autoconfig/service') rname += 'udp4://127.42.42.42:1337' rname += 'test' rname += 'repos' rname += 'testrepo' rinterest = Interest(rname) self.faceidtable.add(42, AddressInfo(('127.13.37.42', 4567), 0)) self.queue_from_lower.put([42, rinterest]) # Receive first service registration reply, should be ACK fid, packet = self.queue_to_lower.get() self.assertEqual(42, fid) self.assertIsInstance(packet, Content) self.assertEqual(rname, packet.name) # Send second service registration with different address fname = Name('/autoconfig/service') fname += 'udp4://127.0.0.42:1337' fname += 'test' fname += 'repos' fname += 'testrepo' finterest = Interest(fname) self.queue_from_lower.put([42, finterest]) # Receive second service registration reply, should be NACK fid, packet = self.queue_to_lower.get() self.assertEqual(42, fid) self.assertIsInstance(packet, Nack) self.assertEqual(NackReason.DUPLICATE, packet.reason) self.assertEqual(fname, packet.name)
def test_register_service(self): """Test service registration and subsequent retrieval of the service list""" self.autoconflayer.start_process() # Send service registration rname = Name('/autoconfig/service') rname += 'udp4://127.42.42.42:1337' rname += 'test' rname += 'repos' rname += 'testrepo' rinterest = Interest(rname) self.faceidtable.add(42, AddressInfo(('127.13.37.42', 4567), 0)) self.queue_from_lower.put([42, rinterest]) # Receive service registration ACK fid, packet = self.queue_to_lower.get() self.assertEqual(42, fid) self.assertIsInstance(packet, Content) self.assertEqual(rname, packet.name) # Request known services list lname = Name('/autoconfig/services') linterest = Interest(lname) self.queue_from_lower.put([42, linterest]) # Receive known services list fid, packet = self.queue_to_lower.get() self.assertEqual(42, fid) self.assertIsInstance(packet, Content) self.assertEqual(lname, packet.name) lines: List[str] = [line for line in packet.content.split('\n') if len(line) > 0] self.assertIn('/test/repos/testrepo', lines)
def test_solicitation_max_retry(self): """Test that solicitations are not retried ad infinitum and a Nack NO_ROUTE is sent upwards after the timeout""" self.autoconflayer._solicitation_max_retry = 6 waittime = self.autoconflayer._solicitation_timeout * 10 self.autoconflayer.start_process() interest = Interest(Name('/foo/bar')) self.queue_from_higher.put([None, interest]) deadline = datetime.utcnow() + timedelta(seconds=waittime) tolower = [] while datetime.utcnow() < deadline: try: data = self.queue_to_lower.get(timeout=waittime / 10) tolower.append(data) except queue.Empty: pass try: tohigher = self.queue_to_higher.get(timeout=waittime / 10) except queue.Empty: self.fail() bcfid = self.faceidtable.get_or_create_faceid( AddressInfo(('127.255.255.255', 4242), 0)) self.assertIsNotNone(bcfid) solictiation = Interest(Name('/autoconfig/forwarders')) solictiation_count = len( [1 for data in tolower if data == [bcfid, solictiation]]) self.assertEqual(6, solictiation_count) self.assertIsNone(tohigher[0]) self.assertIsInstance(tohigher[1], Nack) self.assertEqual('/foo/bar', tohigher[1].name.components_to_string()) self.assertEqual(NackReason.NO_ROUTE, tohigher[1].reason)
def setUp(self): synced_data_struct_factory = PiCNSyncDataStructFactory() synced_data_struct_factory.register( 'fib', ForwardingInformationBaseMemoryPrefix) synced_data_struct_factory.register('faceidtable', FaceIDDict) synced_data_struct_factory.create_manager() fib = synced_data_struct_factory.manager.fib() self.faceidtable: FaceIDDict = synced_data_struct_factory.manager.faceidtable( ) # Create a face and an example route self.mock_interface = MockInterface(port=1337) self.linklayer = BasicLinkLayer([self.mock_interface], self.faceidtable) outfid = self.linklayer.faceidtable.get_or_create_faceid( AddressInfo(('127.13.37.42', 4242), 0)) fib.add_fib_entry(Name('/global'), [outfid]) # List of advertised prefixes self.prefixes: List[Tuple[Name, bool]] = [(Name('/test/repos'), False), (Name('/home'), True)] self.autoconflayer = AutoconfigServerLayer( linklayer=self.linklayer, address='127.0.1.1', registration_prefixes=self.prefixes) self.autoconflayer.fib = fib self.autoconflayer.queue_to_higher = self.queue_to_higher = multiprocessing.Queue( ) self.autoconflayer.queue_from_higher = self.queue_from_higher = multiprocessing.Queue( ) self.autoconflayer.queue_to_lower = self.queue_to_lower = multiprocessing.Queue( ) self.autoconflayer.queue_from_lower = self.queue_from_lower = multiprocessing.Queue( )
def test_solicitation_no_reply_resend(self): """Test whether a forwarder solicitation is resent if no reply is received""" waittime = self.autoconflayer._solicitation_timeout * 4.0 self.autoconflayer.start_process() interest = Interest(Name('/foo/bar')) self.queue_from_higher.put([None, interest]) # Catch all data the autoconfig layer sends downwards for 3 seconds deadline = datetime.utcnow() + timedelta(seconds=waittime) tolower = [] while datetime.utcnow() < deadline: try: data = self.queue_to_lower.get(timeout=waittime / 10) tolower.append(data) except queue.Empty: pass # Make sure the broadcast face was actually created and get its face id bcfid = self.faceidtable.get_or_create_faceid( AddressInfo(('127.255.255.255', 4242), 0)) self.assertIsNotNone(bcfid) # Make sure the forwarder solicitation was sent more than once solictiation = Interest(Name('/autoconfig/forwarders')) solictiation_count = len( [1 for data in tolower if data == [bcfid, solictiation]]) self.assertGreater(solictiation_count, 1)
def test_send_single_packet_with_delay(self): """Test fetching a single content object over the simulation bus""" delay_func = lambda packet: 0.5 self.fetchiface = self.simulation_bus.add_interface("fetch", delay_func=delay_func) self.icn_forwarder1 = ICNForwarder(port=0, encoder=self.encoder_type(), interfaces=[self.simulation_bus.add_interface("icnfwd1", delay_func=delay_func)]) self.icn_forwarder2 = ICNForwarder(port=0, encoder=self.encoder_type(), interfaces=[self.simulation_bus.add_interface("icnfwd2", delay_func=delay_func)]) self.simulation_bus.start_process() self.icn_forwarder1.start_forwarder() self.icn_forwarder2.start_forwarder() fid1 = self.icn_forwarder1.linklayer.faceidtable.get_or_create_faceid(AddressInfo("icnfwd2", 0)) self.icn_forwarder1.icnlayer.fib.add_fib_entry(Name("/test"), [fid1]) self.icn_forwarder2.icnlayer.cs.add_content_object(Content("/test/data", "HelloWorld"), static=True) interest = Interest("/test/data") wire_data = self.encoder.encode(interest) self.fetchiface.send(wire_data, "icnfwd1") res, src = self.fetchiface.receive() self.assertEqual(src, "icnfwd1") c = self.encoder.decode(res) self.assertEqual(c, Content("/test/data", "HelloWorld"))
def test_send_single_packet_with_packet_loss(self): """Test fetching a single content object over the simulation bus""" packet_loss_func = lambda packet: True self.fetchiface = self.simulation_bus.add_interface("fetch", packet_loss_func=packet_loss_func) self.icn_forwarder1 = ICNForwarder(port=0, encoder=self.encoder_type(), interfaces=[self.simulation_bus.add_interface("icnfwd1", packet_loss_func=packet_loss_func)]) self.icn_forwarder2 = ICNForwarder(port=0, encoder=self.encoder_type(), interfaces=[self.simulation_bus.add_interface("icnfwd2", packet_loss_func=packet_loss_func)]) self.simulation_bus.start_process() self.icn_forwarder1.start_forwarder() self.icn_forwarder2.start_forwarder() fid1 = self.icn_forwarder1.linklayer.faceidtable.get_or_create_faceid(AddressInfo("icnfwd2", 0)) self.icn_forwarder1.icnlayer.fib.add_fib_entry(Name("/test"), [fid1]) self.icn_forwarder2.icnlayer.cs.add_content_object(Content("/test/data", "HelloWorld"), static=True) interest = Interest("/test/data") wire_data = self.encoder.encode(interest) self.fetchiface.send(wire_data, "icnfwd1") try: self.fetchiface.receive(timeout=4) except queue.Empty: pass else: self.fail()
def test_service_registration_timeout_renewal(self): """Test that the service registration is renewed before the timeout""" self.faceidtable.add(42, AddressInfo(('127.42.42.42', 9000), 0)) waittime = 5 self.autoconflayer.start_process() # Receive forwarder solicitation bface, _ = self.queue_to_lower.get() # Send forwarder advertisement forwarders = Content(Name('/autoconfig/forwarders'), 'udp4://127.42.42.42:9000\nr:/global\npl:/test\n') self.queue_from_lower.put([42, forwarders]) # Receive service registration fid, data = self.queue_to_lower.get() registration_name = Name('/autoconfig/service') registration_name += 'udp4://127.0.1.1:1337' registration_name += 'test' registration_name += 'testrepo' self.assertEqual(registration_name, data.name) # Send service registration ACK with a ridiculously short timeout content = Content(registration_name, f'{waittime}\n') self.queue_from_lower.put([42, content]) # Catch all data the autoconfig layer sends downwards for 5 seconds data = [] timeout = datetime.utcnow() + timedelta(seconds=waittime) while datetime.utcnow() < timeout: try: data.append(self.queue_to_lower.get(timeout=waittime/10)) except queue.Empty: pass registration_interest = Interest(registration_name) self.assertIn([42, registration_interest], data)
def test_sending_and_receiving_packets(self): """Test sending/receiving many packets in a single case""" self.linklayer1.start_process() self.linklayer2.start_process() fid1 = self.linklayer1.faceidtable.get_or_create_faceid( AddressInfo(("127.0.0.1", self.udp4interface2.get_port()), self.linklayer1.interfaces.index(self.udp4interface1))) self.linklayer1.start_process() self.linklayer2.start_process() fid2 = self.linklayer2.faceidtable.get_or_create_faceid( AddressInfo(("127.0.0.1", self.udp4interface1.get_port()), self.linklayer2.interfaces.index(self.udp4interface2))) for i in range(1, int(1e3)): str1 = "HelloWorld" + str(i) str2 = "GoodBye" + str(i) self.linklayer1.queue_from_higher.put([fid1, str1.encode()]) self.linklayer2.queue_from_higher.put([fid2, str2.encode()]) d2 = self.linklayer2.queue_to_higher.get(timeout=5.0) d1 = self.linklayer1.queue_to_higher.get(timeout=5.0) packet2 = d1[1].decode() packet1 = d2[1].decode() self.assertEqual(packet1, str1) self.assertEqual(packet2, str2) for i in range(1, int(1e3)): str1 = "HelloWorld" + str(i) str2 = "GoodBye" + str(i) self.linklayer1.queue_from_higher.put([fid1, str1.encode()]) self.linklayer2.queue_from_higher.put([fid2, str2.encode()]) d1 = self.linklayer1.queue_to_higher.get(timeout=5.0) d2 = self.linklayer2.queue_to_higher.get(timeout=5.0) packet2 = d1[1].decode() packet1 = d2[1].decode() self.assertEqual(packet1, str1) self.assertEqual(packet2, str2)
def _send_routing_interest(self): solicitation: Interest = Interest(self._prefix) for addr in self._peers: addr_info: AddressInfo = AddressInfo(addr, 0) fid = self._linklayer.faceidtable.get_or_create_faceid(addr_info) try: self.queue_to_lower.put([fid, solicitation]) except AssertionError: # Queue is closed. return
def test_sending_a_packet(self): """Test if a packet is sent correctly""" self.linklayer1.start_process() fid = self.linklayer1.faceidtable.get_or_create_faceid( AddressInfo(("127.0.0.1", self.test_port), self.linklayer1.interfaces.index(self.udp4interface1))) self.linklayer1.queue_from_higher.put([fid, "HelloWorld".encode()]) data, addr = self.testSock.recvfrom(8192) self.assertEqual(data.decode(), "HelloWorld")
def test_get_or_create_faceid(self): """test adding a face and automatically adding a faceid""" faceid1 = 0 addr_info1 = AddressInfo("127.0.0.1", 1) r1 = self.faceidtable.get_or_create_faceid(addr_info1) self.assertEqual(r1, faceid1) r2 = self.faceidtable.get_address_info(faceid1) self.assertEqual(r2, addr_info1) r3 = self.faceidtable.get_or_create_faceid(addr_info1) self.assertEqual(r3, faceid1)
def start_process(self): super().start_process() self.logger.info('Soliciting forwarders') forwarders_interest = Interest(_AUTOCONFIG_FORWARDERS_PREFIX) for i in self._bc_interfaces: interface = self._linklayer.interfaces[i] bcaddr: str = interface.get_broadcast_address() if bcaddr is not None: addr_info = AddressInfo((bcaddr, self._broadcast_port), i) autoconf_fid = self._linklayer.faceidtable.get_or_create_faceid( addr_info, ) self.queue_to_lower.put([autoconf_fid, forwarders_interest])
def test_remove_entry(self): """Test the remove function""" faceid1 = 3 addr_info1 = AddressInfo("127.0.0.1", 1) self.faceidtable.add(faceid1, addr_info1) faceid2 = 7 addr_info2 = AddressInfo("192.168.2.1", 2) self.faceidtable.add(faceid2, addr_info2) self.assertEqual(len(self.faceidtable.addrinfo_to_faceid), 2) self.assertEqual(len(self.faceidtable.faceid_to_addrinfo), 2) self.faceidtable.remove(faceid2) self.assertEqual(len(self.faceidtable.addrinfo_to_faceid), 1) self.assertEqual(len(self.faceidtable.faceid_to_addrinfo), 1) r1 = self.faceidtable.get_face_id(addr_info2) self.assertEqual(r1, None) r2 = self.faceidtable.get_address_info(faceid1) self.assertEqual(r2, addr_info1)
def data_from_lower(self, interface: BaseInterface, to_higher: multiprocessing.Queue, data): """In the Linklayer, it handles received data, to lower is the network interface :param interface: Network interface, that received the data :param to_higher: queue to the higher layer :param data: received data """ packet = data[0] addr = data[1] addr_info = AddressInfo(addr, self.interfaces.index(interface)) faceid = self.faceidtable.get_or_create_faceid(addr_info) self.logger.info("Got data from Network and from Face ID: " + str(faceid) + ", addr: " + str(addr_info.address)) to_higher.put([faceid, packet])
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)
def test_sending_and_receiving_a_packet(self): """Test sending/receiving in a single case""" self.linklayer1.start_process() self.linklayer2.start_process() fid = self.linklayer1.faceidtable.get_or_create_faceid( AddressInfo(("127.0.0.1", self.udp4interface2.get_port()), self.linklayer1.interfaces.index(self.udp4interface1))) self.linklayer1.queue_from_higher.put([fid, "HelloWorld".encode()]) data = self.linklayer2.queue_to_higher.get(timeout=2.0) faceid = data[0] packet = data[1] self.assertEqual(faceid, 0) self.assertEqual(packet.decode(), "HelloWorld")