inspektor-gadget
144 строки · 4.1 Кб
1// SPDX-License-Identifier: GPL-2.0
2//
3// Based on tcpretrans(8) from BCC
4//
5// Copyright 2016 Netflix, Inc.
6//
7// 14-Feb-2016 Brendan Gregg Created this.
8// 03-Nov-2017 Matthias Tafelmeier Extended this.
9// Copyright 2023 Microsoft Corporation
10
11#include <vmlinux.h>12
13#include <bpf/bpf_helpers.h>14#include <bpf/bpf_core_read.h>15#include <bpf/bpf_tracing.h>16#include <bpf/bpf_endian.h>17
18#define GADGET_TYPE_TRACING19#include <gadget/sockets-map.h>20
21#include "tcpretrans.h"22
23/* Define here, because there are conflicts with include files */
24#define AF_INET 225#define AF_INET6 1026
27// we need this to make sure the compiler doesn't remove our struct
28const struct event *unusedevent __attribute__((unused));29
30struct {31__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);32__uint(key_size, sizeof(__u32));33__uint(value_size, sizeof(__u32));34} events SEC(".maps");35
36static __always_inline int __trace_tcp_retrans(void *ctx, const struct sock *sk,37const struct sk_buff *skb)38{
39struct inet_sock *sockp;40struct task_struct *task;41__u64 pid_tgid, uid_gid;42struct event event = {};43struct tcp_skb_cb *tcb;44
45if (sk == NULL)46return 0;47
48if (BPF_CORE_READ_BITFIELD_PROBED(sk, sk_protocol) != IPPROTO_TCP)49return 0;50
51sockp = (struct inet_sock *)sk;52task = (struct task_struct *)bpf_get_current_task();53pid_tgid = bpf_get_current_pid_tgid();54uid_gid = bpf_get_current_uid_gid();55
56event.timestamp = bpf_ktime_get_boot_ns();57event.af = BPF_CORE_READ(sk, __sk_common.skc_family);58event.state = BPF_CORE_READ(sk, __sk_common.skc_state);59
60bpf_get_current_comm(&event.proc_current.task,61sizeof(event.proc_current.task));62event.proc_current.pid = pid_tgid >> 32;63event.proc_current.tid = (__u32)pid_tgid;64event.proc_current.mount_ns_id =65(u64)BPF_CORE_READ(task, nsproxy, mnt_ns, ns.inum);66event.proc_current.uid = (u32)uid_gid;67event.proc_current.gid = (u32)(uid_gid >> 32);68
69// The tcp_retransmit_skb tracepoint is fired with a skb that does not70// contain the TCP header because the TCP header is built on a cloned skb71// we don't have access to.72// skb->transport_header is not set: skb_transport_header_was_set() == false.73// Instead, we have to read the TCP flags from the TCP control buffer.74tcb = (struct tcp_skb_cb *)&(skb->cb[0]);75bpf_probe_read_kernel(&event.tcpflags, sizeof(event.tcpflags),76&tcb->tcp_flags);77
78BPF_CORE_READ_INTO(&event.dport, sk, __sk_common.skc_dport);79if (event.dport == 0)80return 0;81
82BPF_CORE_READ_INTO(&event.sport, sockp, inet_sport);83if (event.sport == 0)84return 0;85
86switch (event.af) {87case AF_INET:88BPF_CORE_READ_INTO(&event.daddr_v4, sk, __sk_common.skc_daddr);89if (event.daddr_v4 == 0)90return 0;91BPF_CORE_READ_INTO(&event.saddr_v4, sk,92__sk_common.skc_rcv_saddr);93if (event.saddr_v4 == 0)94return 0;95break;96
97case AF_INET6:98BPF_CORE_READ_INTO(99&event.saddr_v6, sk,100__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32);101if (event.saddr_v6 == 0)102return 0;103BPF_CORE_READ_INTO(&event.daddr_v6, sk,104__sk_common.skc_v6_daddr.in6_u.u6_addr32);105if (event.daddr_v6 == 0)106return 0;107break;108
109default:110// drop111return 0;112}113
114BPF_CORE_READ_INTO(&event.netns, sk, __sk_common.skc_net.net, ns.inum);115
116struct sockets_value *skb_val = gadget_socket_lookup(sk, event.netns);117
118if (skb_val != NULL) {119event.proc_socket.mount_ns_id = skb_val->mntns;120event.proc_socket.pid = skb_val->pid_tgid >> 32;121event.proc_socket.tid = (__u32)skb_val->pid_tgid;122__builtin_memcpy(&event.proc_socket.task, skb_val->task,123sizeof(event.proc_socket.task));124event.proc_socket.uid = (__u32)skb_val->uid_gid;125event.proc_socket.gid = (__u32)(skb_val->uid_gid >> 32);126}127
128bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &event,129sizeof(event));130return 0;131}
132
133SEC("tracepoint/tcp/tcp_retransmit_skb")134int ig_tcpretrans(struct trace_event_raw_tcp_event_sk_skb *ctx)135{
136// struct trace_event_raw_tcp_event_sk_skb is described in:137// /sys/kernel/tracing/events/tcp/tcp_retransmit_skb/format138const struct sk_buff *skb = ctx->skbaddr;139const struct sock *sk = ctx->skaddr;140
141return __trace_tcp_retrans(ctx, sk, skb);142}
143
144char LICENSE[] SEC("license") = "GPL";145