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 "test_progs.h"
8 #include "bpf_rlimit.h"
9 
10 int error_cnt, pass_cnt;
11 bool jit_enabled;
12 
13 struct ipv4_packet pkt_v4 = {
14 	.eth.h_proto = __bpf_constant_htons(ETH_P_IP),
15 	.iph.ihl = 5,
16 	.iph.protocol = IPPROTO_TCP,
17 	.iph.tot_len = __bpf_constant_htons(MAGIC_BYTES),
18 	.tcp.urg_ptr = 123,
19 	.tcp.doff = 5,
20 };
21 
22 struct ipv6_packet pkt_v6 = {
23 	.eth.h_proto = __bpf_constant_htons(ETH_P_IPV6),
24 	.iph.nexthdr = IPPROTO_TCP,
25 	.iph.payload_len = __bpf_constant_htons(MAGIC_BYTES),
26 	.tcp.urg_ptr = 123,
27 	.tcp.doff = 5,
28 };
29 
30 int bpf_find_map(const char *test, struct bpf_object *obj, const char *name)
31 {
32 	struct bpf_map *map;
33 
34 	map = bpf_object__find_map_by_name(obj, name);
35 	if (!map) {
36 		printf("%s:FAIL:map '%s' not found\n", test, name);
37 		error_cnt++;
38 		return -1;
39 	}
40 	return bpf_map__fd(map);
41 }
42 
43 static bool is_jit_enabled(void)
44 {
45 	const char *jit_sysctl = "/proc/sys/net/core/bpf_jit_enable";
46 	bool enabled = false;
47 	int sysctl_fd;
48 
49 	sysctl_fd = open(jit_sysctl, 0, O_RDONLY);
50 	if (sysctl_fd != -1) {
51 		char tmpc;
52 
53 		if (read(sysctl_fd, &tmpc, sizeof(tmpc)) == 1)
54 			enabled = (tmpc != '0');
55 		close(sysctl_fd);
56 	}
57 
58 	return enabled;
59 }
60 
61 int compare_map_keys(int map1_fd, int map2_fd)
62 {
63 	__u32 key, next_key;
64 	char val_buf[PERF_MAX_STACK_DEPTH *
65 		     sizeof(struct bpf_stack_build_id)];
66 	int err;
67 
68 	err = bpf_map_get_next_key(map1_fd, NULL, &key);
69 	if (err)
70 		return err;
71 	err = bpf_map_lookup_elem(map2_fd, &key, val_buf);
72 	if (err)
73 		return err;
74 
75 	while (bpf_map_get_next_key(map1_fd, &key, &next_key) == 0) {
76 		err = bpf_map_lookup_elem(map2_fd, &next_key, val_buf);
77 		if (err)
78 			return err;
79 
80 		key = next_key;
81 	}
82 	if (errno != ENOENT)
83 		return -1;
84 
85 	return 0;
86 }
87 
88 int compare_stack_ips(int smap_fd, int amap_fd, int stack_trace_len)
89 {
90 	__u32 key, next_key, *cur_key_p, *next_key_p;
91 	char *val_buf1, *val_buf2;
92 	int i, err = 0;
93 
94 	val_buf1 = malloc(stack_trace_len);
95 	val_buf2 = malloc(stack_trace_len);
96 	cur_key_p = NULL;
97 	next_key_p = &key;
98 	while (bpf_map_get_next_key(smap_fd, cur_key_p, next_key_p) == 0) {
99 		err = bpf_map_lookup_elem(smap_fd, next_key_p, val_buf1);
100 		if (err)
101 			goto out;
102 		err = bpf_map_lookup_elem(amap_fd, next_key_p, val_buf2);
103 		if (err)
104 			goto out;
105 		for (i = 0; i < stack_trace_len; i++) {
106 			if (val_buf1[i] != val_buf2[i]) {
107 				err = -1;
108 				goto out;
109 			}
110 		}
111 		key = *next_key_p;
112 		cur_key_p = &key;
113 		next_key_p = &next_key;
114 	}
115 	if (errno != ENOENT)
116 		err = -1;
117 
118 out:
119 	free(val_buf1);
120 	free(val_buf2);
121 	return err;
122 }
123 
124 int extract_build_id(char *build_id, size_t size)
125 {
126 	FILE *fp;
127 	char *line = NULL;
128 	size_t len = 0;
129 
130 	fp = popen("readelf -n ./urandom_read | grep 'Build ID'", "r");
131 	if (fp == NULL)
132 		return -1;
133 
134 	if (getline(&line, &len, fp) == -1)
135 		goto err;
136 	fclose(fp);
137 
138 	if (len > size)
139 		len = size;
140 	memcpy(build_id, line, len);
141 	build_id[len] = '\0';
142 	return 0;
143 err:
144 	fclose(fp);
145 	return -1;
146 }
147 
148 void *spin_lock_thread(void *arg)
149 {
150 	__u32 duration, retval;
151 	int err, prog_fd = *(u32 *) arg;
152 
153 	err = bpf_prog_test_run(prog_fd, 10000, &pkt_v4, sizeof(pkt_v4),
154 				NULL, NULL, &retval, &duration);
155 	CHECK(err || retval, "",
156 	      "err %d errno %d retval %d duration %d\n",
157 	      err, errno, retval, duration);
158 	pthread_exit(arg);
159 }
160 
161 #define DECLARE
162 #include <prog_tests/tests.h>
163 #undef DECLARE
164 
165 int main(void)
166 {
167 	srand(time(NULL));
168 
169 	jit_enabled = is_jit_enabled();
170 
171 #define CALL
172 #include <prog_tests/tests.h>
173 #undef CALL
174 
175 	printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, error_cnt);
176 	return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS;
177 }
178