diff --git a/bpf/rtt_tracker.h b/bpf/rtt_tracker.h index 4d62e98d34c384d14199a694d24d94a7a0512521..1176a520655ffd852939cdb9424762a7fffb3d28 100644 --- a/bpf/rtt_tracker.h +++ b/bpf/rtt_tracker.h @@ -157,4 +157,12 @@ int BPF_PROG(tcp_rcv_fentry, struct sock *sk, struct sk_buff *skb) { return calculate_flow_rtt_tcp(sk, skb); } +SEC("kprobe/tcp_rcv_established") +int BPF_KPROBE(tcp_rcv_kprobe, struct sock *sk, struct sk_buff *skb) { + if (sk == NULL || skb == NULL) { + return 0; + } + return calculate_flow_rtt_tcp(sk, skb); +} + #endif /* __RTT_TRACKER_H__ */ diff --git a/pkg/ebpf/bpf_arm64_bpfel.go b/pkg/ebpf/bpf_arm64_bpfel.go index bc204c62819ffb303f28c67b7db03df171e4135a..ad33b0b590cb6e237e2ad7b392867980f07b07ca 100644 --- a/pkg/ebpf/bpf_arm64_bpfel.go +++ b/pkg/ebpf/bpf_arm64_bpfel.go @@ -120,6 +120,7 @@ type BpfProgramSpecs struct { IngressPcaParse *ebpf.ProgramSpec `ebpf:"ingress_pca_parse"` KfreeSkb *ebpf.ProgramSpec `ebpf:"kfree_skb"` TcpRcvFentry *ebpf.ProgramSpec `ebpf:"tcp_rcv_fentry"` + TcpRcvKprobe *ebpf.ProgramSpec `ebpf:"tcp_rcv_kprobe"` } // BpfMapSpecs contains maps before they are loaded into the kernel. @@ -176,6 +177,7 @@ type BpfPrograms struct { IngressPcaParse *ebpf.Program `ebpf:"ingress_pca_parse"` KfreeSkb *ebpf.Program `ebpf:"kfree_skb"` TcpRcvFentry *ebpf.Program `ebpf:"tcp_rcv_fentry"` + TcpRcvKprobe *ebpf.Program `ebpf:"tcp_rcv_kprobe"` } func (p *BpfPrograms) Close() error { @@ -186,6 +188,7 @@ func (p *BpfPrograms) Close() error { p.IngressPcaParse, p.KfreeSkb, p.TcpRcvFentry, + p.TcpRcvKprobe, ) } diff --git a/pkg/ebpf/bpf_arm64_bpfel.o b/pkg/ebpf/bpf_arm64_bpfel.o index da101f9d91d3b84b8a21527cf72452c3cda95ce6..546a70ad9e4f9fe66dff15ab54a6e344c73a246d 100644 Binary files a/pkg/ebpf/bpf_arm64_bpfel.o and b/pkg/ebpf/bpf_arm64_bpfel.o differ diff --git a/pkg/ebpf/bpf_powerpc_bpfel.go b/pkg/ebpf/bpf_powerpc_bpfel.go index e074d6d88d7e1734a9da0964199c2b0d2c065ccc..bacd97f2254bde89c865eef08f2f9eeebf28afab 100644 --- a/pkg/ebpf/bpf_powerpc_bpfel.go +++ b/pkg/ebpf/bpf_powerpc_bpfel.go @@ -120,6 +120,7 @@ type BpfProgramSpecs struct { IngressPcaParse *ebpf.ProgramSpec `ebpf:"ingress_pca_parse"` KfreeSkb *ebpf.ProgramSpec `ebpf:"kfree_skb"` TcpRcvFentry *ebpf.ProgramSpec `ebpf:"tcp_rcv_fentry"` + TcpRcvKprobe *ebpf.ProgramSpec `ebpf:"tcp_rcv_kprobe"` } // BpfMapSpecs contains maps before they are loaded into the kernel. @@ -176,6 +177,7 @@ type BpfPrograms struct { IngressPcaParse *ebpf.Program `ebpf:"ingress_pca_parse"` KfreeSkb *ebpf.Program `ebpf:"kfree_skb"` TcpRcvFentry *ebpf.Program `ebpf:"tcp_rcv_fentry"` + TcpRcvKprobe *ebpf.Program `ebpf:"tcp_rcv_kprobe"` } func (p *BpfPrograms) Close() error { @@ -186,6 +188,7 @@ func (p *BpfPrograms) Close() error { p.IngressPcaParse, p.KfreeSkb, p.TcpRcvFentry, + p.TcpRcvKprobe, ) } diff --git a/pkg/ebpf/bpf_powerpc_bpfel.o b/pkg/ebpf/bpf_powerpc_bpfel.o index 1b33de675a1c5da94f1fe3acd27479ada68298be..515122a49ce0d1444ce7b70300199fb0f6b9f292 100644 Binary files a/pkg/ebpf/bpf_powerpc_bpfel.o and b/pkg/ebpf/bpf_powerpc_bpfel.o differ diff --git a/pkg/ebpf/bpf_s390_bpfeb.go b/pkg/ebpf/bpf_s390_bpfeb.go index f129c345ff0bbf4059f0e9dd652aa5c36da3d858..a4b5e44f91488004a839a00b62b509c2fca6cd23 100644 --- a/pkg/ebpf/bpf_s390_bpfeb.go +++ b/pkg/ebpf/bpf_s390_bpfeb.go @@ -120,6 +120,7 @@ type BpfProgramSpecs struct { IngressPcaParse *ebpf.ProgramSpec `ebpf:"ingress_pca_parse"` KfreeSkb *ebpf.ProgramSpec `ebpf:"kfree_skb"` TcpRcvFentry *ebpf.ProgramSpec `ebpf:"tcp_rcv_fentry"` + TcpRcvKprobe *ebpf.ProgramSpec `ebpf:"tcp_rcv_kprobe"` } // BpfMapSpecs contains maps before they are loaded into the kernel. @@ -176,6 +177,7 @@ type BpfPrograms struct { IngressPcaParse *ebpf.Program `ebpf:"ingress_pca_parse"` KfreeSkb *ebpf.Program `ebpf:"kfree_skb"` TcpRcvFentry *ebpf.Program `ebpf:"tcp_rcv_fentry"` + TcpRcvKprobe *ebpf.Program `ebpf:"tcp_rcv_kprobe"` } func (p *BpfPrograms) Close() error { @@ -186,6 +188,7 @@ func (p *BpfPrograms) Close() error { p.IngressPcaParse, p.KfreeSkb, p.TcpRcvFentry, + p.TcpRcvKprobe, ) } diff --git a/pkg/ebpf/bpf_s390_bpfeb.o b/pkg/ebpf/bpf_s390_bpfeb.o index f1d6c7fbf11dbfd8b71ee356c8a76c6110103870..84587efd93cd62351a7838f6b2ccb5bc7703fa6e 100644 Binary files a/pkg/ebpf/bpf_s390_bpfeb.o and b/pkg/ebpf/bpf_s390_bpfeb.o differ diff --git a/pkg/ebpf/bpf_x86_bpfel.go b/pkg/ebpf/bpf_x86_bpfel.go index 5b39854730c7912d72928b06ccb5bdbd6eedb5ee..a06125656e6ef387bf6e0d5adda8ee2a0f91d465 100644 --- a/pkg/ebpf/bpf_x86_bpfel.go +++ b/pkg/ebpf/bpf_x86_bpfel.go @@ -120,6 +120,7 @@ type BpfProgramSpecs struct { IngressPcaParse *ebpf.ProgramSpec `ebpf:"ingress_pca_parse"` KfreeSkb *ebpf.ProgramSpec `ebpf:"kfree_skb"` TcpRcvFentry *ebpf.ProgramSpec `ebpf:"tcp_rcv_fentry"` + TcpRcvKprobe *ebpf.ProgramSpec `ebpf:"tcp_rcv_kprobe"` } // BpfMapSpecs contains maps before they are loaded into the kernel. @@ -176,6 +177,7 @@ type BpfPrograms struct { IngressPcaParse *ebpf.Program `ebpf:"ingress_pca_parse"` KfreeSkb *ebpf.Program `ebpf:"kfree_skb"` TcpRcvFentry *ebpf.Program `ebpf:"tcp_rcv_fentry"` + TcpRcvKprobe *ebpf.Program `ebpf:"tcp_rcv_kprobe"` } func (p *BpfPrograms) Close() error { @@ -186,6 +188,7 @@ func (p *BpfPrograms) Close() error { p.IngressPcaParse, p.KfreeSkb, p.TcpRcvFentry, + p.TcpRcvKprobe, ) } diff --git a/pkg/ebpf/bpf_x86_bpfel.o b/pkg/ebpf/bpf_x86_bpfel.o index 9ebe3a2b72cf126d8bf508946ffde6bb9c9a2379..2929682616484946758b1d783165204cc84e8be2 100644 Binary files a/pkg/ebpf/bpf_x86_bpfel.o and b/pkg/ebpf/bpf_x86_bpfel.o differ diff --git a/pkg/ebpf/tracer.go b/pkg/ebpf/tracer.go index 7a4c4419467d6d3b1bbd350303d34eb5bc835114..7cdb4b574c0e58fb94e5251b494fed46e91e4113 100644 --- a/pkg/ebpf/tracer.go +++ b/pkg/ebpf/tracer.go @@ -62,6 +62,7 @@ type FlowFetcher struct { enableEgress bool pktDropsTracePoint link.Link rttFentryLink link.Link + rttKprobeLink link.Link } type FlowFetcherConfig struct { @@ -141,13 +142,18 @@ func NewFlowFetcher(cfg *FlowFetcherConfig) (*FlowFetcher, error) { } } - var rttFentryLink link.Link + var rttFentryLink, rttKprobeLink link.Link if cfg.EnableRTT { rttFentryLink, err = link.AttachTracing(link.TracingOptions{ Program: objects.BpfPrograms.TcpRcvFentry, }) if err != nil { - return nil, fmt.Errorf("failed to attach the BPF program to tcpReceiveFentry: %w", err) + log.Warningf("failed to attach the BPF program to tcpReceiveFentry: %v fallback to use kprobe", err) + // try to use kprobe for older kernels + rttKprobeLink, err = link.Kprobe("tcp_rcv_established", objects.TcpRcvKprobe, nil) + if err != nil { + return nil, fmt.Errorf("failed to attach the BPF program to tcpReceiveKprobe: %w", err) + } } } @@ -167,6 +173,7 @@ func NewFlowFetcher(cfg *FlowFetcherConfig) (*FlowFetcher, error) { enableEgress: cfg.EnableEgress, pktDropsTracePoint: pktDropsLink, rttFentryLink: rttFentryLink, + rttKprobeLink: rttKprobeLink, }, nil } @@ -300,6 +307,11 @@ func (m *FlowFetcher) Close() error { errs = append(errs, err) } } + if m.rttKprobeLink != nil { + if err := m.rttKprobeLink.Close(); err != nil { + errs = append(errs, err) + } + } // m.ringbufReader.Read is a blocking operation, so we need to close the ring buffer // from another goroutine to avoid the system not being able to exit if there // isn't traffic in a given interface @@ -460,6 +472,7 @@ func kernelSpecificLoadAndAssign(oldKernel bool, spec *ebpf.CollectionSpec) (Bpf EgressFlowParse *ebpf.Program `ebpf:"egress_flow_parse"` IngressFlowParse *ebpf.Program `ebpf:"ingress_flow_parse"` TCPRcvFentry *ebpf.Program `ebpf:"tcp_rcv_fentry"` + TCPRcvKprobe *ebpf.Program `ebpf:"tcp_rcv_kprobe"` } type NewBpfObjects struct { NewBpfPrograms @@ -485,6 +498,7 @@ func kernelSpecificLoadAndAssign(oldKernel bool, spec *ebpf.CollectionSpec) (Bpf objects.EgressFlowParse = newObjects.EgressFlowParse objects.IngressFlowParse = newObjects.IngressFlowParse objects.TcpRcvFentry = newObjects.TCPRcvFentry + objects.TcpRcvKprobe = newObjects.TCPRcvKprobe objects.KfreeSkb = nil } else { if err := spec.LoadAndAssign(&objects, nil); err != nil {