Ejemplo n.º 1
0
    def test08_verify_behavior_when_cache_table_is_full(self):
        # Check behavior when cache table is full.
        for num in range(NUM_QUERY_ADDRS):
            self.r1.send_udp_data(PREFIX + "900:" + str(num),
                                  PORT,
                                  random_string(10),
                                  self.r1_address,
                                  timeout=0.05)

        cache_table = self.r1.wpanctl(
            "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2)
        cache_table = wpan_table_parser.parse_address_cache_table_result(
            cache_table)

        verify(len(cache_table) == MAX_CACHE_ENTRIES)

        # Send from c2 to r1 and verify that snoop optimization uses at most`MAX_SNOOPED_NON_EVICTABLE` entries.
        for num in range(NUM_ADDRESSES):
            self.transmit_receive_udp_message(self.c2, self.r1,
                                              PREFIX + "c2:" + str(num),
                                              self.r1_address, PORT)

        cache_table = self.r1.wpanctl(
            "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2)
        cache_table = wpan_table_parser.parse_address_cache_table_result(
            cache_table)
        verify(len(cache_table) == MAX_CACHE_ENTRIES)

        snooped_entries = [
            entry for entry in cache_table
            if entry.state == wpan.ADDRESS_CACHE_ENTRY_STATE_SNOOPED
        ]
        verify(len(snooped_entries) == MAX_SNOOPED_NON_EVICTABLE)

        for entry in snooped_entries:
            verify(entry.rloc16 == self.c2_rloc)
            verify(entry.state == wpan.ADDRESS_CACHE_ENTRY_STATE_SNOOPED)
            verify(entry.can_evict() == False)
            verify(entry.timeout > 0)

        # Now send from r1 to c2, some of the snooped entries would be used, others would go through full address query.
        for num in range(NUM_ADDRESSES):
            self.transmit_receive_udp_message(self.r1, self.c2,
                                              self.r1_address,
                                              PREFIX + "c2:" + str(num), PORT)

        cache_table = self.r1.wpanctl(
            "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2)
        cache_table = wpan_table_parser.parse_address_cache_table_result(
            cache_table)
        verify(len(cache_table) == MAX_CACHE_ENTRIES)

        # Verify that c2 entries are now at the top of cache list.
        for index in range(NUM_ADDRESSES):
            verify(cache_table[index].address == PREFIX + "c2:" +
                   str(NUM_ADDRESSES - index - 1))
            verify(cache_table[index].rloc16 == self.c2_rloc)
            verify(cache_table[index].state ==
                   wpan.ADDRESS_CACHE_ENTRY_STATE_CACHED)
Ejemplo n.º 2
0
    def test06_verify_snoop_optimization(self):
        for num in range(NUM_ADDRESSES):
            self.transmit_receive_udp_message(self.r2, self.r1,
                                              PREFIX + "2:" + str(num),
                                              self.r1_address, PORT)

        cache_table = self.r1.wpanctl(
            "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2)
        cache_table = wpan_table_parser.parse_address_cache_table_result(
            cache_table)

        # We expect to see new "snooped" entries at the top of list.
        # Also verify that only MAX_SNOOPED_NON_EVICTABLE of snooped entries are non-evictable.
        verify(len(cache_table) >= NUM_ADDRESSES)

        for index in range(NUM_ADDRESSES):
            verify(cache_table[index].address == PREFIX + "2:" +
                   str(NUM_ADDRESSES - index - 1))
            verify(cache_table[index].rloc16 == self.r2_rloc)
            verify(cache_table[index].state ==
                   wpan.ADDRESS_CACHE_ENTRY_STATE_SNOOPED)
            if index < NUM_ADDRESSES - MAX_SNOOPED_NON_EVICTABLE:
                verify(cache_table[index].can_evict() == True)
                verify(cache_table[index].timeout == 0)
            else:
                print(index)
                verify(cache_table[index].can_evict() == False)
                verify(cache_table[index].timeout > 0)

        # From r1 send to r2 using the addresses from snooped entries:
        for num in range(NUM_ADDRESSES):
            self.transmit_receive_udp_message(self.r1, self.r2,
                                              self.r1_address,
                                              PREFIX + "2:" + str(num), PORT)

        cache_table = self.r1.wpanctl(
            "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2)
        cache_table = wpan_table_parser.parse_address_cache_table_result(
            cache_table)

        # We expect to see the entries to be in "cached" state now.
        verify(len(cache_table) >= NUM_ADDRESSES)

        for index in range(NUM_ADDRESSES):
            verify(cache_table[index].address == PREFIX + "2:" +
                   str(NUM_ADDRESSES - index - 1))
            verify(cache_table[index].rloc16 == self.r2_rloc)
            verify(cache_table[index].state ==
                   wpan.ADDRESS_CACHE_ENTRY_STATE_CACHED)
    def test09_verify_address_cache_table_on_r1_updates_sed2(self):
        # New network topology
        #
        #     r1 ---- r2 ---- r3
        #     |       |       |
        #     |       |       |
        #     fed1    sed2   fed3

        # Send a UDP message from sed2 to fed1.
        # This message will be forwarded by r1 to its FED child fed1.
        self.transmit_receive_udp_message([
            (self.sed2, self.fed1, self.sed2_address, self.fed1_address)
        ])
        time.sleep(ADDRESS_CACHE_TABLE_WAIT_TIME)

        # r1 upon receiving and forwarding the message from sed2 (through r2 now) should
        # update its address cache table for sed2 (address cache update through snooping).
        #
        # verify that the address cache table is updated correctly.
        addr_cache_table = self.r1.wpanctl(
            "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2)
        addr_cache_table = wpan_table_parser.parse_address_cache_table_result(
            addr_cache_table)
        verify(len(addr_cache_table) == 2)

        for entry in addr_cache_table:
            if entry.address == self.sed2_address:
                # Entry for sed2's address should now point to r2
                verify(entry.rloc16 == self.r2_rloc)
            elif entry.address == self.fed3_address:
                # Entry for fed3's address should still point to fed3
                verify(entry.rloc16 == self.fed3_rloc)
            else:
                raise VerifyError("Unknown entry in the address cache table")
    def test06_verify_address_cache_table_on_r1_removes_sed2(self):

        # New network topology
        #
        #     r1 ---- r2 ---- r3
        #     |               /\
        #     |              /  \
        #     fed1           sed2 fed3

        # From r1 send again to sed2 (which is now a child of r3).
        #
        # Note that r1 still has r2 as the destination for sed2's address in its address
        # cache table.  But since r2 is aware that sed2 is no longer its child, when it
        # receives the IPv6 message with sed2's address, r2 itself would do an address
        # query for the address and forward the IPv6 message.

        self.transmit_receive_udp_message([
            (self.r1, self.sed2, self.r1_address, self.sed2_address)
        ])
        time.sleep(ADDRESS_CACHE_TABLE_WAIT_TIME)

        # The address cache table on r1 should have sed2's address removed.
        addr_cache_table = self.r1.wpanctl(
            "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2)
        addr_cache_table = wpan_table_parser.parse_address_cache_table_result(
            addr_cache_table)
        verify(len(addr_cache_table) == 1)

        for entry in addr_cache_table:
            if entry.address == self.fed3_address:
                # Entry for fed3 should still point towards fed3
                verify(entry.rloc16 == self.fed3_rloc)
            else:
                raise VerifyError("Unknown entry in the address cache table")
    def test04_verify_address_cache_table_on_r1(self):
        # Send a single UDP message from r1 to sed2
        # Send a single UDP message from r1 to fed3
        self.transmit_receive_udp_message([
            (self.r1, self.sed2, self.r1_address, self.sed2_address),
            (self.r1, self.fed3, self.r1_address, self.fed3_address)
        ])
        time.sleep(ADDRESS_CACHE_TABLE_WAIT_TIME)
        # The address cache table on r1 should contain two entries for sed2 and fed3 addresses.

        addr_cache_table = self.r1.wpanctl(
            "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2)
        addr_cache_table = wpan_table_parser.parse_address_cache_table_result(
            addr_cache_table)
        verify(len(addr_cache_table) == 2)

        for entry in addr_cache_table:
            if entry.address == self.sed2_address:
                # Entry for sed2 should point towards its parent r2.
                verify(entry.rloc16 == self.r2_rloc)
            elif entry.address == self.fed3_address:
                # Entry for fed3 should point towards fed3 itself.
                verify(entry.rloc16 == self.fed3_rloc)
            else:
                raise VerifyError("Unknown entry in the address cache table")
Ejemplo n.º 6
0
 def check_cache_entry_switch_to_query_state():
     cache_table = self.r1.wpanctl(
         "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2)
     cache_table = wpan_table_parser.parse_address_cache_table_result(
         cache_table)
     for index in range(NUM_QUERY_ADDRS):
         verify(cache_table[index].state ==
                wpan.ADDRESS_CACHE_ENTRY_STATE_QUERY)
         verify(cache_table[index].can_evict() == True)
Ejemplo n.º 7
0
 def check_cache_entry_in_retry_state_to_get_to_zero_timeout():
     cache_table = self.r1.wpanctl(
         "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2)
     cache_table = wpan_table_parser.parse_address_cache_table_result(
         cache_table)
     for index in range(NUM_QUERY_ADDRS):
         verify(cache_table[index].state ==
                wpan.ADDRESS_CACHE_ENTRY_STATE_RETRY_QUERY)
         verify(cache_table[index].timeout == 0)
Ejemplo n.º 8
0
 def check_cache_entry_switch_to_retry_state():
     cache_table = self.r1.wpanctl(
         "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2)
     cache_table = wpan_table_parser.parse_address_cache_table_result(
         cache_table)
     for index in range(NUM_QUERY_ADDRS):
         self.logger.info(
             f"{cache_table[index].state}, {wpan.ADDRESS_CACHE_ENTRY_STATE_RETRY_QUERY}"
         )
         verify(cache_table[index].state ==
                wpan.ADDRESS_CACHE_ENTRY_STATE_RETRY_QUERY)
         verify(
             cache_table[index].retry_delay >= 2 * INITIAL_RETRY_DELAY)
Ejemplo n.º 9
0
    def test04_verify_cache_table_entries_in_query_state(self):
        # From r1 send msg to a group of addresses (not provided by any nodes in network).
        for num in range(NUM_QUERY_ADDRS):
            self.r1.send_udp_data(PREFIX + "800:" + str(num),
                                  PORT,
                                  random_string(10),
                                  self.r1_address,
                                  timeout=0.05)
            # Wait before next tx to stagger the address queries request ensuring different timeouts
            time.sleep(MAX_STAGGER_INTERVAL / NUM_QUERY_ADDRS)

        # Verify that we do see entries in cache table for all the addresses and all are in "query" state
        addr_cache_table = self.r1.wpanctl(
            "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2)
        addr_cache_table = wpan_table_parser.parse_address_cache_table_result(
            addr_cache_table)
        verify(len(addr_cache_table) == NUM_QUERY_ADDRS)
        for entry in addr_cache_table:
            verify(entry.state == wpan.ADDRESS_CACHE_ENTRY_STATE_QUERY)
            verify(not entry.can_evict())
            verify(entry.timeout > 0)
            verify(entry.retry_delay >= INITIAL_RETRY_DELAY)
    def test07_verify_address_cache_table_on_r1_adds_sed2(self):
        # Send a UDP message from r1 to sed2.
        self.transmit_receive_udp_message([
            (self.r1, self.sed2, self.r1_address, self.sed2_address)
        ])

        time.sleep(ADDRESS_CACHE_TABLE_WAIT_TIME)
        # The address cache table on r1 should have both fed1 and sed2.

        addr_cache_table = self.r1.wpanctl(
            "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2)
        addr_cache_table = wpan_table_parser.parse_address_cache_table_result(
            addr_cache_table)
        verify(len(addr_cache_table) == 2)

        for entry in addr_cache_table:
            if entry.address == self.sed2_address:
                # Entry for sed2 should point towards r3
                verify(entry.rloc16 == self.r3_rloc)
            elif entry.address == self.fed3_address:
                # Entry for fed3 should still point towards fed3
                verify(entry.rloc16 == self.fed3_rloc)
            else:
                raise VerifyError("Unknown entry in the address cache table")
Ejemplo n.º 11
0
    def test07_verify_query_requests_last_transaction_time(self):
        # Check query requests, last transaction time

        # Send from r1 to all addresses on r3.
        for num in range(NUM_ADDRESSES):
            self.transmit_receive_udp_message(self.r1, self.r3,
                                              self.r1_address,
                                              PREFIX + "3:" + str(num), PORT)
            cache_table = self.r1.wpanctl(
                "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2)
            cache_table = wpan_table_parser.parse_address_cache_table_result(
                cache_table)

        # We expect to see the cache entries for the addresses pointing to r3.
        cache_table = self.r1.wpanctl(
            "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2)
        cache_table = wpan_table_parser.parse_address_cache_table_result(
            cache_table)

        for index in range(NUM_ADDRESSES):
            verify(cache_table[index].address == PREFIX + "3:" +
                   str(NUM_ADDRESSES - index - 1))
            verify(cache_table[index].rloc16 == self.r3_rloc)
            verify(cache_table[index].state ==
                   wpan.ADDRESS_CACHE_ENTRY_STATE_CACHED)
            verify(cache_table[index].last_trans == 0)

        # Send from r1 to all addresses on c3 (sleepy child of r3)
        for num in range(NUM_ADDRESSES):
            self.transmit_receive_udp_message(self.r1, self.c3,
                                              self.r1_address,
                                              PREFIX + "c3:" + str(num), PORT)

        # We expect to see the cache entries for c3 addresses pointing to r3.
        cache_table = self.r1.wpanctl(
            "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2)
        cache_table = wpan_table_parser.parse_address_cache_table_result(
            cache_table)

        for index in range(NUM_ADDRESSES):
            verify(cache_table[index].address == PREFIX + "c3:" +
                   str(NUM_ADDRESSES - index - 1))
            verify(cache_table[index].rloc16 == self.r3_rloc)
            verify(cache_table[index].state ==
                   wpan.ADDRESS_CACHE_ENTRY_STATE_CACHED)
            # SED's keep-alive period (`POLL_PERIOD`) is 200ms, `last_trans` should always be 0 as it is
            # the number of seconds since a keep-alive was last received from the child.
            verify(cache_table[index].last_trans == 0)

        # Send again to r2. This should cause the related cache entries to be moved to top of the list:
        for num in range(NUM_ADDRESSES):
            self.transmit_receive_udp_message(self.r1, self.r2,
                                              self.r1_address,
                                              PREFIX + "2:" + str(num), PORT)

        cache_table = self.r1.wpanctl(
            "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2)
        cache_table = wpan_table_parser.parse_address_cache_table_result(
            cache_table)
        for index in range(NUM_ADDRESSES):
            verify(cache_table[index].address == PREFIX + "2:" +
                   str(NUM_ADDRESSES - index - 1))
            verify(cache_table[index].rloc16 == self.r2_rloc)
            verify(cache_table[index].state ==
                   wpan.ADDRESS_CACHE_ENTRY_STATE_CACHED)

        verify(len(cache_table) == MAX_CACHE_ENTRIES)
Ejemplo n.º 12
0
    def test05_verify_retry_query_behavior(self):
        # Wait till all the address queries time out and verify they enter "retry-query" state.
        def check_cache_entry_switch_to_retry_state():
            cache_table = self.r1.wpanctl(
                "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2)
            cache_table = wpan_table_parser.parse_address_cache_table_result(
                cache_table)
            for index in range(NUM_QUERY_ADDRS):
                self.logger.info(
                    f"{cache_table[index].state}, {wpan.ADDRESS_CACHE_ENTRY_STATE_RETRY_QUERY}"
                )
                verify(cache_table[index].state ==
                       wpan.ADDRESS_CACHE_ENTRY_STATE_RETRY_QUERY)
                verify(
                    cache_table[index].retry_delay >= 2 * INITIAL_RETRY_DELAY)

        verify_within(check_cache_entry_switch_to_retry_state, WAIT_TIME)

        # Try sending again to same addresses which are in "retry-delay" state.
        for num in range(NUM_QUERY_ADDRS):
            self.r1.send_udp_data(PREFIX + "800:" + str(num),
                                  PORT,
                                  random_string(10),
                                  self.r1_address,
                                  timeout=0.05)
        # Make sure the entries stayed in retry-delay as before.
        verify_within(check_cache_entry_switch_to_retry_state, WAIT_TIME)

        # Now wait for them to get to zero timeout.
        cache_table = self.r1.wpanctl(
            "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2)
        cache_table = wpan_table_parser.parse_address_cache_table_result(
            cache_table)

        def check_cache_entry_in_retry_state_to_get_to_zero_timeout():
            cache_table = self.r1.wpanctl(
                "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2)
            cache_table = wpan_table_parser.parse_address_cache_table_result(
                cache_table)
            for index in range(NUM_QUERY_ADDRS):
                verify(cache_table[index].state ==
                       wpan.ADDRESS_CACHE_ENTRY_STATE_RETRY_QUERY)
                verify(cache_table[index].timeout == 0)

        verify_within(check_cache_entry_in_retry_state_to_get_to_zero_timeout,
                      WAIT_TIME)

        # Now try again using the same addresses.
        for num in range(NUM_QUERY_ADDRS):
            self.r1.send_udp_data(PREFIX + "800:" + str(num),
                                  PORT,
                                  random_string(10),
                                  self.r1_address,
                                  timeout=0.05)

        # We expect now after the delay to see retries for same addresses.
        def check_cache_entry_switch_to_query_state():
            cache_table = self.r1.wpanctl(
                "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2)
            cache_table = wpan_table_parser.parse_address_cache_table_result(
                cache_table)
            for index in range(NUM_QUERY_ADDRS):
                verify(cache_table[index].state ==
                       wpan.ADDRESS_CACHE_ENTRY_STATE_QUERY)
                verify(cache_table[index].can_evict() == True)

        verify_within(check_cache_entry_switch_to_query_state, WAIT_TIME)