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