staticint sched_next_online(int pid, int *next_to_try)
{
cpu_set_t cpuset; int next = *next_to_try; int ret = -1;
while (next < nr_cpus) {
CPU_ZERO(&cpuset);
CPU_SET(next, &cpuset);
next++; if (!sched_setaffinity(pid, sizeof(cpuset), &cpuset)) {
ret = 0; break;
}
}
*next_to_try = next; return ret;
}
/* Derive target_free from map_size, same as bpf_common_lru_populate */ staticunsignedint __tgt_size(unsignedint map_size)
{ return (map_size / nr_cpus) / 2;
}
/* Inverse of how bpf_common_lru_populate derives target_free from map_size. */ staticunsignedint __map_size(unsignedint tgt_free)
{ return tgt_free * nr_cpus * 2;
}
/* Size of the LRU map is 2 * Add key=1 (+1 key) * Add key=2 (+1 key) * Lookup Key=1 * Add Key=3 * => Key=2 will be removed by LRU * Iterate map. Only found key=1 and key=3
*/ staticvoid test_lru_sanity0(int map_type, int map_flags)
{ unsignedlonglong key, value[nr_cpus]; int lru_map_fd, expected_map_fd; int next_cpu = 0;
/* check that key=3 is not found */
key = 3;
assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -ENOENT);
/* check that key=1 can be found and mark the ref bit to * stop LRU from removing key=1
*/
key = 1;
assert(!bpf_map_lookup_elem_with_ref_bit(lru_map_fd, key, value));
assert(value[0] == 1234);
/* key=2 has been removed from the LRU */
key = 2;
assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -ENOENT);
/* lookup elem key=1 and delete it, then check it doesn't exist */
key = 1;
assert(!bpf_map_lookup_and_delete_elem(lru_map_fd, &key, &value));
assert(value[0] == 1234);
/* remove the same element from the expected map */
assert(!bpf_map_delete_elem(expected_map_fd, &key));
assert(map_equal(lru_map_fd, expected_map_fd));
close(expected_map_fd);
close(lru_map_fd);
printf("Pass\n");
}
/* Verify that unreferenced elements are recycled before referenced ones. * Insert elements. * Reference a subset of these. * Insert more, enough to trigger recycling. * Verify that unreferenced are recycled.
*/ staticvoid test_lru_sanity1(int map_type, int map_flags, unsignedint tgt_free)
{ unsignedlonglong key, end_key, value[nr_cpus]; int lru_map_fd, expected_map_fd; unsignedint batch_size; unsignedint map_size; int next_cpu = 0;
if (map_flags & BPF_F_NO_COMMON_LRU) /* This test is only applicable to common LRU list */ return;
/* Insert another map_size - batch_size keys * Map will contain 1 to batch_size plus these latest, i.e., * => previous 1+batch_size to map_size - batch_size will have been * removed by LRU
*/
key = 1 + __map_size(tgt_free);
end_key = key + __map_size(tgt_free); for (; key < end_key; key++) {
assert(!bpf_map_update_elem(lru_map_fd, &key, value,
BPF_NOEXIST));
assert(!bpf_map_update_elem(expected_map_fd, &key, value,
BPF_NOEXIST));
}
assert(map_equal(lru_map_fd, expected_map_fd));
close(expected_map_fd);
close(lru_map_fd);
printf("Pass\n");
}
/* Verify that insertions exceeding map size will recycle the oldest. * Verify that unreferenced elements are recycled before referenced.
*/ staticvoid test_lru_sanity2(int map_type, int map_flags, unsignedint tgt_free)
{ unsignedlonglong key, value[nr_cpus]; unsignedlonglong end_key; int lru_map_fd, expected_map_fd; unsignedint batch_size; unsignedint map_size; int next_cpu = 0;
if (map_flags & BPF_F_NO_COMMON_LRU) /* This test is only applicable to common LRU list */ return;
/* Any bpf_map_update_elem will require to acquire a new node * from LRU first. * * The local list is running out of free nodes. * It gets from the global LRU list which tries to * shrink the inactive list to get tgt_free * number of free nodes. * * Hence, the oldest key is removed from the LRU list.
*/
key = 1; if (map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
assert(!bpf_map_update_elem(lru_map_fd, &key, value,
BPF_NOEXIST));
assert(!bpf_map_delete_elem(lru_map_fd, &key));
} else {
assert(bpf_map_update_elem(lru_map_fd, &key, value,
BPF_EXIST));
}
/* Re-insert 1 to batch_size again and do a lookup immediately.
*/
end_key = 1 + batch_size;
value[0] = 4321; for (key = 1; key < end_key; key++) {
assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -ENOENT);
assert(!bpf_map_update_elem(lru_map_fd, &key, value,
BPF_NOEXIST));
assert(!bpf_map_lookup_elem_with_ref_bit(lru_map_fd, key, value));
assert(value[0] == 4321);
assert(!bpf_map_update_elem(expected_map_fd, &key, value,
BPF_NOEXIST));
}
value[0] = 1234;
/* Insert batch_size new elements */
key = 1 + __map_size(tgt_free);
end_key = key + batch_size; for (; key < end_key; key++) /* These newly added but not referenced keys will be * gone during the next LRU shrink.
*/
assert(!bpf_map_update_elem(lru_map_fd, &key, value,
BPF_NOEXIST));
/* Test the active/inactive list rotation * * Fill the whole map, deplete the free list. * Reference all except the last lru->target_free elements. * Insert lru->target_free new elements. This triggers one shrink. * Verify that the non-referenced elements are replaced.
*/ staticvoid test_lru_sanity3(int map_type, int map_flags, unsignedint tgt_free)
{ unsignedlonglong key, end_key, value[nr_cpus]; int lru_map_fd, expected_map_fd; unsignedint batch_size; unsignedint map_size; int next_cpu = 0;
if (map_flags & BPF_F_NO_COMMON_LRU) /* This test is only applicable to common LRU list */ return;
/* Cannot find the last key because it was removed by LRU */
assert(bpf_map_lookup_elem(map_fd, &last_key, value) == -ENOENT);
}
/* Test map with only one element */ staticvoid test_lru_sanity5(int map_type, int map_flags)
{ unsignedlonglong key, value[nr_cpus]; int next_cpu = 0; int map_fd;
close(map_fd); /* At least one key should be tested */
assert(key > 0);
printf("Pass\n");
}
/* Test list rotation for BPF_F_NO_COMMON_LRU map */ staticvoid test_lru_sanity6(int map_type, int map_flags, int tgt_free)
{ int lru_map_fd, expected_map_fd; unsignedlonglong key, value[nr_cpus]; unsignedint map_size = tgt_free * 2; int next_cpu = 0;
/* Make ref bit sticky for key: [1, tgt_free] */ for (stable_key = 1; stable_key <= tgt_free; stable_key++) { /* Mark the ref bit */
assert(!bpf_map_lookup_elem_with_ref_bit(lru_map_fd,
stable_key, value));
}
assert(!bpf_map_update_elem(lru_map_fd, &key, value,
BPF_NOEXIST));
}
/* check that key=3 is not found */
key = 3;
assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -ENOENT);
/* check that key=1 can be found and mark the ref bit to * stop LRU from removing key=1
*/
key = 1;
assert(!bpf_map_lookup_elem_with_ref_bit(lru_map_fd, key, value));
assert(value[0] == 1234);
/* check that key=2 can be found and do _not_ mark ref bit. * this will be evicted on next update.
*/
key = 2;
assert(!bpf_map_lookup_elem(lru_map_fd, &key, value));
assert(value[0] == 1234);
/* check that key=3 is not found */
key = 3;
assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -ENOENT);
/* check that key=1 can be found and do _not_ mark ref bit. * this will be evicted on next update.
*/
key = 1;
assert(!bpf_map_lookup_elem(lru_map_fd, &key, value));
assert(value[0] == 1234);
/* check that key=2 can be found and mark the ref bit to * stop LRU from removing key=2
*/
key = 2;
assert(!bpf_map_lookup_elem_with_ref_bit(lru_map_fd, key, value));
assert(value[0] == 1234);
/* key=1 has been removed from the LRU */
key = 1;
assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -ENOENT);
assert(map_equal(lru_map_fd, expected_map_fd));
close(expected_map_fd);
close(lru_map_fd);
printf("Pass\n");
}
int main(int argc, char **argv)
{ int map_types[] = {BPF_MAP_TYPE_LRU_HASH,
BPF_MAP_TYPE_LRU_PERCPU_HASH}; int map_flags[] = {0, BPF_F_NO_COMMON_LRU}; int t, f;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.