Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #define _GNU_SOURCE
0003 #include <pthread.h>
0004 #include <inttypes.h>
0005 #include <stdio.h>
0006 #include <stdlib.h>
0007 #include <unistd.h>
0008 #include <asm/types.h>
0009 #include <sys/syscall.h>
0010 #include <errno.h>
0011 #include <string.h>
0012 #include <linux/bpf.h>
0013 #include <sys/socket.h>
0014 #include <bpf/bpf.h>
0015 #include <bpf/libbpf.h>
0016 #include <sys/ioctl.h>
0017 #include <linux/rtnetlink.h>
0018 #include <signal.h>
0019 #include <linux/perf_event.h>
0020 #include <linux/err.h>
0021 
0022 #include "bpf_util.h"
0023 #include "cgroup_helpers.h"
0024 
0025 #include "test_tcpnotify.h"
0026 #include "trace_helpers.h"
0027 #include "testing_helpers.h"
0028 
0029 #define SOCKET_BUFFER_SIZE (getpagesize() < 8192L ? getpagesize() : 8192L)
0030 
0031 pthread_t tid;
0032 int rx_callbacks;
0033 
0034 static void dummyfn(void *ctx, int cpu, void *data, __u32 size)
0035 {
0036     struct tcp_notifier *t = data;
0037 
0038     if (t->type != 0xde || t->subtype != 0xad ||
0039         t->source != 0xbe || t->hash != 0xef)
0040         return;
0041     rx_callbacks++;
0042 }
0043 
0044 void tcp_notifier_poller(struct perf_buffer *pb)
0045 {
0046     int err;
0047 
0048     while (1) {
0049         err = perf_buffer__poll(pb, 100);
0050         if (err < 0 && err != -EINTR) {
0051             printf("failed perf_buffer__poll: %d\n", err);
0052             return;
0053         }
0054     }
0055 }
0056 
0057 static void *poller_thread(void *arg)
0058 {
0059     struct perf_buffer *pb = arg;
0060 
0061     tcp_notifier_poller(pb);
0062     return arg;
0063 }
0064 
0065 int verify_result(const struct tcpnotify_globals *result)
0066 {
0067     return (result->ncalls > 0 && result->ncalls == rx_callbacks ? 0 : 1);
0068 }
0069 
0070 int main(int argc, char **argv)
0071 {
0072     const char *file = "test_tcpnotify_kern.o";
0073     struct bpf_map *perf_map, *global_map;
0074     struct tcpnotify_globals g = {0};
0075     struct perf_buffer *pb = NULL;
0076     const char *cg_path = "/foo";
0077     int prog_fd, rv, cg_fd = -1;
0078     int error = EXIT_FAILURE;
0079     struct bpf_object *obj;
0080     char test_script[80];
0081     cpu_set_t cpuset;
0082     __u32 key = 0;
0083 
0084     libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
0085 
0086     CPU_ZERO(&cpuset);
0087     CPU_SET(0, &cpuset);
0088     pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
0089 
0090     cg_fd = cgroup_setup_and_join(cg_path);
0091     if (cg_fd < 0)
0092         goto err;
0093 
0094     if (bpf_prog_test_load(file, BPF_PROG_TYPE_SOCK_OPS, &obj, &prog_fd)) {
0095         printf("FAILED: load_bpf_file failed for: %s\n", file);
0096         goto err;
0097     }
0098 
0099     rv = bpf_prog_attach(prog_fd, cg_fd, BPF_CGROUP_SOCK_OPS, 0);
0100     if (rv) {
0101         printf("FAILED: bpf_prog_attach: %d (%s)\n",
0102                error, strerror(errno));
0103         goto err;
0104     }
0105 
0106     perf_map = bpf_object__find_map_by_name(obj, "perf_event_map");
0107     if (!perf_map) {
0108         printf("FAIL:map '%s' not found\n", "perf_event_map");
0109         goto err;
0110     }
0111 
0112     global_map = bpf_object__find_map_by_name(obj, "global_map");
0113     if (!global_map) {
0114         printf("FAIL:map '%s' not found\n", "global_map");
0115         return -1;
0116     }
0117 
0118     pb = perf_buffer__new(bpf_map__fd(perf_map), 8, dummyfn, NULL, NULL, NULL);
0119     if (!pb)
0120         goto err;
0121 
0122     pthread_create(&tid, NULL, poller_thread, pb);
0123 
0124     sprintf(test_script,
0125         "iptables -A INPUT -p tcp --dport %d -j DROP",
0126         TESTPORT);
0127     if (system(test_script)) {
0128         printf("FAILED: execute command: %s, err %d\n", test_script, -errno);
0129         goto err;
0130     }
0131 
0132     sprintf(test_script,
0133         "nc 127.0.0.1 %d < /etc/passwd > /dev/null 2>&1 ",
0134         TESTPORT);
0135     if (system(test_script))
0136         printf("execute command: %s, err %d\n", test_script, -errno);
0137 
0138     sprintf(test_script,
0139         "iptables -D INPUT -p tcp --dport %d -j DROP",
0140         TESTPORT);
0141     if (system(test_script)) {
0142         printf("FAILED: execute command: %s, err %d\n", test_script, -errno);
0143         goto err;
0144     }
0145 
0146     rv = bpf_map_lookup_elem(bpf_map__fd(global_map), &key, &g);
0147     if (rv != 0) {
0148         printf("FAILED: bpf_map_lookup_elem returns %d\n", rv);
0149         goto err;
0150     }
0151 
0152     sleep(10);
0153 
0154     if (verify_result(&g)) {
0155         printf("FAILED: Wrong stats Expected %d calls, got %d\n",
0156             g.ncalls, rx_callbacks);
0157         goto err;
0158     }
0159 
0160     printf("PASSED!\n");
0161     error = 0;
0162 err:
0163     bpf_prog_detach(cg_fd, BPF_CGROUP_SOCK_OPS);
0164     close(cg_fd);
0165     cleanup_cgroup_environment();
0166     perf_buffer__free(pb);
0167     return error;
0168 }