def check_off_mesh_routes(): # If a node itself adds a route, the route entry will be seen twice in # its WPAN_THREAD_OFF_MESH_ROUTES list (one time as part of network-wide # network data and again as part of the local network data). Note that # `r1 and `r2` each add a route, while `sed2` does not. verify( len(wpan.parse_list(r1.get(wpan.WPAN_THREAD_OFF_MESH_ROUTES))) == NUM_ROUTES + NUM_ROUTES_LOCAL) verify( len(wpan.parse_list(r2.get(wpan.WPAN_THREAD_OFF_MESH_ROUTES))) == NUM_ROUTES + NUM_ROUTES_LOCAL) verify( len(wpan.parse_list(sed2.get(wpan.WPAN_THREAD_OFF_MESH_ROUTES))) == NUM_ROUTES)
def verify_no_address(node_list, prefix): """ This function verifies that none of nodes in the `node_list` contain an IPv6 address with the given `prefix`. """ for node in node_list: all_addrs = wpan.parse_list(node.get(wpan.WPAN_IP6_ALL_ADDRESSES)) verify(all([not addr.startswith(prefix[:-1]) for addr in all_addrs]))
def verify_address(node_list, prefix): """ This function verifies that all nodes in the `node_list` contain an IPv6 address with the given `prefix`. """ for node in node_list: all_addrs = wpan.parse_list(node.get(wpan.WPAN_IP6_ALL_ADDRESSES)) verify(any([addr.startswith(prefix[:-1]) for addr in all_addrs]))
def verify_prefix(node_list, prefix, on_mesh=True, slaac=True, def_route=False, priority='med'): """ This function verifies that all the nodes in the given `node_list` contain an IPv6 address with the given prefix, and that the given prefix is present in the on-mesh prefixes list with the given flags (on-mesh, slaac, etc). """ for node in node_list: all_addrs = wpan.parse_list(node.get(wpan.WPAN_IP6_ALL_ADDRESSES)) verify(any([addr.startswith(prefix[:-1]) for addr in all_addrs])) prefixes = wpan.parse_on_mesh_prefix_result(node.get(wpan.WPAN_THREAD_ON_MESH_PREFIXES)) for p in prefixes: if p.prefix == prefix: verify(p.prefix_len == '64') verify(p.is_stable()) verify(p.is_on_mesh() == on_mesh) verify(p.is_def_route() == def_route) verify(p.is_slaac() == slaac) verify(p.is_dhcp() == False) verify(p.priority == priority)
# def check_child_table(): # Checks the child table includes the expected number of children. child_table = wpan.parse_list(parent.get(wpan.WPAN_THREAD_CHILD_TABLE)) verify(len(child_table) == NUM_CHILDREN) # Verify that all children are present in the child table check_child_table() # Remember number of NCP state changes (using "stat:ncp" property) per child child_num_state_changes = [] for child in all_children: child_num_state_changes.append(len(wpan.parse_list(child.get("stat:ncp")))) # Reset the parent parent.reset() def check_parent_is_associated(): verify(parent.is_associated()) wpan.verify_within(check_parent_is_associated, 5) # Verify that all the children are recovered and present in the parent's # child table again (within 5 seconds). wpan.verify_within(check_child_table, 9)
parent2.whitelist_node(child) parent1.form("inform-parent") parent2.join_node(parent1, wpan.JOIN_TYPE_ROUTER) child.join_node(parent2, wpan.JOIN_TYPE_SLEEPY_END_DEVICE); child.set(wpan.WPAN_POLL_INTERVAL, '300') #----------------------------------------------------------------------------------------------------------------------- # Test implementation # CHILD_SUPERVISION_CHECK_TIMEOUT = 2 PARENT_SUPERVISION_INTERVAL = 1 # Verify the `child` is attached to `parent2`. child_table = wpan.parse_list(parent2.get(wpan.WPAN_THREAD_CHILD_TABLE)) verify(len(child_table) == 1) # Remove the `child` from whitelist of `parent2` and add it to whitelist of `parent1` instead. parent1.whitelist_node(child) parent2.un_whitelist_node(child) # Enable supervision check on the `child` and also on `parent1`. child.set(wpan.WPAN_CHILD_SUPERVISION_CHECK_TIMEOUT, str(CHILD_SUPERVISION_CHECK_TIMEOUT)) parent1.set(wpan.WPAN_CHILD_SUPERVISION_INTERVAL, str(PARENT_SUPERVISION_INTERVAL)) # Since child supervision is not enabled on `parent2` and the `child` is # removed from whitelist on `parent2`, after the supervision check timeout # the `child` should realize that it can no longer talk to its current # parent (`parent2`) and try to reattach. All re-attach attempts to `parent2`
def check_ip6_addresses(): # Verify that SLAAC addresses are removed on r2 and c2 verify_no_address([r2, c2], PREFIX) # And that user-added address matching the prefix is not removed on r1 r1_addrs = wpan.parse_list(r1.get(wpan.WPAN_IP6_ALL_ADDRESSES)) verify(IP_ADDRESS in r1_addrs)
# List of multicast addresses subscribed by routers only router_mcast_addrs = mcast_addrs + [ "ff02::2", # All routers link-local "ff03::2" # All routers realm-local ] check_multicast_addresses(router, router_mcast_addrs) check_multicast_addresses(fed, router_mcast_addrs) check_multicast_addresses(sed, mcast_addrs) # Add a multicast address MCAST_ADDR = "ff02::114" for node in [router, fed, sed]: node.add(wpan.WPAN_IP6_MULTICAST_ADDRESSES, MCAST_ADDR) addrs = wpan.parse_list(node.get(wpan.WPAN_IP6_MULTICAST_ADDRESSES)) verify(MCAST_ADDR in addrs) node.remove(wpan.WPAN_IP6_MULTICAST_ADDRESSES, MCAST_ADDR) addrs = wpan.parse_list(node.get(wpan.WPAN_IP6_MULTICAST_ADDRESSES)) verify(not MCAST_ADDR in addrs) #----------------------------------------------------------------------------------------------------------------------- # Test finished wpan.Node.finalize_all_nodes() print '\'{}\' passed.'.format(test_name)
wpan.verify_within(check_child_addresses_on_parent, WAIT_TIME) # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Check the child recovery after a parent reset using quick re-attach # ("Child Update" exchange). # Disable supervision check on the child. child.set(wpan.WPAN_CHILD_SUPERVISION_CHECK_TIMEOUT, '1000') child.set(wpan.WPAN_POLL_INTERVAL, '10000') time.sleep(0.1) # We use the "stat:ncp" wpantund property to verify that child does not # get detached. child_num_state_changes = len(wpan.parse_list(child.get("stat:ncp"))) # Reset parent and wait for it to be associated. parent.reset() wpan.verify_within(check_parent_is_associated, WAIT_TIME) child.set(wpan.WPAN_POLL_INTERVAL, '100') # Verify that we again see all the child addresses in the parent's child table. # Note that child should register its addresses using "Child Update # Request" exchange. wpan.verify_within(check_child_addresses_on_parent, WAIT_TIME) # Verify that there was no state change on child. verify(child_num_state_changes == len(wpan.parse_list(child.get("stat:ncp"))))
def check_multicast_addresses(node, mcast_addr_list): addrs = wpan.parse_list(node.get(wpan.WPAN_IP6_MULTICAST_ADDRESSES)) for addr in mcast_addr_list: verify(addr in addrs)
joiner3.set(wpan.WPAN_THREAD_JOINER_DISCERNER_BIT_LENGTH, '0') verify(int(joiner3.get(wpan.WPAN_THREAD_JOINER_DISCERNER_BIT_LENGTH), 0) == 0) verify(int(joiner3.get(wpan.WPAN_THREAD_JOINER_DISCERNER_VALUE), 0) == 0) # Adding Joiners on Commissioner commr.commissioner_start() commr.commissioner_add_joiner_with_discerner(DISCERNER1, D_LEN1, PSK1, JOINER_TIMOUT) commr.commissioner_add_joiner_with_discerner(DISCERNER2, D_LEN2, PSK2, JOINER_TIMOUT) commr.commissioner_add_joiner(EUI64_3, PSK3, JOINER_TIMOUT) verify( len(wpan.parse_list(commr.get(wpan.WPAN_THREAD_COMMISSIONER_JOINERS))) == 3) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Start `joiner2` first # Starting with `joiner2` verifies the behavior of Commissioner to # prefer the Joiner entry with the longest matching discriminator. Note # that `joiner2` uses a longer discriminator compared to `joiner1` with # similar value. joiner2.joiner_join(PSK2) verify(joiner2.get(wpan.WPAN_STATE) == wpan.STATE_COMMISSIONED) joiner2.joiner_attach()
def check_ip6_addresses(): # Verify that SLAAC addresses are removed on r2 and c2 verify_no_address([r2,c2], PREFIX) # And that user-added address matching the preifx is not removed on r1 r1_addrs = wpan.parse_list(r1.get(wpan.WPAN_IP6_ALL_ADDRESSES)) verify(IP_ADDRESS in r1_addrs)
r1.remove_prefix(PREFIX) wpan.verify_within(check_prefix_and_slaac_address_are_removed, WAIT_INTERVAL) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IP_ADDRESS = PREFIX + "1234" # Explicitly add an address with the prefix on r1 r1.add_ip6_address_on_interface(IP_ADDRESS) # Afterwards, add the prefix on r2 (with SLAAC flag) r2.add_prefix(PREFIX, stable=True, on_mesh=True, slaac=True) wpan.verify_within(check_prefix_and_slaac_address_are_added, WAIT_INTERVAL) # Verify that on r1 we do see the user-added address r1_addrs = wpan.parse_list(r1.get(wpan.WPAN_IP6_ALL_ADDRESSES)) verify(IP_ADDRESS in r1_addrs) # Also verify that adding the prefix did not add a SLAAC address for same prefix on r1 r1_addrs.remove(IP_ADDRESS); verify(all([not addr.startswith(PREFIX[:-1]) for addr in r1_addrs])) # Remove the PREFIX on r2 r2.remove_prefix(PREFIX) def check_ip6_addresses(): # Verify that SLAAC addresses are removed on r2 and c2 verify_no_address([r2,c2], PREFIX) # And that user-added address matching the preifx is not removed on r1 r1_addrs = wpan.parse_list(r1.get(wpan.WPAN_IP6_ALL_ADDRESSES)) verify(IP_ADDRESS in r1_addrs)
def check_child_is_reattached(): verify( len(wpan.parse_list(child.get("stat:ncp"))) > child_num_state_changes) child_is_in_parent2_table = (len( wpan.parse_list(parent2.get(wpan.WPAN_THREAD_CHILD_TABLE))) == 1) verify(child.is_associated())
def check_child_table(): # Checks the child table includes the expected number of children. child_table = wpan.parse_list(parent.get(wpan.WPAN_THREAD_CHILD_TABLE)) verify(len(child_table) == NUM_CHILDREN)
# "00:00:06.475 ago -> offline" # ] # def check_child_table(): # Checks the child table includes the expected number of children. child_table = wpan.parse_list(parent.get(wpan.WPAN_THREAD_CHILD_TABLE)) verify(len(child_table) == NUM_CHILDREN) # Verify that all children are present in the child table check_child_table() # Remember number of NCP state changes (using "stat:ncp" property) per child child_num_state_changes = [] for child in all_children: child_num_state_changes.append(len(wpan.parse_list(child.get("stat:ncp")))) # Reset the parent parent.reset() def check_parent_is_associated(): verify(parent.is_associated()) wpan.verify_within(check_parent_is_associated, 5) # Verify that all the children are recovered and present in the parent's child table again (within 5 seconds). wpan.verify_within(check_child_table, 9) # Verify that number of state changes on all children stays as before (indicating they did not get detached). for i in range(len(all_children)): verify(child_num_state_changes[i] == len(wpan.parse_list(all_children[i].get("stat:ncp"))))
# List of multicast addresses subscribed by routers only router_mcast_addrs = mcast_addrs + [ "ff02::2", # All routers link-local "ff03::2", # All routers realm-local ] check_multicast_addresses(router, router_mcast_addrs) check_multicast_addresses(fed, router_mcast_addrs) check_multicast_addresses(sed, mcast_addrs) # Add a multicast address MCAST_ADDR = "ff02::114" for node in [router, fed, sed]: node.add(wpan.WPAN_IP6_MULTICAST_ADDRESSES, MCAST_ADDR) addrs = wpan.parse_list(node.get(wpan.WPAN_IP6_MULTICAST_ADDRESSES)) verify(MCAST_ADDR in addrs) node.remove(wpan.WPAN_IP6_MULTICAST_ADDRESSES, MCAST_ADDR) addrs = wpan.parse_list(node.get(wpan.WPAN_IP6_MULTICAST_ADDRESSES)) verify(MCAST_ADDR not in addrs) # ----------------------------------------------------------------------------------------------------------------------- # Test finished wpan.Node.finalize_all_nodes() print('\'{}\' passed.'.format(test_name))
c2.whitelist_node(r3) # Wait for c2 to detach from r2 and attach to r3. # # Upon re-attach, previous parent r2 is notified and should remove c2 from # its child table. def check_c2_is_removed_from_r2_child_table(): child_table = wpan.parse_list(r2.get(wpan.WPAN_THREAD_CHILD_TABLE)) verify(len(child_table) == 0) wpan.verify_within(check_c2_is_removed_from_r2_child_table, REATTACH_WAIT_TIME) # Verify that both c2, c3 are children of r3 child_table = wpan.parse_list(r3.get(wpan.WPAN_THREAD_CHILD_TABLE)) verify(len(child_table) == 2) # New network topology # # r1 ---- r2 ---- r3 # | /\ # | / \ # c1 c2(s) c3 # From r1 send again to c2 (which is now a child of r3). # # Note that r1 still has r2 as the destination for c2's address in its address # cache table. But since r2 is aware that c2 is no longer its child, when it # receives the IPv6 message with c2's address, r2 itself would do an address # query for the address and forward the IPv6 message.
def check_c2_is_removed_from_r2_child_table(): child_table = wpan.parse_list(r2.get(wpan.WPAN_THREAD_CHILD_TABLE)) verify(len(child_table) == 0)
(r1_type == wpan.NODE_TYPE_LEADER and r2_type == wpan.NODE_TYPE_ROUTER) or ( r2_type == wpan.NODE_TYPE_LEADER and r1_type == wpan.NODE_TYPE_ROUTER ) ) wpan.verify_within(check_r1_r2_roles, short_wait) # Verify all nodes have both prefixes def check_prefixes(): verify_prefix([r1, r2, c1, c2], prefix1) verify_prefix([r1, r2, c1, c2], prefix2) wpan.verify_within(check_prefixes, short_wait) # Verify that the children stayed with their parents verify(len(wpan.parse_list(r1.get(wpan.WPAN_THREAD_CHILD_TABLE))) == 1) verify(len(wpan.parse_list(r2.get(wpan.WPAN_THREAD_CHILD_TABLE))) == 1) # ----------------------------------------------------------------------------------------------------------------------- # Test finished wpan.Node.finalize_all_nodes() print('\'{}\' passed.'.format(test_name))
test_prefix_add_remove() leader.add_prefix(prefix2, stable=True) test_prefix_add_remove() leader.remove_prefix(prefix1) test_prefix_add_remove() leader.remove_prefix(prefix2) test_prefix_add_remove() leader.add_route(prefix1, stable=False) num_routes = num_routes + 1 test_prefix_add_remove() verify( len(wpan.parse_list(c2.get(wpan.WPAN_THREAD_OFF_MESH_ROUTES))) == num_routes) leader.add_route(prefix2, stable=True) num_routes = num_routes + 1 test_prefix_add_remove() verify( len(wpan.parse_list(c2.get(wpan.WPAN_THREAD_OFF_MESH_ROUTES))) == num_routes) leader.add_prefix(prefix3, stable=True) test_prefix_add_remove() verify( len(wpan.parse_list(c2.get(wpan.WPAN_THREAD_OFF_MESH_ROUTES))) == num_routes)
def check_c_is_removed_from_r1_child_table(): child_table = wpan.parse_list(r1.get(wpan.WPAN_THREAD_CHILD_TABLE)) verify(len(child_table) == 0)
def check_r1_router_table(): router_table = wpan.parse_router_table_result( r1.get(wpan.WPAN_THREAD_ROUTER_TABLE)) verify(len(router_table) == 2) for entry in router_table: verify(entry.rloc16 == r1_rloc or entry.is_link_established()) wpan.verify_within(check_r1_router_table, WAIT_TIME) # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Check that r1 detected both TREL and 15.4 as supported radio by r2 r1_radios = wpan.parse_list(r1.get(wpan.WPAN_OT_SUPPORTED_RADIO_LINKS)) verify( len(r1_radios) == 2 and (wpan.RADIO_LINK_IEEE_802_15_4 in r1_radios) and (wpan.RADIO_LINK_TREL_UDP6 in r1_radios)) r2_radios = wpan.parse_list(r2.get(wpan.WPAN_OT_SUPPORTED_RADIO_LINKS)) verify( len(r2_radios) == 2 and (wpan.RADIO_LINK_IEEE_802_15_4 in r2_radios) and (wpan.RADIO_LINK_TREL_UDP6 in r2_radios)) def check_r1_sees_r2_has_two_radio_links(): r1_neighbor_radios = wpan.parse_multi_radio_result( r1.get(wpan.WPAN_OT_NEIGHBOR_TABLE_MULTI_RADIO_INFO)) verify(len(r1_neighbor_radios) == 1) verify(len(r1_neighbor_radios[0].radios) == 2)
def check_child_is_reattached(): verify(len(wpan.parse_list(child.get("stat:ncp"))) > child_num_state_changes) child_is_in_parent2_table = (len(wpan.parse_list(parent2.get(wpan.WPAN_THREAD_CHILD_TABLE)))==1) verify(child.is_associated())
r2.un_allowlist_node(c) r1.allowlist_node(c) c.allowlist_node(r1) # Wait for c to detach from r2 and attach to r1. def check_c_is_removed_from_r2_child_table(): child_table = wpan.parse_list(r2.get(wpan.WPAN_THREAD_CHILD_TABLE)) verify(len(child_table) == 0) wpan.verify_within(check_c_is_removed_from_r2_child_table, REATTACH_WAIT_TIME) # check that c is now a child of r1 child_table = wpan.parse_list(r1.get(wpan.WPAN_THREAD_CHILD_TABLE)) verify(len(child_table) == 1) # Send a single UDP message from r2 to c # # This adds an address cache entry on r2 for c pointing to r1 (the current parent of c). sender = r2.prepare_tx(r2_address, c_address, "Hi from r2 to c") recver = c.prepare_rx(sender) wpan.Node.perform_async_tx_rx() verify(sender.was_successful and recver.was_successful) # Force c to switch its parent from r1 to r3 # # r3 ---- r1 ---- r2 # | \
parent2.whitelist_node(child) parent1.form("inform-parent") parent2.join_node(parent1, wpan.JOIN_TYPE_ROUTER) child.join_node(parent2, wpan.JOIN_TYPE_SLEEPY_END_DEVICE) child.set(wpan.WPAN_POLL_INTERVAL, '300') # ----------------------------------------------------------------------------------------------------------------------- # Test implementation # CHILD_SUPERVISION_CHECK_TIMEOUT = 2 PARENT_SUPERVISION_INTERVAL = 1 # Verify the `child` is attached to `parent2`. child_table = wpan.parse_list(parent2.get(wpan.WPAN_THREAD_CHILD_TABLE)) verify(len(child_table) == 1) # Remove the `child` from whitelist of `parent2` and add it to whitelist # of `parent1` instead. parent1.whitelist_node(child) parent2.un_whitelist_node(child) # Enable supervision check on the `child` and also on `parent1`. child.set( wpan.WPAN_CHILD_SUPERVISION_CHECK_TIMEOUT, str(CHILD_SUPERVISION_CHECK_TIMEOUT), ) parent1.set(wpan.WPAN_CHILD_SUPERVISION_INTERVAL, str(PARENT_SUPERVISION_INTERVAL))
wpan.verify_within(check_prefix_and_slaac_address_are_removed, WAIT_INTERVAL) # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Check behavior when a user-added address with same prefix already exists. IP_ADDRESS = PREFIX + "1234" # Explicitly add an address with the prefix on r1 r1.add_ip6_address_on_interface(IP_ADDRESS) # Afterwards, add the prefix on r2 (with SLAAC flag) r2.add_prefix(PREFIX, stable=True, on_mesh=True, slaac=True) wpan.verify_within(check_prefix_and_slaac_address_are_added, WAIT_INTERVAL) # Verify that on r1 we do see the user-added address r1_addrs = wpan.parse_list(r1.get(wpan.WPAN_IP6_ALL_ADDRESSES)) verify(IP_ADDRESS in r1_addrs) # Also verify that adding the prefix did not add a SLAAC address for same # prefix on r1 r1_addrs.remove(IP_ADDRESS) verify(all([not addr.startswith(PREFIX[:-1]) for addr in r1_addrs])) # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Check behavior when a user-added address with same prefix is removed # (SLAAC module should add a SLAAC address). r1.remove_ip6_address_on_interface(IP_ADDRESS) wpan.verify_within(check_prefix_and_slaac_address_are_added, WAIT_INTERVAL) verify([node.find_ip6_address_with_prefix(PREFIX) for node in all_nodes] == slaac_addrs)
def check_child_is_reattached(): verify( len(wpan.parse_list(child.get("stat:ncp"))) > child_num_state_changes) verify(child.is_associated())
# On node2, form a network with same parameters but a different mesh-local # prefix node2.form( NET_NAME, channel=CHANNEL, panid=PANID, xpanid=XPANID, key=KEY, mesh_local_prefix=ML_PREFIX_2, ) # Node 2 is expected to attach to node1 and adopt the mesh-local prefix # from node1 verify(node2.is_associated()) verify( node2.get(wpan.WPAN_IP6_MESH_LOCAL_PREFIX) == node1.get(wpan.WPAN_IP6_MESH_LOCAL_PREFIX) ) # Ensure that there are only two addresses on the node2 (link-local and mesh-local address) and that RLOC # address is correctly filtered (by wpantund). verify(len(wpan.parse_list(node2.get(wpan.WPAN_IP6_ALL_ADDRESSES))) == 2) # ----------------------------------------------------------------------------------------------------------------------- # Test finished wpan.Node.finalize_all_nodes() print('\'{}\' passed.'.format(test_name))
c2 = wpan.Node(wpan.NODE_TREL) c3 = wpan.Node(wpan.NODE_15_4_TREL) # ----------------------------------------------------------------------------------------------------------------------- # Init all nodes wpan.Node.init_all_nodes() # ----------------------------------------------------------------------------------------------------------------------- # Test implementation WAIT_TIME = 5 # Verify that each node supports the correct radio links: parent_radios = wpan.parse_list(parent.get(wpan.WPAN_OT_SUPPORTED_RADIO_LINKS)) verify( len(parent_radios) == 2 and (wpan.RADIO_LINK_IEEE_802_15_4 in parent_radios) and (wpan.RADIO_LINK_TREL_UDP6 in parent_radios)) c1_radios = wpan.parse_list(c1.get(wpan.WPAN_OT_SUPPORTED_RADIO_LINKS)) verify(len(c1_radios) == 1 and wpan.RADIO_LINK_IEEE_802_15_4 in c1_radios) c2_radios = wpan.parse_list(c2.get(wpan.WPAN_OT_SUPPORTED_RADIO_LINKS)) verify(len(c2_radios) == 1 and wpan.RADIO_LINK_TREL_UDP6 in c2_radios) c3_radios = wpan.parse_list(c3.get(wpan.WPAN_OT_SUPPORTED_RADIO_LINKS)) verify( len(c3_radios) == 2 and (wpan.RADIO_LINK_IEEE_802_15_4 in c3_radios) and (wpan.RADIO_LINK_TREL_UDP6 in c3_radios))