1/* Copyright (c) 2017 Facebook
2 *
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of version 2 of the GNU General Public
5 * License as published by the Free Software Foundation.
6 */
7#include <stdio.h>
8#include <unistd.h>
9#include <errno.h>
10#include <string.h>
11#include <assert.h>
12#include <stdlib.h>
13#include <time.h>
14
15#include <linux/types.h>
16typedef __u16 __sum16;
17#include <arpa/inet.h>
18#include <linux/if_ether.h>
19#include <linux/if_packet.h>
20#include <linux/ip.h>
21#include <linux/ipv6.h>
22#include <linux/tcp.h>
23#include <linux/filter.h>
24#include <linux/unistd.h>
25
26#include <sys/wait.h>
27#include <sys/resource.h>
28#include <sys/types.h>
29#include <fcntl.h>
30
31#include <linux/bpf.h>
32#include <linux/err.h>
33#include <bpf/bpf.h>
34#include <bpf/libbpf.h>
35#include "test_iptunnel_common.h"
36#include "bpf_util.h"
37#include "bpf_endian.h"
38
39static int error_cnt, pass_cnt;
40
41#define MAGIC_BYTES 123
42
43/* ipv4 test vector */
44static struct {
45	struct ethhdr eth;
46	struct iphdr iph;
47	struct tcphdr tcp;
48} __packed pkt_v4 = {
49	.eth.h_proto = bpf_htons(ETH_P_IP),
50	.iph.ihl = 5,
51	.iph.protocol = 6,
52	.iph.tot_len = bpf_htons(MAGIC_BYTES),
53	.tcp.urg_ptr = 123,
54};
55
56/* ipv6 test vector */
57static struct {
58	struct ethhdr eth;
59	struct ipv6hdr iph;
60	struct tcphdr tcp;
61} __packed pkt_v6 = {
62	.eth.h_proto = bpf_htons(ETH_P_IPV6),
63	.iph.nexthdr = 6,
64	.iph.payload_len = bpf_htons(MAGIC_BYTES),
65	.tcp.urg_ptr = 123,
66};
67
68#define CHECK(condition, tag, format...) ({				\
69	int __ret = !!(condition);					\
70	if (__ret) {							\
71		error_cnt++;						\
72		printf("%s:FAIL:%s ", __func__, tag);			\
73		printf(format);						\
74	} else {							\
75		pass_cnt++;						\
76		printf("%s:PASS:%s %d nsec\n", __func__, tag, duration);\
77	}								\
78	__ret;								\
79})
80
81static int bpf_find_map(const char *test, struct bpf_object *obj,
82			const char *name)
83{
84	struct bpf_map *map;
85
86	map = bpf_object__find_map_by_name(obj, name);
87	if (!map) {
88		printf("%s:FAIL:map '%s' not found\n", test, name);
89		error_cnt++;
90		return -1;
91	}
92	return bpf_map__fd(map);
93}
94
95static void test_pkt_access(void)
96{
97	const char *file = "./test_pkt_access.o";
98	struct bpf_object *obj;
99	__u32 duration, retval;
100	int err, prog_fd;
101
102	err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
103	if (err) {
104		error_cnt++;
105		return;
106	}
107
108	err = bpf_prog_test_run(prog_fd, 100000, &pkt_v4, sizeof(pkt_v4),
109				NULL, NULL, &retval, &duration);
110	CHECK(err || errno || retval, "ipv4",
111	      "err %d errno %d retval %d duration %d\n",
112	      err, errno, retval, duration);
113
114	err = bpf_prog_test_run(prog_fd, 100000, &pkt_v6, sizeof(pkt_v6),
115				NULL, NULL, &retval, &duration);
116	CHECK(err || errno || retval, "ipv6",
117	      "err %d errno %d retval %d duration %d\n",
118	      err, errno, retval, duration);
119	bpf_object__close(obj);
120}
121
122static void test_xdp(void)
123{
124	struct vip key4 = {.protocol = 6, .family = AF_INET};
125	struct vip key6 = {.protocol = 6, .family = AF_INET6};
126	struct iptnl_info value4 = {.family = AF_INET};
127	struct iptnl_info value6 = {.family = AF_INET6};
128	const char *file = "./test_xdp.o";
129	struct bpf_object *obj;
130	char buf[128];
131	struct ipv6hdr *iph6 = (void *)buf + sizeof(struct ethhdr);
132	struct iphdr *iph = (void *)buf + sizeof(struct ethhdr);
133	__u32 duration, retval, size;
134	int err, prog_fd, map_fd;
135
136	err = bpf_prog_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd);
137	if (err) {
138		error_cnt++;
139		return;
140	}
141
142	map_fd = bpf_find_map(__func__, obj, "vip2tnl");
143	if (map_fd < 0)
144		goto out;
145	bpf_map_update_elem(map_fd, &key4, &value4, 0);
146	bpf_map_update_elem(map_fd, &key6, &value6, 0);
147
148	err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4),
149				buf, &size, &retval, &duration);
150
151	CHECK(err || errno || retval != XDP_TX || size != 74 ||
152	      iph->protocol != IPPROTO_IPIP, "ipv4",
153	      "err %d errno %d retval %d size %d\n",
154	      err, errno, retval, size);
155
156	err = bpf_prog_test_run(prog_fd, 1, &pkt_v6, sizeof(pkt_v6),
157				buf, &size, &retval, &duration);
158	CHECK(err || errno || retval != XDP_TX || size != 114 ||
159	      iph6->nexthdr != IPPROTO_IPV6, "ipv6",
160	      "err %d errno %d retval %d size %d\n",
161	      err, errno, retval, size);
162out:
163	bpf_object__close(obj);
164}
165
166#define MAGIC_VAL 0x1234
167#define NUM_ITER 100000
168#define VIP_NUM 5
169
170static void test_l4lb(void)
171{
172	unsigned int nr_cpus = bpf_num_possible_cpus();
173	const char *file = "./test_l4lb.o";
174	struct vip key = {.protocol = 6};
175	struct vip_meta {
176		__u32 flags;
177		__u32 vip_num;
178	} value = {.vip_num = VIP_NUM};
179	__u32 stats_key = VIP_NUM;
180	struct vip_stats {
181		__u64 bytes;
182		__u64 pkts;
183	} stats[nr_cpus];
184	struct real_definition {
185		union {
186			__be32 dst;
187			__be32 dstv6[4];
188		};
189		__u8 flags;
190	} real_def = {.dst = MAGIC_VAL};
191	__u32 ch_key = 11, real_num = 3;
192	__u32 duration, retval, size;
193	int err, i, prog_fd, map_fd;
194	__u64 bytes = 0, pkts = 0;
195	struct bpf_object *obj;
196	char buf[128];
197	u32 *magic = (u32 *)buf;
198
199	err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
200	if (err) {
201		error_cnt++;
202		return;
203	}
204
205	map_fd = bpf_find_map(__func__, obj, "vip_map");
206	if (map_fd < 0)
207		goto out;
208	bpf_map_update_elem(map_fd, &key, &value, 0);
209
210	map_fd = bpf_find_map(__func__, obj, "ch_rings");
211	if (map_fd < 0)
212		goto out;
213	bpf_map_update_elem(map_fd, &ch_key, &real_num, 0);
214
215	map_fd = bpf_find_map(__func__, obj, "reals");
216	if (map_fd < 0)
217		goto out;
218	bpf_map_update_elem(map_fd, &real_num, &real_def, 0);
219
220	err = bpf_prog_test_run(prog_fd, NUM_ITER, &pkt_v4, sizeof(pkt_v4),
221				buf, &size, &retval, &duration);
222	CHECK(err || errno || retval != 7/*TC_ACT_REDIRECT*/ || size != 54 ||
223	      *magic != MAGIC_VAL, "ipv4",
224	      "err %d errno %d retval %d size %d magic %x\n",
225	      err, errno, retval, size, *magic);
226
227	err = bpf_prog_test_run(prog_fd, NUM_ITER, &pkt_v6, sizeof(pkt_v6),
228				buf, &size, &retval, &duration);
229	CHECK(err || errno || retval != 7/*TC_ACT_REDIRECT*/ || size != 74 ||
230	      *magic != MAGIC_VAL, "ipv6",
231	      "err %d errno %d retval %d size %d magic %x\n",
232	      err, errno, retval, size, *magic);
233
234	map_fd = bpf_find_map(__func__, obj, "stats");
235	if (map_fd < 0)
236		goto out;
237	bpf_map_lookup_elem(map_fd, &stats_key, stats);
238	for (i = 0; i < nr_cpus; i++) {
239		bytes += stats[i].bytes;
240		pkts += stats[i].pkts;
241	}
242	if (bytes != MAGIC_BYTES * NUM_ITER * 2 || pkts != NUM_ITER * 2) {
243		error_cnt++;
244		printf("test_l4lb:FAIL:stats %lld %lld\n", bytes, pkts);
245	}
246out:
247	bpf_object__close(obj);
248}
249
250static void test_tcp_estats(void)
251{
252	const char *file = "./test_tcp_estats.o";
253	int err, prog_fd;
254	struct bpf_object *obj;
255	__u32 duration = 0;
256
257	err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd);
258	CHECK(err, "", "err %d errno %d\n", err, errno);
259	if (err) {
260		error_cnt++;
261		return;
262	}
263
264	bpf_object__close(obj);
265}
266
267static inline __u64 ptr_to_u64(const void *ptr)
268{
269	return (__u64) (unsigned long) ptr;
270}
271
272static void test_bpf_obj_id(void)
273{
274	const __u64 array_magic_value = 0xfaceb00c;
275	const __u32 array_key = 0;
276	const int nr_iters = 2;
277	const char *file = "./test_obj_id.o";
278	const char *jit_sysctl = "/proc/sys/net/core/bpf_jit_enable";
279	const char *expected_prog_name = "test_obj_id";
280	const char *expected_map_name = "test_map_id";
281	const __u64 nsec_per_sec = 1000000000;
282
283	struct bpf_object *objs[nr_iters];
284	int prog_fds[nr_iters], map_fds[nr_iters];
285	/* +1 to test for the info_len returned by kernel */
286	struct bpf_prog_info prog_infos[nr_iters + 1];
287	struct bpf_map_info map_infos[nr_iters + 1];
288	/* Each prog only uses one map. +1 to test nr_map_ids
289	 * returned by kernel.
290	 */
291	__u32 map_ids[nr_iters + 1];
292	char jited_insns[128], xlated_insns[128], zeros[128];
293	__u32 i, next_id, info_len, nr_id_found, duration = 0;
294	struct timespec real_time_ts, boot_time_ts;
295	int sysctl_fd, jit_enabled = 0, err = 0;
296	__u64 array_value;
297	uid_t my_uid = getuid();
298	time_t now, load_time;
299
300	sysctl_fd = open(jit_sysctl, 0, O_RDONLY);
301	if (sysctl_fd != -1) {
302		char tmpc;
303
304		if (read(sysctl_fd, &tmpc, sizeof(tmpc)) == 1)
305			jit_enabled = (tmpc != '0');
306		close(sysctl_fd);
307	}
308
309	err = bpf_prog_get_fd_by_id(0);
310	CHECK(err >= 0 || errno != ENOENT,
311	      "get-fd-by-notexist-prog-id", "err %d errno %d\n", err, errno);
312
313	err = bpf_map_get_fd_by_id(0);
314	CHECK(err >= 0 || errno != ENOENT,
315	      "get-fd-by-notexist-map-id", "err %d errno %d\n", err, errno);
316
317	for (i = 0; i < nr_iters; i++)
318		objs[i] = NULL;
319
320	/* Check bpf_obj_get_info_by_fd() */
321	bzero(zeros, sizeof(zeros));
322	for (i = 0; i < nr_iters; i++) {
323		now = time(NULL);
324		err = bpf_prog_load(file, BPF_PROG_TYPE_SOCKET_FILTER,
325				    &objs[i], &prog_fds[i]);
326		/* test_obj_id.o is a dumb prog. It should never fail
327		 * to load.
328		 */
329		if (err)
330			error_cnt++;
331		assert(!err);
332
333		/* Insert a magic value to the map */
334		map_fds[i] = bpf_find_map(__func__, objs[i], "test_map_id");
335		assert(map_fds[i] >= 0);
336		err = bpf_map_update_elem(map_fds[i], &array_key,
337					  &array_magic_value, 0);
338		assert(!err);
339
340		/* Check getting map info */
341		info_len = sizeof(struct bpf_map_info) * 2;
342		bzero(&map_infos[i], info_len);
343		err = bpf_obj_get_info_by_fd(map_fds[i], &map_infos[i],
344					     &info_len);
345		if (CHECK(err ||
346			  map_infos[i].type != BPF_MAP_TYPE_ARRAY ||
347			  map_infos[i].key_size != sizeof(__u32) ||
348			  map_infos[i].value_size != sizeof(__u64) ||
349			  map_infos[i].max_entries != 1 ||
350			  map_infos[i].map_flags != 0 ||
351			  info_len != sizeof(struct bpf_map_info) ||
352			  strcmp((char *)map_infos[i].name, expected_map_name),
353			  "get-map-info(fd)",
354			  "err %d errno %d type %d(%d) info_len %u(%Zu) key_size %u value_size %u max_entries %u map_flags %X name %s(%s)\n",
355			  err, errno,
356			  map_infos[i].type, BPF_MAP_TYPE_ARRAY,
357			  info_len, sizeof(struct bpf_map_info),
358			  map_infos[i].key_size,
359			  map_infos[i].value_size,
360			  map_infos[i].max_entries,
361			  map_infos[i].map_flags,
362			  map_infos[i].name, expected_map_name))
363			goto done;
364
365		/* Check getting prog info */
366		info_len = sizeof(struct bpf_prog_info) * 2;
367		bzero(&prog_infos[i], info_len);
368		bzero(jited_insns, sizeof(jited_insns));
369		bzero(xlated_insns, sizeof(xlated_insns));
370		prog_infos[i].jited_prog_insns = ptr_to_u64(jited_insns);
371		prog_infos[i].jited_prog_len = sizeof(jited_insns);
372		prog_infos[i].xlated_prog_insns = ptr_to_u64(xlated_insns);
373		prog_infos[i].xlated_prog_len = sizeof(xlated_insns);
374		prog_infos[i].map_ids = ptr_to_u64(map_ids + i);
375		prog_infos[i].nr_map_ids = 2;
376		err = clock_gettime(CLOCK_REALTIME, &real_time_ts);
377		assert(!err);
378		err = clock_gettime(CLOCK_BOOTTIME, &boot_time_ts);
379		assert(!err);
380		err = bpf_obj_get_info_by_fd(prog_fds[i], &prog_infos[i],
381					     &info_len);
382		load_time = (real_time_ts.tv_sec - boot_time_ts.tv_sec)
383			+ (prog_infos[i].load_time / nsec_per_sec);
384		if (CHECK(err ||
385			  prog_infos[i].type != BPF_PROG_TYPE_SOCKET_FILTER ||
386			  info_len != sizeof(struct bpf_prog_info) ||
387			  (jit_enabled && !prog_infos[i].jited_prog_len) ||
388			  (jit_enabled &&
389			   !memcmp(jited_insns, zeros, sizeof(zeros))) ||
390			  !prog_infos[i].xlated_prog_len ||
391			  !memcmp(xlated_insns, zeros, sizeof(zeros)) ||
392			  load_time < now - 60 || load_time > now + 60 ||
393			  prog_infos[i].created_by_uid != my_uid ||
394			  prog_infos[i].nr_map_ids != 1 ||
395			  *(int *)prog_infos[i].map_ids != map_infos[i].id ||
396			  strcmp((char *)prog_infos[i].name, expected_prog_name),
397			  "get-prog-info(fd)",
398			  "err %d errno %d i %d type %d(%d) info_len %u(%Zu) jit_enabled %d jited_prog_len %u xlated_prog_len %u jited_prog %d xlated_prog %d load_time %lu(%lu) uid %u(%u) nr_map_ids %u(%u) map_id %u(%u) name %s(%s)\n",
399			  err, errno, i,
400			  prog_infos[i].type, BPF_PROG_TYPE_SOCKET_FILTER,
401			  info_len, sizeof(struct bpf_prog_info),
402			  jit_enabled,
403			  prog_infos[i].jited_prog_len,
404			  prog_infos[i].xlated_prog_len,
405			  !!memcmp(jited_insns, zeros, sizeof(zeros)),
406			  !!memcmp(xlated_insns, zeros, sizeof(zeros)),
407			  load_time, now,
408			  prog_infos[i].created_by_uid, my_uid,
409			  prog_infos[i].nr_map_ids, 1,
410			  *(int *)prog_infos[i].map_ids, map_infos[i].id,
411			  prog_infos[i].name, expected_prog_name))
412			goto done;
413	}
414
415	/* Check bpf_prog_get_next_id() */
416	nr_id_found = 0;
417	next_id = 0;
418	while (!bpf_prog_get_next_id(next_id, &next_id)) {
419		struct bpf_prog_info prog_info = {};
420		__u32 saved_map_id;
421		int prog_fd;
422
423		info_len = sizeof(prog_info);
424
425		prog_fd = bpf_prog_get_fd_by_id(next_id);
426		if (prog_fd < 0 && errno == ENOENT)
427			/* The bpf_prog is in the dead row */
428			continue;
429		if (CHECK(prog_fd < 0, "get-prog-fd(next_id)",
430			  "prog_fd %d next_id %d errno %d\n",
431			  prog_fd, next_id, errno))
432			break;
433
434		for (i = 0; i < nr_iters; i++)
435			if (prog_infos[i].id == next_id)
436				break;
437
438		if (i == nr_iters)
439			continue;
440
441		nr_id_found++;
442
443		/* Negative test:
444		 * prog_info.nr_map_ids = 1
445		 * prog_info.map_ids = NULL
446		 */
447		prog_info.nr_map_ids = 1;
448		err = bpf_obj_get_info_by_fd(prog_fd, &prog_info, &info_len);
449		if (CHECK(!err || errno != EFAULT,
450			  "get-prog-fd-bad-nr-map-ids", "err %d errno %d(%d)",
451			  err, errno, EFAULT))
452			break;
453		bzero(&prog_info, sizeof(prog_info));
454		info_len = sizeof(prog_info);
455
456		saved_map_id = *(int *)(prog_infos[i].map_ids);
457		prog_info.map_ids = prog_infos[i].map_ids;
458		prog_info.nr_map_ids = 2;
459		err = bpf_obj_get_info_by_fd(prog_fd, &prog_info, &info_len);
460		prog_infos[i].jited_prog_insns = 0;
461		prog_infos[i].xlated_prog_insns = 0;
462		CHECK(err || info_len != sizeof(struct bpf_prog_info) ||
463		      memcmp(&prog_info, &prog_infos[i], info_len) ||
464		      *(int *)prog_info.map_ids != saved_map_id,
465		      "get-prog-info(next_id->fd)",
466		      "err %d errno %d info_len %u(%Zu) memcmp %d map_id %u(%u)\n",
467		      err, errno, info_len, sizeof(struct bpf_prog_info),
468		      memcmp(&prog_info, &prog_infos[i], info_len),
469		      *(int *)prog_info.map_ids, saved_map_id);
470		close(prog_fd);
471	}
472	CHECK(nr_id_found != nr_iters,
473	      "check total prog id found by get_next_id",
474	      "nr_id_found %u(%u)\n",
475	      nr_id_found, nr_iters);
476
477	/* Check bpf_map_get_next_id() */
478	nr_id_found = 0;
479	next_id = 0;
480	while (!bpf_map_get_next_id(next_id, &next_id)) {
481		struct bpf_map_info map_info = {};
482		int map_fd;
483
484		info_len = sizeof(map_info);
485
486		map_fd = bpf_map_get_fd_by_id(next_id);
487		if (map_fd < 0 && errno == ENOENT)
488			/* The bpf_map is in the dead row */
489			continue;
490		if (CHECK(map_fd < 0, "get-map-fd(next_id)",
491			  "map_fd %d next_id %u errno %d\n",
492			  map_fd, next_id, errno))
493			break;
494
495		for (i = 0; i < nr_iters; i++)
496			if (map_infos[i].id == next_id)
497				break;
498
499		if (i == nr_iters)
500			continue;
501
502		nr_id_found++;
503
504		err = bpf_map_lookup_elem(map_fd, &array_key, &array_value);
505		assert(!err);
506
507		err = bpf_obj_get_info_by_fd(map_fd, &map_info, &info_len);
508		CHECK(err || info_len != sizeof(struct bpf_map_info) ||
509		      memcmp(&map_info, &map_infos[i], info_len) ||
510		      array_value != array_magic_value,
511		      "check get-map-info(next_id->fd)",
512		      "err %d errno %d info_len %u(%Zu) memcmp %d array_value %llu(%llu)\n",
513		      err, errno, info_len, sizeof(struct bpf_map_info),
514		      memcmp(&map_info, &map_infos[i], info_len),
515		      array_value, array_magic_value);
516
517		close(map_fd);
518	}
519	CHECK(nr_id_found != nr_iters,
520	      "check total map id found by get_next_id",
521	      "nr_id_found %u(%u)\n",
522	      nr_id_found, nr_iters);
523
524done:
525	for (i = 0; i < nr_iters; i++)
526		bpf_object__close(objs[i]);
527}
528
529static void test_pkt_md_access(void)
530{
531	const char *file = "./test_pkt_md_access.o";
532	struct bpf_object *obj;
533	__u32 duration, retval;
534	int err, prog_fd;
535
536	err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
537	if (err) {
538		error_cnt++;
539		return;
540	}
541
542	err = bpf_prog_test_run(prog_fd, 10, &pkt_v4, sizeof(pkt_v4),
543				NULL, NULL, &retval, &duration);
544	CHECK(err || retval, "",
545	      "err %d errno %d retval %d duration %d\n",
546	      err, errno, retval, duration);
547
548	bpf_object__close(obj);
549}
550
551static void test_obj_name(void)
552{
553	struct {
554		const char *name;
555		int success;
556		int expected_errno;
557	} tests[] = {
558		{ "", 1, 0 },
559		{ "_123456789ABCDE", 1, 0 },
560		{ "_123456789ABCDEF", 0, EINVAL },
561		{ "_123456789ABCD\n", 0, EINVAL },
562	};
563	struct bpf_insn prog[] = {
564		BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
565		BPF_EXIT_INSN(),
566	};
567	__u32 duration = 0;
568	int i;
569
570	for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
571		size_t name_len = strlen(tests[i].name) + 1;
572		union bpf_attr attr;
573		size_t ncopy;
574		int fd;
575
576		/* test different attr.prog_name during BPF_PROG_LOAD */
577		ncopy = name_len < sizeof(attr.prog_name) ?
578			name_len : sizeof(attr.prog_name);
579		bzero(&attr, sizeof(attr));
580		attr.prog_type = BPF_PROG_TYPE_SCHED_CLS;
581		attr.insn_cnt = 2;
582		attr.insns = ptr_to_u64(prog);
583		attr.license = ptr_to_u64("");
584		memcpy(attr.prog_name, tests[i].name, ncopy);
585
586		fd = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
587		CHECK((tests[i].success && fd < 0) ||
588		      (!tests[i].success && fd != -1) ||
589		      (!tests[i].success && errno != tests[i].expected_errno),
590		      "check-bpf-prog-name",
591		      "fd %d(%d) errno %d(%d)\n",
592		       fd, tests[i].success, errno, tests[i].expected_errno);
593
594		if (fd != -1)
595			close(fd);
596
597		/* test different attr.map_name during BPF_MAP_CREATE */
598		ncopy = name_len < sizeof(attr.map_name) ?
599			name_len : sizeof(attr.map_name);
600		bzero(&attr, sizeof(attr));
601		attr.map_type = BPF_MAP_TYPE_ARRAY;
602		attr.key_size = 4;
603		attr.value_size = 4;
604		attr.max_entries = 1;
605		attr.map_flags = 0;
606		memcpy(attr.map_name, tests[i].name, ncopy);
607		fd = syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));
608		CHECK((tests[i].success && fd < 0) ||
609		      (!tests[i].success && fd != -1) ||
610		      (!tests[i].success && errno != tests[i].expected_errno),
611		      "check-bpf-map-name",
612		      "fd %d(%d) errno %d(%d)\n",
613		      fd, tests[i].success, errno, tests[i].expected_errno);
614
615		if (fd != -1)
616			close(fd);
617	}
618}
619
620int main(void)
621{
622	struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
623
624	setrlimit(RLIMIT_MEMLOCK, &rinf);
625
626	test_pkt_access();
627	test_xdp();
628	test_l4lb();
629	test_tcp_estats();
630	test_bpf_obj_id();
631	test_pkt_md_access();
632	test_obj_name();
633
634	printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, error_cnt);
635	return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS;
636}
637