Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2017 Facebook
0004  */
0005 #include <sys/socket.h>
0006 #include <arpa/inet.h>
0007 #include <stdint.h>
0008 #include <assert.h>
0009 #include <errno.h>
0010 #include <stdlib.h>
0011 #include <stdio.h>
0012 #include <bpf/bpf.h>
0013 #include <bpf/libbpf.h>
0014 
0015 #include "bpf_util.h"
0016 
0017 static int map_fd[7];
0018 
0019 #define PORT_A      (map_fd[0])
0020 #define PORT_H      (map_fd[1])
0021 #define REG_RESULT_H    (map_fd[2])
0022 #define INLINE_RESULT_H (map_fd[3])
0023 #define A_OF_PORT_A (map_fd[4]) /* Test case #0 */
0024 #define H_OF_PORT_A (map_fd[5]) /* Test case #1 */
0025 #define H_OF_PORT_H (map_fd[6]) /* Test case #2 */
0026 
0027 static const char * const test_names[] = {
0028     "Array of Array",
0029     "Hash of Array",
0030     "Hash of Hash",
0031 };
0032 
0033 #define NR_TESTS ARRAY_SIZE(test_names)
0034 
0035 static void check_map_id(int inner_map_fd, int map_in_map_fd, uint32_t key)
0036 {
0037     struct bpf_map_info info = {};
0038     uint32_t info_len = sizeof(info);
0039     int ret, id;
0040 
0041     ret = bpf_obj_get_info_by_fd(inner_map_fd, &info, &info_len);
0042     assert(!ret);
0043 
0044     ret = bpf_map_lookup_elem(map_in_map_fd, &key, &id);
0045     assert(!ret);
0046     assert(id == info.id);
0047 }
0048 
0049 static void populate_map(uint32_t port_key, int magic_result)
0050 {
0051     int ret;
0052 
0053     ret = bpf_map_update_elem(PORT_A, &port_key, &magic_result, BPF_ANY);
0054     assert(!ret);
0055 
0056     ret = bpf_map_update_elem(PORT_H, &port_key, &magic_result,
0057                   BPF_NOEXIST);
0058     assert(!ret);
0059 
0060     ret = bpf_map_update_elem(A_OF_PORT_A, &port_key, &PORT_A, BPF_ANY);
0061     assert(!ret);
0062     check_map_id(PORT_A, A_OF_PORT_A, port_key);
0063 
0064     ret = bpf_map_update_elem(H_OF_PORT_A, &port_key, &PORT_A, BPF_NOEXIST);
0065     assert(!ret);
0066     check_map_id(PORT_A, H_OF_PORT_A, port_key);
0067 
0068     ret = bpf_map_update_elem(H_OF_PORT_H, &port_key, &PORT_H, BPF_NOEXIST);
0069     assert(!ret);
0070     check_map_id(PORT_H, H_OF_PORT_H, port_key);
0071 }
0072 
0073 static void test_map_in_map(void)
0074 {
0075     struct sockaddr_in6 in6 = { .sin6_family = AF_INET6 };
0076     uint32_t result_key = 0, port_key;
0077     int result, inline_result;
0078     int magic_result = 0xfaceb00c;
0079     int ret;
0080     int i;
0081 
0082     port_key = rand() & 0x00FF;
0083     populate_map(port_key, magic_result);
0084 
0085     in6.sin6_addr.s6_addr16[0] = 0xdead;
0086     in6.sin6_addr.s6_addr16[1] = 0xbeef;
0087     in6.sin6_port = port_key;
0088 
0089     for (i = 0; i < NR_TESTS; i++) {
0090         printf("%s: ", test_names[i]);
0091 
0092         in6.sin6_addr.s6_addr16[7] = i;
0093         ret = connect(-1, (struct sockaddr *)&in6, sizeof(in6));
0094         assert(ret == -1 && errno == EBADF);
0095 
0096         ret = bpf_map_lookup_elem(REG_RESULT_H, &result_key, &result);
0097         assert(!ret);
0098 
0099         ret = bpf_map_lookup_elem(INLINE_RESULT_H, &result_key,
0100                       &inline_result);
0101         assert(!ret);
0102 
0103         if (result != magic_result || inline_result != magic_result) {
0104             printf("Error. result:%d inline_result:%d\n",
0105                    result, inline_result);
0106             exit(1);
0107         }
0108 
0109         bpf_map_delete_elem(REG_RESULT_H, &result_key);
0110         bpf_map_delete_elem(INLINE_RESULT_H, &result_key);
0111 
0112         printf("Pass\n");
0113     }
0114 }
0115 
0116 int main(int argc, char **argv)
0117 {
0118     struct bpf_link *link = NULL;
0119     struct bpf_program *prog;
0120     struct bpf_object *obj;
0121     char filename[256];
0122 
0123     snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
0124     obj = bpf_object__open_file(filename, NULL);
0125     if (libbpf_get_error(obj)) {
0126         fprintf(stderr, "ERROR: opening BPF object file failed\n");
0127         return 0;
0128     }
0129 
0130     prog = bpf_object__find_program_by_name(obj, "trace_sys_connect");
0131     if (!prog) {
0132         printf("finding a prog in obj file failed\n");
0133         goto cleanup;
0134     }
0135 
0136     /* load BPF program */
0137     if (bpf_object__load(obj)) {
0138         fprintf(stderr, "ERROR: loading BPF object file failed\n");
0139         goto cleanup;
0140     }
0141 
0142     map_fd[0] = bpf_object__find_map_fd_by_name(obj, "port_a");
0143     map_fd[1] = bpf_object__find_map_fd_by_name(obj, "port_h");
0144     map_fd[2] = bpf_object__find_map_fd_by_name(obj, "reg_result_h");
0145     map_fd[3] = bpf_object__find_map_fd_by_name(obj, "inline_result_h");
0146     map_fd[4] = bpf_object__find_map_fd_by_name(obj, "a_of_port_a");
0147     map_fd[5] = bpf_object__find_map_fd_by_name(obj, "h_of_port_a");
0148     map_fd[6] = bpf_object__find_map_fd_by_name(obj, "h_of_port_h");
0149     if (map_fd[0] < 0 || map_fd[1] < 0 || map_fd[2] < 0 ||
0150         map_fd[3] < 0 || map_fd[4] < 0 || map_fd[5] < 0 || map_fd[6] < 0) {
0151         fprintf(stderr, "ERROR: finding a map in obj file failed\n");
0152         goto cleanup;
0153     }
0154 
0155     link = bpf_program__attach(prog);
0156     if (libbpf_get_error(link)) {
0157         fprintf(stderr, "ERROR: bpf_program__attach failed\n");
0158         link = NULL;
0159         goto cleanup;
0160     }
0161 
0162     test_map_in_map();
0163 
0164 cleanup:
0165     bpf_link__destroy(link);
0166     bpf_object__close(obj);
0167     return 0;
0168 }