1bd4aed0eSJiong Wang // SPDX-License-Identifier: GPL-2.0 2bd4aed0eSJiong Wang #include <stddef.h> 3bd4aed0eSJiong Wang #include <string.h> 4bd4aed0eSJiong Wang #include <linux/bpf.h> 5bd4aed0eSJiong Wang #include <linux/if_ether.h> 6bd4aed0eSJiong Wang #include <linux/if_packet.h> 7bd4aed0eSJiong Wang #include <linux/ip.h> 8bd4aed0eSJiong Wang #include <linux/ipv6.h> 9bd4aed0eSJiong Wang #include <linux/types.h> 10bd4aed0eSJiong Wang #include <linux/socket.h> 11bd4aed0eSJiong Wang #include <linux/tcp.h> 12bd4aed0eSJiong Wang #include <netinet/in.h> 13bd4aed0eSJiong Wang #include "bpf_helpers.h" 14bd4aed0eSJiong Wang #include "bpf_endian.h" 15bd4aed0eSJiong Wang #include "test_tcpnotify.h" 16bd4aed0eSJiong Wang 17bd4aed0eSJiong Wang struct bpf_map_def SEC("maps") global_map = { 18bd4aed0eSJiong Wang .type = BPF_MAP_TYPE_ARRAY, 19bd4aed0eSJiong Wang .key_size = sizeof(__u32), 20bd4aed0eSJiong Wang .value_size = sizeof(struct tcpnotify_globals), 21bd4aed0eSJiong Wang .max_entries = 4, 22bd4aed0eSJiong Wang }; 23bd4aed0eSJiong Wang 24bd4aed0eSJiong Wang struct bpf_map_def SEC("maps") perf_event_map = { 25bd4aed0eSJiong Wang .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY, 26bd4aed0eSJiong Wang .key_size = sizeof(int), 27bd4aed0eSJiong Wang .value_size = sizeof(__u32), 28bd4aed0eSJiong Wang .max_entries = 2, 29bd4aed0eSJiong Wang }; 30bd4aed0eSJiong Wang 31bd4aed0eSJiong Wang int _version SEC("version") = 1; 32bd4aed0eSJiong Wang 33bd4aed0eSJiong Wang SEC("sockops") 34bd4aed0eSJiong Wang int bpf_testcb(struct bpf_sock_ops *skops) 35bd4aed0eSJiong Wang { 36bd4aed0eSJiong Wang int rv = -1; 37bd4aed0eSJiong Wang int op; 38bd4aed0eSJiong Wang 39bd4aed0eSJiong Wang op = (int) skops->op; 40bd4aed0eSJiong Wang 41bd4aed0eSJiong Wang if (bpf_ntohl(skops->remote_port) != TESTPORT) { 42bd4aed0eSJiong Wang skops->reply = -1; 43bd4aed0eSJiong Wang return 0; 44bd4aed0eSJiong Wang } 45bd4aed0eSJiong Wang 46bd4aed0eSJiong Wang switch (op) { 47bd4aed0eSJiong Wang case BPF_SOCK_OPS_TIMEOUT_INIT: 48bd4aed0eSJiong Wang case BPF_SOCK_OPS_RWND_INIT: 49bd4aed0eSJiong Wang case BPF_SOCK_OPS_NEEDS_ECN: 50bd4aed0eSJiong Wang case BPF_SOCK_OPS_BASE_RTT: 51bd4aed0eSJiong Wang case BPF_SOCK_OPS_RTO_CB: 52bd4aed0eSJiong Wang rv = 1; 53bd4aed0eSJiong Wang break; 54bd4aed0eSJiong Wang 55bd4aed0eSJiong Wang case BPF_SOCK_OPS_TCP_CONNECT_CB: 56bd4aed0eSJiong Wang case BPF_SOCK_OPS_TCP_LISTEN_CB: 57bd4aed0eSJiong Wang case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB: 58bd4aed0eSJiong Wang case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB: 59bd4aed0eSJiong Wang bpf_sock_ops_cb_flags_set(skops, (BPF_SOCK_OPS_RETRANS_CB_FLAG| 60bd4aed0eSJiong Wang BPF_SOCK_OPS_RTO_CB_FLAG)); 61bd4aed0eSJiong Wang rv = 1; 62bd4aed0eSJiong Wang break; 63bd4aed0eSJiong Wang case BPF_SOCK_OPS_RETRANS_CB: { 64bd4aed0eSJiong Wang __u32 key = 0; 65bd4aed0eSJiong Wang struct tcpnotify_globals g, *gp; 66bd4aed0eSJiong Wang struct tcp_notifier msg = { 67bd4aed0eSJiong Wang .type = 0xde, 68bd4aed0eSJiong Wang .subtype = 0xad, 69bd4aed0eSJiong Wang .source = 0xbe, 70bd4aed0eSJiong Wang .hash = 0xef, 71bd4aed0eSJiong Wang }; 72bd4aed0eSJiong Wang 73bd4aed0eSJiong Wang rv = 1; 74bd4aed0eSJiong Wang 75bd4aed0eSJiong Wang /* Update results */ 76bd4aed0eSJiong Wang gp = bpf_map_lookup_elem(&global_map, &key); 77bd4aed0eSJiong Wang if (!gp) 78bd4aed0eSJiong Wang break; 79bd4aed0eSJiong Wang g = *gp; 80bd4aed0eSJiong Wang g.total_retrans = skops->total_retrans; 81bd4aed0eSJiong Wang g.ncalls++; 82bd4aed0eSJiong Wang bpf_map_update_elem(&global_map, &key, &g, 83bd4aed0eSJiong Wang BPF_ANY); 84bd4aed0eSJiong Wang bpf_perf_event_output(skops, &perf_event_map, 85bd4aed0eSJiong Wang BPF_F_CURRENT_CPU, 86bd4aed0eSJiong Wang &msg, sizeof(msg)); 87bd4aed0eSJiong Wang } 88bd4aed0eSJiong Wang break; 89bd4aed0eSJiong Wang default: 90bd4aed0eSJiong Wang rv = -1; 91bd4aed0eSJiong Wang } 92bd4aed0eSJiong Wang skops->reply = rv; 93bd4aed0eSJiong Wang return 1; 94bd4aed0eSJiong Wang } 95bd4aed0eSJiong Wang char _license[] SEC("license") = "GPL"; 96