aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2019-05-15 21:28:44 -0400
committerDavid S. Miller <davem@davemloft.net>2019-05-15 21:28:44 -0400
commitc7d5ec26ea4adf450d9ab2b794e7735761a93af1 (patch)
treea2c0e405c6cd4c90dcd3eda665e1488a98564341
parent858f5017446764e8bca0b29589a3b164186ae471 (diff)
parent5fa2ca7c4a3fc176f31b495e1a704862d8188b53 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
Daniel Borkmann says: ==================== pull-request: bpf 2019-05-16 The following pull-request contains BPF updates for your *net* tree. The main changes are: 1) Fix a use after free in __dev_map_entry_free(), from Eric. 2) Several sockmap related bug fixes: a splat in strparser if it was never initialized, remove duplicate ingress msg list purging which can race, fix msg->sg.size accounting upon skb to msg conversion, and last but not least fix a timeout bug in tcp_bpf_wait_data(), from John. 3) Fix LRU map to avoid messing with eviction heuristics upon syscall lookup, e.g. map walks from user space side will then lead to eviction of just recently created entries on updates as it would mark all map entries, from Daniel. 4) Don't bail out when libbpf feature probing fails. Also various smaller fixes to flow_dissector test, from Stanislav. 5) Fix missing brackets for BTF_INT_OFFSET() in UAPI, from Gary. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--Documentation/bpf/btf.rst2
-rw-r--r--include/linux/bpf.h1
-rw-r--r--include/uapi/linux/btf.h2
-rw-r--r--kernel/bpf/devmap.c3
-rw-r--r--kernel/bpf/hashtab.c23
-rw-r--r--kernel/bpf/syscall.c5
-rw-r--r--kernel/trace/bpf_trace.c5
-rw-r--r--net/core/skmsg.c7
-rw-r--r--net/ipv4/tcp_bpf.c7
-rw-r--r--tools/include/uapi/linux/btf.h2
-rw-r--r--tools/lib/bpf/libbpf.c2
-rw-r--r--tools/testing/selftests/bpf/prog_tests/flow_dissector.c9
-rw-r--r--tools/testing/selftests/bpf/test_lru_map.c288
13 files changed, 321 insertions, 35 deletions
diff --git a/Documentation/bpf/btf.rst b/Documentation/bpf/btf.rst
index 8820360d00da..35d83e24dbdb 100644
--- a/Documentation/bpf/btf.rst
+++ b/Documentation/bpf/btf.rst
@@ -131,7 +131,7 @@ The following sections detail encoding of each kind.
131``btf_type`` is followed by a ``u32`` with the following bits arrangement:: 131``btf_type`` is followed by a ``u32`` with the following bits arrangement::
132 132
133 #define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24) 133 #define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24)
134 #define BTF_INT_OFFSET(VAL) (((VAL & 0x00ff0000)) >> 16) 134 #define BTF_INT_OFFSET(VAL) (((VAL) & 0x00ff0000) >> 16)
135 #define BTF_INT_BITS(VAL) ((VAL) & 0x000000ff) 135 #define BTF_INT_BITS(VAL) ((VAL) & 0x000000ff)
136 136
137The ``BTF_INT_ENCODING`` has the following attributes:: 137The ``BTF_INT_ENCODING`` has the following attributes::
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 59631dd0777c..4fb3aa2dc975 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -36,6 +36,7 @@ struct bpf_map_ops {
36 void (*map_free)(struct bpf_map *map); 36 void (*map_free)(struct bpf_map *map);
37 int (*map_get_next_key)(struct bpf_map *map, void *key, void *next_key); 37 int (*map_get_next_key)(struct bpf_map *map, void *key, void *next_key);
38 void (*map_release_uref)(struct bpf_map *map); 38 void (*map_release_uref)(struct bpf_map *map);
39 void *(*map_lookup_elem_sys_only)(struct bpf_map *map, void *key);
39 40
40 /* funcs callable from userspace and from eBPF programs */ 41 /* funcs callable from userspace and from eBPF programs */
41 void *(*map_lookup_elem)(struct bpf_map *map, void *key); 42 void *(*map_lookup_elem)(struct bpf_map *map, void *key);
diff --git a/include/uapi/linux/btf.h b/include/uapi/linux/btf.h
index 9310652ca4f9..63ae4a39e58b 100644
--- a/include/uapi/linux/btf.h
+++ b/include/uapi/linux/btf.h
@@ -83,7 +83,7 @@ struct btf_type {
83 * is the 32 bits arrangement: 83 * is the 32 bits arrangement:
84 */ 84 */
85#define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24) 85#define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24)
86#define BTF_INT_OFFSET(VAL) (((VAL & 0x00ff0000)) >> 16) 86#define BTF_INT_OFFSET(VAL) (((VAL) & 0x00ff0000) >> 16)
87#define BTF_INT_BITS(VAL) ((VAL) & 0x000000ff) 87#define BTF_INT_BITS(VAL) ((VAL) & 0x000000ff)
88 88
89/* Attributes stored in the BTF_INT_ENCODING */ 89/* Attributes stored in the BTF_INT_ENCODING */
diff --git a/kernel/bpf/devmap.c b/kernel/bpf/devmap.c
index 191b79948424..1e525d70f833 100644
--- a/kernel/bpf/devmap.c
+++ b/kernel/bpf/devmap.c
@@ -164,6 +164,9 @@ static void dev_map_free(struct bpf_map *map)
164 bpf_clear_redirect_map(map); 164 bpf_clear_redirect_map(map);
165 synchronize_rcu(); 165 synchronize_rcu();
166 166
167 /* Make sure prior __dev_map_entry_free() have completed. */
168 rcu_barrier();
169
167 /* To ensure all pending flush operations have completed wait for flush 170 /* To ensure all pending flush operations have completed wait for flush
168 * bitmap to indicate all flush_needed bits to be zero on _all_ cpus. 171 * bitmap to indicate all flush_needed bits to be zero on _all_ cpus.
169 * Because the above synchronize_rcu() ensures the map is disconnected 172 * Because the above synchronize_rcu() ensures the map is disconnected
diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
index 192d32e77db3..0f2708fde5f7 100644
--- a/kernel/bpf/hashtab.c
+++ b/kernel/bpf/hashtab.c
@@ -527,18 +527,30 @@ static u32 htab_map_gen_lookup(struct bpf_map *map, struct bpf_insn *insn_buf)
527 return insn - insn_buf; 527 return insn - insn_buf;
528} 528}
529 529
530static void *htab_lru_map_lookup_elem(struct bpf_map *map, void *key) 530static __always_inline void *__htab_lru_map_lookup_elem(struct bpf_map *map,
531 void *key, const bool mark)
531{ 532{
532 struct htab_elem *l = __htab_map_lookup_elem(map, key); 533 struct htab_elem *l = __htab_map_lookup_elem(map, key);
533 534
534 if (l) { 535 if (l) {
535 bpf_lru_node_set_ref(&l->lru_node); 536 if (mark)
537 bpf_lru_node_set_ref(&l->lru_node);
536 return l->key + round_up(map->key_size, 8); 538 return l->key + round_up(map->key_size, 8);
537 } 539 }
538 540
539 return NULL; 541 return NULL;
540} 542}
541 543
544static void *htab_lru_map_lookup_elem(struct bpf_map *map, void *key)
545{
546 return __htab_lru_map_lookup_elem(map, key, true);
547}
548
549static void *htab_lru_map_lookup_elem_sys(struct bpf_map *map, void *key)
550{
551 return __htab_lru_map_lookup_elem(map, key, false);
552}
553
542static u32 htab_lru_map_gen_lookup(struct bpf_map *map, 554static u32 htab_lru_map_gen_lookup(struct bpf_map *map,
543 struct bpf_insn *insn_buf) 555 struct bpf_insn *insn_buf)
544{ 556{
@@ -1250,6 +1262,7 @@ const struct bpf_map_ops htab_lru_map_ops = {
1250 .map_free = htab_map_free, 1262 .map_free = htab_map_free,
1251 .map_get_next_key = htab_map_get_next_key, 1263 .map_get_next_key = htab_map_get_next_key,
1252 .map_lookup_elem = htab_lru_map_lookup_elem, 1264 .map_lookup_elem = htab_lru_map_lookup_elem,
1265 .map_lookup_elem_sys_only = htab_lru_map_lookup_elem_sys,
1253 .map_update_elem = htab_lru_map_update_elem, 1266 .map_update_elem = htab_lru_map_update_elem,
1254 .map_delete_elem = htab_lru_map_delete_elem, 1267 .map_delete_elem = htab_lru_map_delete_elem,
1255 .map_gen_lookup = htab_lru_map_gen_lookup, 1268 .map_gen_lookup = htab_lru_map_gen_lookup,
@@ -1281,7 +1294,6 @@ static void *htab_lru_percpu_map_lookup_elem(struct bpf_map *map, void *key)
1281 1294
1282int bpf_percpu_hash_copy(struct bpf_map *map, void *key, void *value) 1295int bpf_percpu_hash_copy(struct bpf_map *map, void *key, void *value)
1283{ 1296{
1284 struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
1285 struct htab_elem *l; 1297 struct htab_elem *l;
1286 void __percpu *pptr; 1298 void __percpu *pptr;
1287 int ret = -ENOENT; 1299 int ret = -ENOENT;
@@ -1297,8 +1309,9 @@ int bpf_percpu_hash_copy(struct bpf_map *map, void *key, void *value)
1297 l = __htab_map_lookup_elem(map, key); 1309 l = __htab_map_lookup_elem(map, key);
1298 if (!l) 1310 if (!l)
1299 goto out; 1311 goto out;
1300 if (htab_is_lru(htab)) 1312 /* We do not mark LRU map element here in order to not mess up
1301 bpf_lru_node_set_ref(&l->lru_node); 1313 * eviction heuristics when user space does a map walk.
1314 */
1302 pptr = htab_elem_get_ptr(l, map->key_size); 1315 pptr = htab_elem_get_ptr(l, map->key_size);
1303 for_each_possible_cpu(cpu) { 1316 for_each_possible_cpu(cpu) {
1304 bpf_long_memcpy(value + off, 1317 bpf_long_memcpy(value + off,
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index ad3ccf82f31d..cb5440b02e82 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -808,7 +808,10 @@ static int map_lookup_elem(union bpf_attr *attr)
808 err = map->ops->map_peek_elem(map, value); 808 err = map->ops->map_peek_elem(map, value);
809 } else { 809 } else {
810 rcu_read_lock(); 810 rcu_read_lock();
811 ptr = map->ops->map_lookup_elem(map, key); 811 if (map->ops->map_lookup_elem_sys_only)
812 ptr = map->ops->map_lookup_elem_sys_only(map, key);
813 else
814 ptr = map->ops->map_lookup_elem(map, key);
812 if (IS_ERR(ptr)) { 815 if (IS_ERR(ptr)) {
813 err = PTR_ERR(ptr); 816 err = PTR_ERR(ptr);
814 } else if (!ptr) { 817 } else if (!ptr) {
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index b496ffdf5f36..f92d6ad5e080 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -1297,7 +1297,8 @@ int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id,
1297} 1297}
1298 1298
1299#ifdef CONFIG_MODULES 1299#ifdef CONFIG_MODULES
1300int bpf_event_notify(struct notifier_block *nb, unsigned long op, void *module) 1300static int bpf_event_notify(struct notifier_block *nb, unsigned long op,
1301 void *module)
1301{ 1302{
1302 struct bpf_trace_module *btm, *tmp; 1303 struct bpf_trace_module *btm, *tmp;
1303 struct module *mod = module; 1304 struct module *mod = module;
@@ -1336,7 +1337,7 @@ static struct notifier_block bpf_module_nb = {
1336 .notifier_call = bpf_event_notify, 1337 .notifier_call = bpf_event_notify,
1337}; 1338};
1338 1339
1339int __init bpf_event_init(void) 1340static int __init bpf_event_init(void)
1340{ 1341{
1341 register_module_notifier(&bpf_module_nb); 1342 register_module_notifier(&bpf_module_nb);
1342 return 0; 1343 return 0;
diff --git a/net/core/skmsg.c b/net/core/skmsg.c
index cc94d921476c..93bffaad2135 100644
--- a/net/core/skmsg.c
+++ b/net/core/skmsg.c
@@ -411,6 +411,7 @@ static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb)
411 sk_mem_charge(sk, skb->len); 411 sk_mem_charge(sk, skb->len);
412 copied = skb->len; 412 copied = skb->len;
413 msg->sg.start = 0; 413 msg->sg.start = 0;
414 msg->sg.size = copied;
414 msg->sg.end = num_sge == MAX_MSG_FRAGS ? 0 : num_sge; 415 msg->sg.end = num_sge == MAX_MSG_FRAGS ? 0 : num_sge;
415 msg->skb = skb; 416 msg->skb = skb;
416 417
@@ -554,8 +555,10 @@ static void sk_psock_destroy_deferred(struct work_struct *gc)
554 struct sk_psock *psock = container_of(gc, struct sk_psock, gc); 555 struct sk_psock *psock = container_of(gc, struct sk_psock, gc);
555 556
556 /* No sk_callback_lock since already detached. */ 557 /* No sk_callback_lock since already detached. */
557 strp_stop(&psock->parser.strp); 558
558 strp_done(&psock->parser.strp); 559 /* Parser has been stopped */
560 if (psock->progs.skb_parser)
561 strp_done(&psock->parser.strp);
559 562
560 cancel_work_sync(&psock->work); 563 cancel_work_sync(&psock->work);
561 564
diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c
index 1bb7321a256d..3d1e15401384 100644
--- a/net/ipv4/tcp_bpf.c
+++ b/net/ipv4/tcp_bpf.c
@@ -27,7 +27,10 @@ static int tcp_bpf_wait_data(struct sock *sk, struct sk_psock *psock,
27 int flags, long timeo, int *err) 27 int flags, long timeo, int *err)
28{ 28{
29 DEFINE_WAIT_FUNC(wait, woken_wake_function); 29 DEFINE_WAIT_FUNC(wait, woken_wake_function);
30 int ret; 30 int ret = 0;
31
32 if (!timeo)
33 return ret;
31 34
32 add_wait_queue(sk_sleep(sk), &wait); 35 add_wait_queue(sk_sleep(sk), &wait);
33 sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk); 36 sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
@@ -528,8 +531,6 @@ static void tcp_bpf_remove(struct sock *sk, struct sk_psock *psock)
528{ 531{
529 struct sk_psock_link *link; 532 struct sk_psock_link *link;
530 533
531 sk_psock_cork_free(psock);
532 __sk_psock_purge_ingress_msg(psock);
533 while ((link = sk_psock_link_pop(psock))) { 534 while ((link = sk_psock_link_pop(psock))) {
534 sk_psock_unlink(sk, link); 535 sk_psock_unlink(sk, link);
535 sk_psock_free_link(link); 536 sk_psock_free_link(link);
diff --git a/tools/include/uapi/linux/btf.h b/tools/include/uapi/linux/btf.h
index 9310652ca4f9..63ae4a39e58b 100644
--- a/tools/include/uapi/linux/btf.h
+++ b/tools/include/uapi/linux/btf.h
@@ -83,7 +83,7 @@ struct btf_type {
83 * is the 32 bits arrangement: 83 * is the 32 bits arrangement:
84 */ 84 */
85#define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24) 85#define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24)
86#define BTF_INT_OFFSET(VAL) (((VAL & 0x00ff0000)) >> 16) 86#define BTF_INT_OFFSET(VAL) (((VAL) & 0x00ff0000) >> 16)
87#define BTF_INT_BITS(VAL) ((VAL) & 0x000000ff) 87#define BTF_INT_BITS(VAL) ((VAL) & 0x000000ff)
88 88
89/* Attributes stored in the BTF_INT_ENCODING */ 89/* Attributes stored in the BTF_INT_ENCODING */
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 7e3b79d7c25f..3562b6ef5fdc 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -1696,7 +1696,7 @@ bpf_object__probe_caps(struct bpf_object *obj)
1696 for (i = 0; i < ARRAY_SIZE(probe_fn); i++) { 1696 for (i = 0; i < ARRAY_SIZE(probe_fn); i++) {
1697 ret = probe_fn[i](obj); 1697 ret = probe_fn[i](obj);
1698 if (ret < 0) 1698 if (ret < 0)
1699 return ret; 1699 pr_debug("Probe #%d failed with %d.\n", i, ret);
1700 } 1700 }
1701 1701
1702 return 0; 1702 return 0;
diff --git a/tools/testing/selftests/bpf/prog_tests/flow_dissector.c b/tools/testing/selftests/bpf/prog_tests/flow_dissector.c
index 8b54adfd6264..fbd1d88a6095 100644
--- a/tools/testing/selftests/bpf/prog_tests/flow_dissector.c
+++ b/tools/testing/selftests/bpf/prog_tests/flow_dissector.c
@@ -242,12 +242,12 @@ void test_flow_dissector(void)
242 */ 242 */
243 243
244 err = bpf_prog_attach(prog_fd, 0, BPF_FLOW_DISSECTOR, 0); 244 err = bpf_prog_attach(prog_fd, 0, BPF_FLOW_DISSECTOR, 0);
245 CHECK(err, "bpf_prog_attach", "err %d errno %d", err, errno); 245 CHECK(err, "bpf_prog_attach", "err %d errno %d\n", err, errno);
246 246
247 tap_fd = create_tap("tap0"); 247 tap_fd = create_tap("tap0");
248 CHECK(tap_fd < 0, "create_tap", "tap_fd %d errno %d", tap_fd, errno); 248 CHECK(tap_fd < 0, "create_tap", "tap_fd %d errno %d\n", tap_fd, errno);
249 err = ifup("tap0"); 249 err = ifup("tap0");
250 CHECK(err, "ifup", "err %d errno %d", err, errno); 250 CHECK(err, "ifup", "err %d errno %d\n", err, errno);
251 251
252 for (i = 0; i < ARRAY_SIZE(tests); i++) { 252 for (i = 0; i < ARRAY_SIZE(tests); i++) {
253 struct bpf_flow_keys flow_keys = {}; 253 struct bpf_flow_keys flow_keys = {};
@@ -255,7 +255,7 @@ void test_flow_dissector(void)
255 __u32 key = 0; 255 __u32 key = 0;
256 256
257 err = tx_tap(tap_fd, &tests[i].pkt, sizeof(tests[i].pkt)); 257 err = tx_tap(tap_fd, &tests[i].pkt, sizeof(tests[i].pkt));
258 CHECK(err < 0, "tx_tap", "err %d errno %d", err, errno); 258 CHECK(err < 0, "tx_tap", "err %d errno %d\n", err, errno);
259 259
260 err = bpf_map_lookup_elem(keys_fd, &key, &flow_keys); 260 err = bpf_map_lookup_elem(keys_fd, &key, &flow_keys);
261 CHECK_ATTR(err, tests[i].name, "bpf_map_lookup_elem %d\n", err); 261 CHECK_ATTR(err, tests[i].name, "bpf_map_lookup_elem %d\n", err);
@@ -264,5 +264,6 @@ void test_flow_dissector(void)
264 CHECK_FLOW_KEYS(tests[i].name, flow_keys, tests[i].keys); 264 CHECK_FLOW_KEYS(tests[i].name, flow_keys, tests[i].keys);
265 } 265 }
266 266
267 bpf_prog_detach(prog_fd, BPF_FLOW_DISSECTOR);
267 bpf_object__close(obj); 268 bpf_object__close(obj);
268} 269}
diff --git a/tools/testing/selftests/bpf/test_lru_map.c b/tools/testing/selftests/bpf/test_lru_map.c
index 781c7de343be..1b25a7e348dc 100644
--- a/tools/testing/selftests/bpf/test_lru_map.c
+++ b/tools/testing/selftests/bpf/test_lru_map.c
@@ -18,9 +18,11 @@
18#include <sys/wait.h> 18#include <sys/wait.h>
19 19
20#include <bpf/bpf.h> 20#include <bpf/bpf.h>
21#include <bpf/libbpf.h>
21 22
22#include "bpf_util.h" 23#include "bpf_util.h"
23#include "bpf_rlimit.h" 24#include "bpf_rlimit.h"
25#include "../../../include/linux/filter.h"
24 26
25#define LOCAL_FREE_TARGET (128) 27#define LOCAL_FREE_TARGET (128)
26#define PERCPU_FREE_TARGET (4) 28#define PERCPU_FREE_TARGET (4)
@@ -40,6 +42,68 @@ static int create_map(int map_type, int map_flags, unsigned int size)
40 return map_fd; 42 return map_fd;
41} 43}
42 44
45static int bpf_map_lookup_elem_with_ref_bit(int fd, unsigned long long key,
46 void *value)
47{
48 struct bpf_load_program_attr prog;
49 struct bpf_create_map_attr map;
50 struct bpf_insn insns[] = {
51 BPF_LD_MAP_VALUE(BPF_REG_9, 0, 0),
52 BPF_LD_MAP_FD(BPF_REG_1, fd),
53 BPF_LD_IMM64(BPF_REG_3, key),
54 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
55 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
56 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, 0),
57 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
58 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
59 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
60 BPF_STX_MEM(BPF_DW, BPF_REG_9, BPF_REG_1, 0),
61 BPF_MOV64_IMM(BPF_REG_0, 42),
62 BPF_JMP_IMM(BPF_JA, 0, 0, 1),
63 BPF_MOV64_IMM(BPF_REG_0, 1),
64 BPF_EXIT_INSN(),
65 };
66 __u8 data[64] = {};
67 int mfd, pfd, ret, zero = 0;
68 __u32 retval = 0;
69
70 memset(&map, 0, sizeof(map));
71 map.map_type = BPF_MAP_TYPE_ARRAY;
72 map.key_size = sizeof(int);
73 map.value_size = sizeof(unsigned long long);
74 map.max_entries = 1;
75
76 mfd = bpf_create_map_xattr(&map);
77 if (mfd < 0)
78 return -1;
79
80 insns[0].imm = mfd;
81
82 memset(&prog, 0, sizeof(prog));
83 prog.prog_type = BPF_PROG_TYPE_SCHED_CLS;
84 prog.insns = insns;
85 prog.insns_cnt = ARRAY_SIZE(insns);
86 prog.license = "GPL";
87
88 pfd = bpf_load_program_xattr(&prog, NULL, 0);
89 if (pfd < 0) {
90 close(mfd);
91 return -1;
92 }
93
94 ret = bpf_prog_test_run(pfd, 1, data, sizeof(data),
95 NULL, NULL, &retval, NULL);
96 if (ret < 0 || retval != 42) {
97 ret = -1;
98 } else {
99 assert(!bpf_map_lookup_elem(mfd, &zero, value));
100 ret = 0;
101 }
102 close(pfd);
103 close(mfd);
104 return ret;
105}
106
43static int map_subset(int map0, int map1) 107static int map_subset(int map0, int map1)
44{ 108{
45 unsigned long long next_key = 0; 109 unsigned long long next_key = 0;
@@ -87,7 +151,7 @@ static int sched_next_online(int pid, int *next_to_try)
87 return ret; 151 return ret;
88} 152}
89 153
90/* Size of the LRU amp is 2 154/* Size of the LRU map is 2
91 * Add key=1 (+1 key) 155 * Add key=1 (+1 key)
92 * Add key=2 (+1 key) 156 * Add key=2 (+1 key)
93 * Lookup Key=1 157 * Lookup Key=1
@@ -157,7 +221,7 @@ static void test_lru_sanity0(int map_type, int map_flags)
157 * stop LRU from removing key=1 221 * stop LRU from removing key=1
158 */ 222 */
159 key = 1; 223 key = 1;
160 assert(!bpf_map_lookup_elem(lru_map_fd, &key, value)); 224 assert(!bpf_map_lookup_elem_with_ref_bit(lru_map_fd, key, value));
161 assert(value[0] == 1234); 225 assert(value[0] == 1234);
162 226
163 key = 3; 227 key = 3;
@@ -167,7 +231,8 @@ static void test_lru_sanity0(int map_type, int map_flags)
167 231
168 /* key=2 has been removed from the LRU */ 232 /* key=2 has been removed from the LRU */
169 key = 2; 233 key = 2;
170 assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -1); 234 assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -1 &&
235 errno == ENOENT);
171 236
172 assert(map_equal(lru_map_fd, expected_map_fd)); 237 assert(map_equal(lru_map_fd, expected_map_fd));
173 238
@@ -221,7 +286,7 @@ static void test_lru_sanity1(int map_type, int map_flags, unsigned int tgt_free)
221 /* Lookup 1 to tgt_free/2 */ 286 /* Lookup 1 to tgt_free/2 */
222 end_key = 1 + batch_size; 287 end_key = 1 + batch_size;
223 for (key = 1; key < end_key; key++) { 288 for (key = 1; key < end_key; key++) {
224 assert(!bpf_map_lookup_elem(lru_map_fd, &key, value)); 289 assert(!bpf_map_lookup_elem_with_ref_bit(lru_map_fd, key, value));
225 assert(!bpf_map_update_elem(expected_map_fd, &key, value, 290 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
226 BPF_NOEXIST)); 291 BPF_NOEXIST));
227 } 292 }
@@ -322,10 +387,11 @@ static void test_lru_sanity2(int map_type, int map_flags, unsigned int tgt_free)
322 end_key = 1 + batch_size; 387 end_key = 1 + batch_size;
323 value[0] = 4321; 388 value[0] = 4321;
324 for (key = 1; key < end_key; key++) { 389 for (key = 1; key < end_key; key++) {
325 assert(bpf_map_lookup_elem(lru_map_fd, &key, value)); 390 assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -1 &&
391 errno == ENOENT);
326 assert(!bpf_map_update_elem(lru_map_fd, &key, value, 392 assert(!bpf_map_update_elem(lru_map_fd, &key, value,
327 BPF_NOEXIST)); 393 BPF_NOEXIST));
328 assert(!bpf_map_lookup_elem(lru_map_fd, &key, value)); 394 assert(!bpf_map_lookup_elem_with_ref_bit(lru_map_fd, key, value));
329 assert(value[0] == 4321); 395 assert(value[0] == 4321);
330 assert(!bpf_map_update_elem(expected_map_fd, &key, value, 396 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
331 BPF_NOEXIST)); 397 BPF_NOEXIST));
@@ -404,7 +470,7 @@ static void test_lru_sanity3(int map_type, int map_flags, unsigned int tgt_free)
404 /* Lookup key 1 to tgt_free*3/2 */ 470 /* Lookup key 1 to tgt_free*3/2 */
405 end_key = tgt_free + batch_size; 471 end_key = tgt_free + batch_size;
406 for (key = 1; key < end_key; key++) { 472 for (key = 1; key < end_key; key++) {
407 assert(!bpf_map_lookup_elem(lru_map_fd, &key, value)); 473 assert(!bpf_map_lookup_elem_with_ref_bit(lru_map_fd, key, value));
408 assert(!bpf_map_update_elem(expected_map_fd, &key, value, 474 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
409 BPF_NOEXIST)); 475 BPF_NOEXIST));
410 } 476 }
@@ -463,7 +529,7 @@ static void test_lru_sanity4(int map_type, int map_flags, unsigned int tgt_free)
463 assert(bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST)); 529 assert(bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST));
464 530
465 for (key = 1; key <= tgt_free; key++) { 531 for (key = 1; key <= tgt_free; key++) {
466 assert(!bpf_map_lookup_elem(lru_map_fd, &key, value)); 532 assert(!bpf_map_lookup_elem_with_ref_bit(lru_map_fd, key, value));
467 assert(!bpf_map_update_elem(expected_map_fd, &key, value, 533 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
468 BPF_NOEXIST)); 534 BPF_NOEXIST));
469 } 535 }
@@ -494,16 +560,16 @@ static void do_test_lru_sanity5(unsigned long long last_key, int map_fd)
494 unsigned long long key, value[nr_cpus]; 560 unsigned long long key, value[nr_cpus];
495 561
496 /* Ensure the last key inserted by previous CPU can be found */ 562 /* Ensure the last key inserted by previous CPU can be found */
497 assert(!bpf_map_lookup_elem(map_fd, &last_key, value)); 563 assert(!bpf_map_lookup_elem_with_ref_bit(map_fd, last_key, value));
498
499 value[0] = 1234; 564 value[0] = 1234;
500 565
501 key = last_key + 1; 566 key = last_key + 1;
502 assert(!bpf_map_update_elem(map_fd, &key, value, BPF_NOEXIST)); 567 assert(!bpf_map_update_elem(map_fd, &key, value, BPF_NOEXIST));
503 assert(!bpf_map_lookup_elem(map_fd, &key, value)); 568 assert(!bpf_map_lookup_elem_with_ref_bit(map_fd, key, value));
504 569
505 /* Cannot find the last key because it was removed by LRU */ 570 /* Cannot find the last key because it was removed by LRU */
506 assert(bpf_map_lookup_elem(map_fd, &last_key, value)); 571 assert(bpf_map_lookup_elem(map_fd, &last_key, value) == -1 &&
572 errno == ENOENT);
507} 573}
508 574
509/* Test map with only one element */ 575/* Test map with only one element */
@@ -590,8 +656,8 @@ static void test_lru_sanity6(int map_type, int map_flags, int tgt_free)
590 /* Make ref bit sticky for key: [1, tgt_free] */ 656 /* Make ref bit sticky for key: [1, tgt_free] */
591 for (stable_key = 1; stable_key <= tgt_free; stable_key++) { 657 for (stable_key = 1; stable_key <= tgt_free; stable_key++) {
592 /* Mark the ref bit */ 658 /* Mark the ref bit */
593 assert(!bpf_map_lookup_elem(lru_map_fd, &stable_key, 659 assert(!bpf_map_lookup_elem_with_ref_bit(lru_map_fd,
594 value)); 660 stable_key, value));
595 } 661 }
596 assert(!bpf_map_update_elem(lru_map_fd, &key, value, 662 assert(!bpf_map_update_elem(lru_map_fd, &key, value,
597 BPF_NOEXIST)); 663 BPF_NOEXIST));
@@ -612,6 +678,198 @@ static void test_lru_sanity6(int map_type, int map_flags, int tgt_free)
612 printf("Pass\n"); 678 printf("Pass\n");
613} 679}
614 680
681/* Size of the LRU map is 2
682 * Add key=1 (+1 key)
683 * Add key=2 (+1 key)
684 * Lookup Key=1 (datapath)
685 * Lookup Key=2 (syscall)
686 * Add Key=3
687 * => Key=2 will be removed by LRU
688 * Iterate map. Only found key=1 and key=3
689 */
690static void test_lru_sanity7(int map_type, int map_flags)
691{
692 unsigned long long key, value[nr_cpus];
693 int lru_map_fd, expected_map_fd;
694 int next_cpu = 0;
695
696 printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type,
697 map_flags);
698
699 assert(sched_next_online(0, &next_cpu) != -1);
700
701 if (map_flags & BPF_F_NO_COMMON_LRU)
702 lru_map_fd = create_map(map_type, map_flags, 2 * nr_cpus);
703 else
704 lru_map_fd = create_map(map_type, map_flags, 2);
705 assert(lru_map_fd != -1);
706
707 expected_map_fd = create_map(BPF_MAP_TYPE_HASH, 0, 2);
708 assert(expected_map_fd != -1);
709
710 value[0] = 1234;
711
712 /* insert key=1 element */
713
714 key = 1;
715 assert(!bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST));
716 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
717 BPF_NOEXIST));
718
719 /* BPF_NOEXIST means: add new element if it doesn't exist */
720 assert(bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST) == -1
721 /* key=1 already exists */
722 && errno == EEXIST);
723
724 /* insert key=2 element */
725
726 /* check that key=2 is not found */
727 key = 2;
728 assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -1 &&
729 errno == ENOENT);
730
731 /* BPF_EXIST means: update existing element */
732 assert(bpf_map_update_elem(lru_map_fd, &key, value, BPF_EXIST) == -1 &&
733 /* key=2 is not there */
734 errno == ENOENT);
735
736 assert(!bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST));
737
738 /* insert key=3 element */
739
740 /* check that key=3 is not found */
741 key = 3;
742 assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -1 &&
743 errno == ENOENT);
744
745 /* check that key=1 can be found and mark the ref bit to
746 * stop LRU from removing key=1
747 */
748 key = 1;
749 assert(!bpf_map_lookup_elem_with_ref_bit(lru_map_fd, key, value));
750 assert(value[0] == 1234);
751
752 /* check that key=2 can be found and do _not_ mark ref bit.
753 * this will be evicted on next update.
754 */
755 key = 2;
756 assert(!bpf_map_lookup_elem(lru_map_fd, &key, value));
757 assert(value[0] == 1234);
758
759 key = 3;
760 assert(!bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST));
761 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
762 BPF_NOEXIST));
763
764 /* key=2 has been removed from the LRU */
765 key = 2;
766 assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -1 &&
767 errno == ENOENT);
768
769 assert(map_equal(lru_map_fd, expected_map_fd));
770
771 close(expected_map_fd);
772 close(lru_map_fd);
773
774 printf("Pass\n");
775}
776
777/* Size of the LRU map is 2
778 * Add key=1 (+1 key)
779 * Add key=2 (+1 key)
780 * Lookup Key=1 (syscall)
781 * Lookup Key=2 (datapath)
782 * Add Key=3
783 * => Key=1 will be removed by LRU
784 * Iterate map. Only found key=2 and key=3
785 */
786static void test_lru_sanity8(int map_type, int map_flags)
787{
788 unsigned long long key, value[nr_cpus];
789 int lru_map_fd, expected_map_fd;
790 int next_cpu = 0;
791
792 printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type,
793 map_flags);
794
795 assert(sched_next_online(0, &next_cpu) != -1);
796
797 if (map_flags & BPF_F_NO_COMMON_LRU)
798 lru_map_fd = create_map(map_type, map_flags, 2 * nr_cpus);
799 else
800 lru_map_fd = create_map(map_type, map_flags, 2);
801 assert(lru_map_fd != -1);
802
803 expected_map_fd = create_map(BPF_MAP_TYPE_HASH, 0, 2);
804 assert(expected_map_fd != -1);
805
806 value[0] = 1234;
807
808 /* insert key=1 element */
809
810 key = 1;
811 assert(!bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST));
812
813 /* BPF_NOEXIST means: add new element if it doesn't exist */
814 assert(bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST) == -1
815 /* key=1 already exists */
816 && errno == EEXIST);
817
818 /* insert key=2 element */
819
820 /* check that key=2 is not found */
821 key = 2;
822 assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -1 &&
823 errno == ENOENT);
824
825 /* BPF_EXIST means: update existing element */
826 assert(bpf_map_update_elem(lru_map_fd, &key, value, BPF_EXIST) == -1 &&
827 /* key=2 is not there */
828 errno == ENOENT);
829
830 assert(!bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST));
831 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
832 BPF_NOEXIST));
833
834 /* insert key=3 element */
835
836 /* check that key=3 is not found */
837 key = 3;
838 assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -1 &&
839 errno == ENOENT);
840
841 /* check that key=1 can be found and do _not_ mark ref bit.
842 * this will be evicted on next update.
843 */
844 key = 1;
845 assert(!bpf_map_lookup_elem(lru_map_fd, &key, value));
846 assert(value[0] == 1234);
847
848 /* check that key=2 can be found and mark the ref bit to
849 * stop LRU from removing key=2
850 */
851 key = 2;
852 assert(!bpf_map_lookup_elem_with_ref_bit(lru_map_fd, key, value));
853 assert(value[0] == 1234);
854
855 key = 3;
856 assert(!bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST));
857 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
858 BPF_NOEXIST));
859
860 /* key=1 has been removed from the LRU */
861 key = 1;
862 assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -1 &&
863 errno == ENOENT);
864
865 assert(map_equal(lru_map_fd, expected_map_fd));
866
867 close(expected_map_fd);
868 close(lru_map_fd);
869
870 printf("Pass\n");
871}
872
615int main(int argc, char **argv) 873int main(int argc, char **argv)
616{ 874{
617 int map_types[] = {BPF_MAP_TYPE_LRU_HASH, 875 int map_types[] = {BPF_MAP_TYPE_LRU_HASH,
@@ -637,6 +895,8 @@ int main(int argc, char **argv)
637 test_lru_sanity4(map_types[t], map_flags[f], tgt_free); 895 test_lru_sanity4(map_types[t], map_flags[f], tgt_free);
638 test_lru_sanity5(map_types[t], map_flags[f]); 896 test_lru_sanity5(map_types[t], map_flags[f]);
639 test_lru_sanity6(map_types[t], map_flags[f], tgt_free); 897 test_lru_sanity6(map_types[t], map_flags[f], tgt_free);
898 test_lru_sanity7(map_types[t], map_flags[f]);
899 test_lru_sanity8(map_types[t], map_flags[f]);
640 900
641 printf("\n"); 901 printf("\n");
642 } 902 }