ebpf_exporter
112 строк · 3.4 Кб
1#include <vmlinux.h>
2#include <bpf/bpf_tracing.h>
3#include "maps.bpf.h"
4
5#define MAX_ENTRIES 8192
6
7// Type of tcp retransmits
8#define RETRANSMIT 1
9#define TLP 2
10
11#define AF_INET 2
12#define AF_INET6 10
13
14#define UPPER_PORT_BOUND 32768
15
16struct ipv4_key_t {
17u32 saddr;
18u32 daddr;
19u16 main_port;
20u8 type;
21};
22
23struct ipv6_key_t {
24u8 saddr[16];
25u8 daddr[16];
26u16 main_port;
27u8 type;
28};
29
30struct {
31__uint(type, BPF_MAP_TYPE_LRU_HASH);
32__uint(max_entries, MAX_ENTRIES);
33__type(key, struct ipv4_key_t);
34__type(value, u64);
35} tcp_retransmit_ipv4_packets_total SEC(".maps");
36
37struct {
38__uint(type, BPF_MAP_TYPE_LRU_HASH);
39__uint(max_entries, MAX_ENTRIES);
40__type(key, struct ipv6_key_t);
41__type(value, u64);
42} tcp_retransmit_ipv6_packets_total SEC(".maps");
43
44static int extract_main_port(const struct sock *sk)
45{
46u16 sport = sk->__sk_common.skc_num;
47u16 dport = __builtin_bswap16(sk->__sk_common.skc_dport);
48
49if (sport > UPPER_PORT_BOUND && dport > UPPER_PORT_BOUND) {
50return 0;
51}
52
53if (sport < dport) {
54return sport;
55}
56
57return dport;
58}
59
60#define TRACE_PROTOCOL(key_type, map, ip_extractor) \
61key_type key = {}; \
62\
63key.type = type; \
64key.main_port = extract_main_port(sk); \
65\
66ip_extractor; \
67\
68increment_map(map, &key, 1); \
69\
70return 0;
71
72static int trace_ipv4(const struct sock *sk, u8 type)
73{
74TRACE_PROTOCOL(struct ipv4_key_t, &tcp_retransmit_ipv4_packets_total, {
75key.saddr = sk->__sk_common.skc_rcv_saddr;
76key.daddr = sk->__sk_common.skc_daddr;
77});
78}
79
80static int trace_ipv6(const struct sock *sk, u8 type)
81{
82TRACE_PROTOCOL(struct ipv6_key_t, &tcp_retransmit_ipv6_packets_total, {
83bpf_probe_read_kernel(&key.saddr, sizeof(key.saddr), sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32);
84bpf_probe_read_kernel(&key.daddr, sizeof(key.daddr), sk->__sk_common.skc_v6_daddr.in6_u.u6_addr32);
85});
86}
87
88static int trace_event(const struct sock *sk, u8 type)
89{
90switch (sk->__sk_common.skc_family) {
91case AF_INET:
92return trace_ipv4(sk, type);
93case AF_INET6:
94return trace_ipv6(sk, type);
95}
96
97return 0;
98}
99
100SEC("fentry/tcp_send_loss_probe")
101int BPF_PROG(tcp_send_loss_probe, struct sock *sk)
102{
103return trace_event(sk, TLP);
104}
105
106SEC("fentry/tcp_retransmit_skb")
107int BPF_PROG(tcp_retransmit_skb, struct sock *sk)
108{
109return trace_event(sk, RETRANSMIT);
110}
111
112char LICENSE[] SEC("license") = "GPL";
113