|
@@ -521,6 +521,126 @@ static void test_lpm_delete(void)
|
|
|
close(map_fd);
|
|
|
}
|
|
|
|
|
|
+static void test_lpm_get_next_key(void)
|
|
|
+{
|
|
|
+ struct bpf_lpm_trie_key *key_p, *next_key_p;
|
|
|
+ size_t key_size;
|
|
|
+ __u32 value = 0;
|
|
|
+ int map_fd;
|
|
|
+
|
|
|
+ key_size = sizeof(*key_p) + sizeof(__u32);
|
|
|
+ key_p = alloca(key_size);
|
|
|
+ next_key_p = alloca(key_size);
|
|
|
+
|
|
|
+ map_fd = bpf_create_map(BPF_MAP_TYPE_LPM_TRIE, key_size, sizeof(value),
|
|
|
+ 100, BPF_F_NO_PREALLOC);
|
|
|
+ assert(map_fd >= 0);
|
|
|
+
|
|
|
+ /* empty tree. get_next_key should return ENOENT */
|
|
|
+ assert(bpf_map_get_next_key(map_fd, NULL, key_p) == -1 &&
|
|
|
+ errno == ENOENT);
|
|
|
+
|
|
|
+ /* get and verify the first key, get the second one should fail. */
|
|
|
+ key_p->prefixlen = 16;
|
|
|
+ inet_pton(AF_INET, "192.168.0.0", key_p->data);
|
|
|
+ assert(bpf_map_update_elem(map_fd, key_p, &value, 0) == 0);
|
|
|
+
|
|
|
+ memset(key_p, 0, key_size);
|
|
|
+ assert(bpf_map_get_next_key(map_fd, NULL, key_p) == 0);
|
|
|
+ assert(key_p->prefixlen == 16 && key_p->data[0] == 192 &&
|
|
|
+ key_p->data[1] == 168);
|
|
|
+
|
|
|
+ assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == -1 &&
|
|
|
+ errno == ENOENT);
|
|
|
+
|
|
|
+ /* no exact matching key should get the first one in post order. */
|
|
|
+ key_p->prefixlen = 8;
|
|
|
+ assert(bpf_map_get_next_key(map_fd, NULL, key_p) == 0);
|
|
|
+ assert(key_p->prefixlen == 16 && key_p->data[0] == 192 &&
|
|
|
+ key_p->data[1] == 168);
|
|
|
+
|
|
|
+ /* add one more element (total two) */
|
|
|
+ key_p->prefixlen = 24;
|
|
|
+ inet_pton(AF_INET, "192.168.0.0", key_p->data);
|
|
|
+ assert(bpf_map_update_elem(map_fd, key_p, &value, 0) == 0);
|
|
|
+
|
|
|
+ memset(key_p, 0, key_size);
|
|
|
+ assert(bpf_map_get_next_key(map_fd, NULL, key_p) == 0);
|
|
|
+ assert(key_p->prefixlen == 24 && key_p->data[0] == 192 &&
|
|
|
+ key_p->data[1] == 168 && key_p->data[2] == 0);
|
|
|
+
|
|
|
+ memset(next_key_p, 0, key_size);
|
|
|
+ assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == 0);
|
|
|
+ assert(next_key_p->prefixlen == 16 && next_key_p->data[0] == 192 &&
|
|
|
+ next_key_p->data[1] == 168);
|
|
|
+
|
|
|
+ memcpy(key_p, next_key_p, key_size);
|
|
|
+ assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == -1 &&
|
|
|
+ errno == ENOENT);
|
|
|
+
|
|
|
+ /* Add one more element (total three) */
|
|
|
+ key_p->prefixlen = 24;
|
|
|
+ inet_pton(AF_INET, "192.168.128.0", key_p->data);
|
|
|
+ assert(bpf_map_update_elem(map_fd, key_p, &value, 0) == 0);
|
|
|
+
|
|
|
+ memset(key_p, 0, key_size);
|
|
|
+ assert(bpf_map_get_next_key(map_fd, NULL, key_p) == 0);
|
|
|
+ assert(key_p->prefixlen == 24 && key_p->data[0] == 192 &&
|
|
|
+ key_p->data[1] == 168 && key_p->data[2] == 0);
|
|
|
+
|
|
|
+ memset(next_key_p, 0, key_size);
|
|
|
+ assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == 0);
|
|
|
+ assert(next_key_p->prefixlen == 24 && next_key_p->data[0] == 192 &&
|
|
|
+ next_key_p->data[1] == 168 && next_key_p->data[2] == 128);
|
|
|
+
|
|
|
+ memcpy(key_p, next_key_p, key_size);
|
|
|
+ assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == 0);
|
|
|
+ assert(next_key_p->prefixlen == 16 && next_key_p->data[0] == 192 &&
|
|
|
+ next_key_p->data[1] == 168);
|
|
|
+
|
|
|
+ memcpy(key_p, next_key_p, key_size);
|
|
|
+ assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == -1 &&
|
|
|
+ errno == ENOENT);
|
|
|
+
|
|
|
+ /* Add one more element (total four) */
|
|
|
+ key_p->prefixlen = 24;
|
|
|
+ inet_pton(AF_INET, "192.168.1.0", key_p->data);
|
|
|
+ assert(bpf_map_update_elem(map_fd, key_p, &value, 0) == 0);
|
|
|
+
|
|
|
+ memset(key_p, 0, key_size);
|
|
|
+ assert(bpf_map_get_next_key(map_fd, NULL, key_p) == 0);
|
|
|
+ assert(key_p->prefixlen == 24 && key_p->data[0] == 192 &&
|
|
|
+ key_p->data[1] == 168 && key_p->data[2] == 0);
|
|
|
+
|
|
|
+ memset(next_key_p, 0, key_size);
|
|
|
+ assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == 0);
|
|
|
+ assert(next_key_p->prefixlen == 24 && next_key_p->data[0] == 192 &&
|
|
|
+ next_key_p->data[1] == 168 && next_key_p->data[2] == 1);
|
|
|
+
|
|
|
+ memcpy(key_p, next_key_p, key_size);
|
|
|
+ assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == 0);
|
|
|
+ assert(next_key_p->prefixlen == 24 && next_key_p->data[0] == 192 &&
|
|
|
+ next_key_p->data[1] == 168 && next_key_p->data[2] == 128);
|
|
|
+
|
|
|
+ memcpy(key_p, next_key_p, key_size);
|
|
|
+ assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == 0);
|
|
|
+ assert(next_key_p->prefixlen == 16 && next_key_p->data[0] == 192 &&
|
|
|
+ next_key_p->data[1] == 168);
|
|
|
+
|
|
|
+ memcpy(key_p, next_key_p, key_size);
|
|
|
+ assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == -1 &&
|
|
|
+ errno == ENOENT);
|
|
|
+
|
|
|
+ /* no exact matching key should return the first one in post order */
|
|
|
+ key_p->prefixlen = 22;
|
|
|
+ inet_pton(AF_INET, "192.168.1.0", key_p->data);
|
|
|
+ assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == 0);
|
|
|
+ assert(next_key_p->prefixlen == 24 && next_key_p->data[0] == 192 &&
|
|
|
+ next_key_p->data[1] == 168 && next_key_p->data[2] == 0);
|
|
|
+
|
|
|
+ close(map_fd);
|
|
|
+}
|
|
|
+
|
|
|
int main(void)
|
|
|
{
|
|
|
struct rlimit limit = { RLIM_INFINITY, RLIM_INFINITY };
|
|
@@ -545,6 +665,8 @@ int main(void)
|
|
|
|
|
|
test_lpm_delete();
|
|
|
|
|
|
+ test_lpm_get_next_key();
|
|
|
+
|
|
|
printf("test_lpm: OK\n");
|
|
|
return 0;
|
|
|
}
|