github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/examples/tcprtt/tcprtt.c (about)

     1  //go:build ignore
     2  
     3  #include "common.h"
     4  
     5  #include "bpf_endian.h"
     6  #include "bpf_tracing.h"
     7  
     8  #define AF_INET 2
     9  
    10  char __license[] SEC("license") = "Dual MIT/GPL";
    11  
    12  /**
    13   * For CO-RE relocatable eBPF programs, __attribute__((preserve_access_index))
    14   * preserves the offset of the specified fields in the original kernel struct.
    15   * So here we don't need to include "vmlinux.h". Instead we only need to define
    16   * the kernel struct and their fields the eBPF program actually requires.
    17   *
    18   * Also note that BTF-enabled programs like fentry, fexit, fmod_ret, tp_btf,
    19   * lsm, etc. declared using the BPF_PROG macro can read kernel memory without
    20   * needing to call bpf_probe_read*().
    21   */
    22  
    23  /**
    24   * struct sock_common is the minimal network layer representation of sockets.
    25   * This is a simplified copy of the kernel's struct sock_common.
    26   * This copy contains only the fields needed for this example to
    27   * fetch the source and destination port numbers and IP addresses.
    28   */
    29  struct sock_common {
    30  	union {
    31  		struct {
    32  			// skc_daddr is destination IP address
    33  			__be32 skc_daddr;
    34  			// skc_rcv_saddr is the source IP address
    35  			__be32 skc_rcv_saddr;
    36  		};
    37  	};
    38  	union {
    39  		struct {
    40  			// skc_dport is the destination TCP/UDP port
    41  			__be16 skc_dport;
    42  			// skc_num is the source TCP/UDP port
    43  			__u16 skc_num;
    44  		};
    45  	};
    46  	// skc_family is the network address family (2 for IPV4)
    47  	short unsigned int skc_family;
    48  } __attribute__((preserve_access_index));
    49  
    50  /**
    51   * struct sock is the network layer representation of sockets.
    52   * This is a simplified copy of the kernel's struct sock.
    53   * This copy is needed only to access struct sock_common.
    54   */
    55  struct sock {
    56  	struct sock_common __sk_common;
    57  } __attribute__((preserve_access_index));
    58  
    59  /**
    60   * struct tcp_sock is the Linux representation of a TCP socket.
    61   * This is a simplified copy of the kernel's struct tcp_sock.
    62   * For this example we only need srtt_us to read the smoothed RTT.
    63   */
    64  struct tcp_sock {
    65  	u32 srtt_us;
    66  } __attribute__((preserve_access_index));
    67  
    68  struct {
    69  	__uint(type, BPF_MAP_TYPE_RINGBUF);
    70  	__uint(max_entries, 1 << 24);
    71  } events SEC(".maps");
    72  
    73  /**
    74   * The sample submitted to userspace over a ring buffer.
    75   * Emit struct event's type info into the ELF's BTF so bpf2go
    76   * can generate a Go type from it.
    77   */
    78  struct event {
    79  	u16 sport;
    80  	u16 dport;
    81  	u32 saddr;
    82  	u32 daddr;
    83  	u32 srtt;
    84  };
    85  struct event *unused_event __attribute__((unused));
    86  
    87  SEC("fentry/tcp_close")
    88  int BPF_PROG(tcp_close, struct sock *sk) {
    89  	if (sk->__sk_common.skc_family != AF_INET) {
    90  		return 0;
    91  	}
    92  
    93  	// The input struct sock is actually a tcp_sock, so we can type-cast
    94  	struct tcp_sock *ts = bpf_skc_to_tcp_sock(sk);
    95  	if (!ts) {
    96  		return 0;
    97  	}
    98  
    99  	struct event *tcp_info;
   100  	tcp_info = bpf_ringbuf_reserve(&events, sizeof(struct event), 0);
   101  	if (!tcp_info) {
   102  		return 0;
   103  	}
   104  
   105  	tcp_info->saddr = sk->__sk_common.skc_rcv_saddr;
   106  	tcp_info->daddr = sk->__sk_common.skc_daddr;
   107  	tcp_info->dport = bpf_ntohs(sk->__sk_common.skc_dport);
   108  	tcp_info->sport = sk->__sk_common.skc_num;
   109  
   110  	tcp_info->srtt = ts->srtt_us >> 3;
   111  	tcp_info->srtt /= 1000;
   112  
   113  	bpf_ringbuf_submit(tcp_info, 0);
   114  
   115  	return 0;
   116  }