0001
0002 #include <stddef.h>
0003 #include <string.h>
0004 #include <netinet/in.h>
0005 #include <linux/bpf.h>
0006 #include <linux/if_ether.h>
0007 #include <linux/if_packet.h>
0008 #include <linux/ip.h>
0009 #include <linux/ipv6.h>
0010 #include <linux/types.h>
0011 #include <linux/socket.h>
0012 #include <linux/tcp.h>
0013 #include <bpf/bpf_helpers.h>
0014 #include <bpf/bpf_endian.h>
0015 #include "test_tcpnotify.h"
0016
0017 struct {
0018 __uint(type, BPF_MAP_TYPE_ARRAY);
0019 __uint(max_entries, 4);
0020 __type(key, __u32);
0021 __type(value, struct tcpnotify_globals);
0022 } global_map SEC(".maps");
0023
0024 struct {
0025 __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
0026 __uint(max_entries, 2);
0027 __type(key, int);
0028 __type(value, __u32);
0029 } perf_event_map SEC(".maps");
0030
0031 SEC("sockops")
0032 int bpf_testcb(struct bpf_sock_ops *skops)
0033 {
0034 int rv = -1;
0035 int op;
0036
0037 op = (int) skops->op;
0038
0039 if (bpf_ntohl(skops->remote_port) != TESTPORT) {
0040 skops->reply = -1;
0041 return 0;
0042 }
0043
0044 switch (op) {
0045 case BPF_SOCK_OPS_TIMEOUT_INIT:
0046 case BPF_SOCK_OPS_RWND_INIT:
0047 case BPF_SOCK_OPS_NEEDS_ECN:
0048 case BPF_SOCK_OPS_BASE_RTT:
0049 case BPF_SOCK_OPS_RTO_CB:
0050 rv = 1;
0051 break;
0052
0053 case BPF_SOCK_OPS_TCP_CONNECT_CB:
0054 case BPF_SOCK_OPS_TCP_LISTEN_CB:
0055 case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB:
0056 case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB:
0057 bpf_sock_ops_cb_flags_set(skops, (BPF_SOCK_OPS_RETRANS_CB_FLAG|
0058 BPF_SOCK_OPS_RTO_CB_FLAG));
0059 rv = 1;
0060 break;
0061 case BPF_SOCK_OPS_RETRANS_CB: {
0062 __u32 key = 0;
0063 struct tcpnotify_globals g, *gp;
0064 struct tcp_notifier msg = {
0065 .type = 0xde,
0066 .subtype = 0xad,
0067 .source = 0xbe,
0068 .hash = 0xef,
0069 };
0070
0071 rv = 1;
0072
0073
0074 gp = bpf_map_lookup_elem(&global_map, &key);
0075 if (!gp)
0076 break;
0077 g = *gp;
0078 g.total_retrans = skops->total_retrans;
0079 g.ncalls++;
0080 bpf_map_update_elem(&global_map, &key, &g,
0081 BPF_ANY);
0082 bpf_perf_event_output(skops, &perf_event_map,
0083 BPF_F_CURRENT_CPU,
0084 &msg, sizeof(msg));
0085 }
0086 break;
0087 default:
0088 rv = -1;
0089 }
0090 skops->reply = rv;
0091 return 1;
0092 }
0093 char _license[] SEC("license") = "GPL";