1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2017 Facebook
5 #include <sys/resource.h>
6 #include <sys/socket.h>
14 #include <bpf/libbpf.h>
18 #define PORT_A (map_fd[0])
19 #define PORT_H (map_fd[1])
20 #define REG_RESULT_H (map_fd[2])
21 #define INLINE_RESULT_H (map_fd[3])
22 #define A_OF_PORT_A (map_fd[4]) /* Test case #0 */
23 #define H_OF_PORT_A (map_fd[5]) /* Test case #1 */
24 #define H_OF_PORT_H (map_fd[6]) /* Test case #2 */
26 static const char * const test_names
[] = {
32 #define NR_TESTS (sizeof(test_names) / sizeof(*test_names))
34 static void check_map_id(int inner_map_fd
, int map_in_map_fd
, uint32_t key
)
36 struct bpf_map_info info
= {};
37 uint32_t info_len
= sizeof(info
);
40 ret
= bpf_obj_get_info_by_fd(inner_map_fd
, &info
, &info_len
);
43 ret
= bpf_map_lookup_elem(map_in_map_fd
, &key
, &id
);
45 assert(id
== info
.id
);
48 static void populate_map(uint32_t port_key
, int magic_result
)
52 ret
= bpf_map_update_elem(PORT_A
, &port_key
, &magic_result
, BPF_ANY
);
55 ret
= bpf_map_update_elem(PORT_H
, &port_key
, &magic_result
,
59 ret
= bpf_map_update_elem(A_OF_PORT_A
, &port_key
, &PORT_A
, BPF_ANY
);
61 check_map_id(PORT_A
, A_OF_PORT_A
, port_key
);
63 ret
= bpf_map_update_elem(H_OF_PORT_A
, &port_key
, &PORT_A
, BPF_NOEXIST
);
65 check_map_id(PORT_A
, H_OF_PORT_A
, port_key
);
67 ret
= bpf_map_update_elem(H_OF_PORT_H
, &port_key
, &PORT_H
, BPF_NOEXIST
);
69 check_map_id(PORT_H
, H_OF_PORT_H
, port_key
);
72 static void test_map_in_map(void)
74 struct sockaddr_in6 in6
= { .sin6_family
= AF_INET6
};
75 uint32_t result_key
= 0, port_key
;
76 int result
, inline_result
;
77 int magic_result
= 0xfaceb00c;
81 port_key
= rand() & 0x00FF;
82 populate_map(port_key
, magic_result
);
84 in6
.sin6_addr
.s6_addr16
[0] = 0xdead;
85 in6
.sin6_addr
.s6_addr16
[1] = 0xbeef;
86 in6
.sin6_port
= port_key
;
88 for (i
= 0; i
< NR_TESTS
; i
++) {
89 printf("%s: ", test_names
[i
]);
91 in6
.sin6_addr
.s6_addr16
[7] = i
;
92 ret
= connect(-1, (struct sockaddr
*)&in6
, sizeof(in6
));
93 assert(ret
== -1 && errno
== EBADF
);
95 ret
= bpf_map_lookup_elem(REG_RESULT_H
, &result_key
, &result
);
98 ret
= bpf_map_lookup_elem(INLINE_RESULT_H
, &result_key
,
102 if (result
!= magic_result
|| inline_result
!= magic_result
) {
103 printf("Error. result:%d inline_result:%d\n",
104 result
, inline_result
);
108 bpf_map_delete_elem(REG_RESULT_H
, &result_key
);
109 bpf_map_delete_elem(INLINE_RESULT_H
, &result_key
);
115 int main(int argc
, char **argv
)
117 struct bpf_link
*link
= NULL
;
118 struct bpf_program
*prog
;
119 struct bpf_object
*obj
;
122 snprintf(filename
, sizeof(filename
), "%s_kern.o", argv
[0]);
123 obj
= bpf_object__open_file(filename
, NULL
);
124 if (libbpf_get_error(obj
)) {
125 fprintf(stderr
, "ERROR: opening BPF object file failed\n");
129 prog
= bpf_object__find_program_by_name(obj
, "trace_sys_connect");
131 printf("finding a prog in obj file failed\n");
135 /* load BPF program */
136 if (bpf_object__load(obj
)) {
137 fprintf(stderr
, "ERROR: loading BPF object file failed\n");
141 map_fd
[0] = bpf_object__find_map_fd_by_name(obj
, "port_a");
142 map_fd
[1] = bpf_object__find_map_fd_by_name(obj
, "port_h");
143 map_fd
[2] = bpf_object__find_map_fd_by_name(obj
, "reg_result_h");
144 map_fd
[3] = bpf_object__find_map_fd_by_name(obj
, "inline_result_h");
145 map_fd
[4] = bpf_object__find_map_fd_by_name(obj
, "a_of_port_a");
146 map_fd
[5] = bpf_object__find_map_fd_by_name(obj
, "h_of_port_a");
147 map_fd
[6] = bpf_object__find_map_fd_by_name(obj
, "h_of_port_h");
148 if (map_fd
[0] < 0 || map_fd
[1] < 0 || map_fd
[2] < 0 ||
149 map_fd
[3] < 0 || map_fd
[4] < 0 || map_fd
[5] < 0 || map_fd
[6] < 0) {
150 fprintf(stderr
, "ERROR: finding a map in obj file failed\n");
154 link
= bpf_program__attach(prog
);
155 if (libbpf_get_error(link
)) {
156 fprintf(stderr
, "ERROR: bpf_program__attach failed\n");
164 bpf_link__destroy(link
);
165 bpf_object__close(obj
);