Skip to content

Commit

Permalink
feat: support trace socket event for ipv6 (#278)
Browse files Browse the repository at this point in the history
  • Loading branch information
hengyoush authored Jan 26, 2025
1 parent 1bf2149 commit 9a8c64d
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 37 deletions.
51 changes: 36 additions & 15 deletions agent/compatible/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,27 @@ const (
type InstrumentFunction struct {
KernelFunctionName string
BPFGoProgName string
Backup bool
}

func MakeInstrumentFunction(k string, b string) InstrumentFunction {
return InstrumentFunction{
KernelFunctionName: k,
BPFGoProgName: b,
Backup: false,
}
}

func MakeBackupInstrumentFunction(k string, b string) InstrumentFunction {
return InstrumentFunction{
KernelFunctionName: k,
BPFGoProgName: b,
Backup: true,
}
}

func (f *InstrumentFunction) IsBackup() bool {
return f.Backup
}

func (f *InstrumentFunction) GetRealKernelFunctionName() string {
Expand Down Expand Up @@ -106,13 +127,13 @@ func init() {
baseVersion := KernelVersion{
Version: "5.15.0",
InstrumentFunctions: map[bpf.AgentStepT][]InstrumentFunction{
bpf.AgentStepTIP_OUT: {InstrumentFunction{"kprobe/__ip_queue_xmit", "IpQueueXmit"}},
bpf.AgentStepTQDISC_OUT: {InstrumentFunction{"kprobe/dev_queue_xmit", "DevQueueXmit"}},
bpf.AgentStepTDEV_OUT: {InstrumentFunction{"kprobe/dev_hard_start_xmit", "DevHardStartXmit"}},
bpf.AgentStepTDEV_IN: {InstrumentFunction{"tracepoint/net/netif_receive_skb", "TracepointNetifReceiveSkb"}},
bpf.AgentStepTIP_IN: {InstrumentFunction{"kprobe/ip_rcv_core", "IpRcvCore"}},
bpf.AgentStepTTCP_IN: {InstrumentFunction{"kprobe/tcp_v4_do_rcv", "TcpV4DoRcv"}},
bpf.AgentStepTUSER_COPY: {InstrumentFunction{"tracepoint/skb/skb_copy_datagram_iovec", "TracepointSkbCopyDatagramIovec"}},
bpf.AgentStepTIP_OUT: {MakeInstrumentFunction("kprobe/__ip_queue_xmit", "IpQueueXmit")},
bpf.AgentStepTQDISC_OUT: {MakeInstrumentFunction("kprobe/dev_queue_xmit", "DevQueueXmit")},
bpf.AgentStepTDEV_OUT: {MakeInstrumentFunction("kprobe/dev_hard_start_xmit", "DevHardStartXmit")},
bpf.AgentStepTDEV_IN: {MakeInstrumentFunction("tracepoint/net/netif_receive_skb", "TracepointNetifReceiveSkb")},
bpf.AgentStepTIP_IN: {MakeInstrumentFunction("kprobe/ip_rcv_core", "IpRcvCore")},
bpf.AgentStepTTCP_IN: {MakeInstrumentFunction("kprobe/tcp_v4_do_rcv", "TcpV4DoRcv"), MakeInstrumentFunction("kprobe/tcp_v6_do_rcv", "TcpV6DoRcv")},
bpf.AgentStepTUSER_COPY: {MakeInstrumentFunction("tracepoint/skb/skb_copy_datagram_iovec", "TracepointSkbCopyDatagramIovec")},
},
Capabilities: map[Capability]bool{
SupportConstants: true,
Expand All @@ -122,32 +143,32 @@ func init() {
SupportFilterByContainer: true,
},
}
baseVersion.addBackupInstrumentFunction(bpf.AgentStepTQDISC_OUT, InstrumentFunction{"kprobe/__dev_queue_xmit", "DevQueueXmit"})
baseVersion.addBackupInstrumentFunction(bpf.AgentStepTQDISC_OUT, MakeBackupInstrumentFunction("kprobe/__dev_queue_xmit", "DevQueueXmit"))
v5d15 := copyKernelVersion(baseVersion)
KernelVersionsMap.Put(v5d15.Version, v5d15)

v5d4 := copyKernelVersion(v5d15)
v5d4.Version = "5.4.0"
v5d4.addBackupInstrumentFunction(bpf.AgentStepTIP_IN, InstrumentFunction{"kprobe/ip_rcv_core.isra.0", "IpRcvCore"})
v5d4.addBackupInstrumentFunction(bpf.AgentStepTIP_IN, InstrumentFunction{"kprobe/ip_rcv_core.isra.20", "IpRcvCore"})
v5d4.addBackupInstrumentFunction(bpf.AgentStepTIP_IN, MakeBackupInstrumentFunction("kprobe/ip_rcv_core.isra.0", "IpRcvCore"))
v5d4.addBackupInstrumentFunction(bpf.AgentStepTIP_IN, MakeBackupInstrumentFunction("kprobe/ip_rcv_core.isra.20", "IpRcvCore"))
v5d4.removeCapability(SupportRingBuffer).removeCapability(SupportXDP)
KernelVersionsMap.Put(v5d4.Version, v5d4)

v4d14 := copyKernelVersion(v5d4)
v4d14.Version = "4.14.0"
v4d14.InstrumentFunctions[bpf.AgentStepTIP_OUT] =
[]InstrumentFunction{{"kprobe/ip_queue_xmit", "IpQueueXmit"}}
v4d14.addBackupInstrumentFunction(bpf.AgentStepTIP_OUT, InstrumentFunction{"kprobe/__ip_queue_xmit", "IpQueueXmit"})
[]InstrumentFunction{MakeInstrumentFunction("kprobe/ip_queue_xmit", "IpQueueXmit")}
v4d14.addBackupInstrumentFunction(bpf.AgentStepTIP_OUT, MakeBackupInstrumentFunction("kprobe/__ip_queue_xmit", "IpQueueXmit"))
v4d14.InstrumentFunctions[bpf.AgentStepTIP_IN] =
[]InstrumentFunction{{"kprobe/ip_rcv", "IpRcvCore"}}
[]InstrumentFunction{MakeInstrumentFunction("kprobe/ip_rcv", "IpRcvCore")}
v4d14.removeCapability(SupportConstants).removeCapability(SupportRawTracepoint).removeCapability(SupportBTF).removeCapability(SupportXDP)
KernelVersionsMap.Put(v4d14.Version, v4d14)

v310 := copyKernelVersion(v5d4)
v310.Version = "3.10.0"
v310.InstrumentFunctions[bpf.AgentStepTIP_OUT] =
[]InstrumentFunction{{"kprobe/ip_queue_xmit", "IpQueueXmit2"}}
v310.addBackupInstrumentFunction(bpf.AgentStepTIP_IN, InstrumentFunction{"kprobe/ip_rcv", "IpRcvCore"})
[]InstrumentFunction{MakeInstrumentFunction("kprobe/ip_queue_xmit", "IpQueueXmit2")}
v310.addBackupInstrumentFunction(bpf.AgentStepTIP_IN, MakeBackupInstrumentFunction("kprobe/ip_rcv", "IpRcvCore"))
v310.removeCapability(SupportConstants).
removeCapability(SupportRawTracepoint).
removeCapability(SupportXDP).
Expand Down
3 changes: 3 additions & 0 deletions bpf/agent_arm64_bpfel.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions bpf/agent_x86_bpfel.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions bpf/agentlagacykernel310_arm64_bpfel.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions bpf/agentlagacykernel310_x86_bpfel.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions bpf/loader/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -509,14 +509,18 @@ func attachBpfProgs(ifName string, kernelVersion *compatible.KernelVersion, opti
if isNonCriticalStep {
common.AgentLog.Debugf("Attach failed: %v, functions: %v skip it because it's a non-criticalstep", err, functions)
} else {
return nil, fmt.Errorf("Attach failed: %v, functions: %v", err, functions)
return nil, fmt.Errorf("attach failed: %v, functions: %v", err, functions)
}
} else {
common.AgentLog.Debugf("Attach failed but has fallback: %v, functions: %v", err, functions)
}
} else {
linkList.PushBack(l)
break
if idx < len(functions)-1 && !functions[idx+1].IsBackup() {
continue
} else {
break
}
}
}
}
Expand Down
38 changes: 18 additions & 20 deletions bpf/pktlatency.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,21 +297,16 @@ static bool __always_inline use_ipv6(struct sock_common * skc) {
static bool __always_inline parse_sock_key_sk(struct sock* sk, struct sock_key* key) {
struct sock_common *skc = {0};
skc = (struct sock_common *)sk;
bool supportIpv6 = use_ipv6(skc);
switch (_C(skc, skc_family)) {
case AF_INET:
key->dip[0] = _C(skc, skc_daddr);
key->sip[0] = _C(skc, skc_rcv_saddr);
break;
case AF_INET6:
if (supportIpv6) {
bpf_probe_read_kernel((void *)(key->dip), sizeof(struct in6_addr), (const void *)__builtin_preserve_access_index(&((typeof((skc)))((skc)))->skc_v6_daddr));
bpf_probe_read_kernel((void *)(key->sip), sizeof(struct in6_addr), (const void *)__builtin_preserve_access_index(&((typeof((skc)))((skc)))->skc_v6_rcv_saddr));
} else {
key->dip[0] = _C(skc, skc_daddr);
key->sip[0] = _C(skc, skc_rcv_saddr);
}
break;
bpf_probe_read_kernel((void *)(key->dip), sizeof(struct in6_addr), (const void *)__builtin_preserve_access_index(&((typeof((skc)))((skc)))->skc_v6_daddr.in6_u.u6_addr32));
bpf_probe_read_kernel((void *)(key->sip), sizeof(struct in6_addr), (const void *)__builtin_preserve_access_index(&((typeof((skc)))((skc)))->skc_v6_rcv_saddr.in6_u.u6_addr32));
// bpf_printk("ipv6!, sport: %d, dport: %d", _C(skc, skc_num), _C(skc, skc_dport));
break;
default:
return false;
}
Expand Down Expand Up @@ -472,7 +467,7 @@ static __always_inline int parse_skb(void* ctx, struct sk_buff *skb, bool sk_not
l3 = (void *)eth + ETH_HLEN;
BPF_CORE_READ_INTO(&l3_proto, eth, h_proto);
l3_proto = bpf_ntohs(l3_proto);
// bpf_printk("%s, l3_proto: %x",func_name, l3_proto);
// bpf_printk("test l3_proto: %x", l3_proto);
if (l3_proto == ETH_P_IP || l3_proto == ETH_P_IPV6) {
__l3:
if (!skb_l4_check(trans_header, network_header)) {
Expand Down Expand Up @@ -506,7 +501,8 @@ static __always_inline int parse_skb(void* ctx, struct sk_buff *skb, bool sk_not
}
} else if (l3_proto == ETH_P_IPV6) {
proto_l4 = _(ipv6->nexthdr);
tcp_len = _C(ipv6, payload_len);
tcp_len = bpf_ntohs(_C(ipv6, payload_len));
// bpf_printk("testipv6, tcp_len: %d", tcp_len);
l4 = l4 ? l4 : ip + sizeof(*ipv6);
}else{
goto err;
Expand Down Expand Up @@ -664,6 +660,13 @@ int BPF_KPROBE(tcp_v4_do_rcv, struct sock *sk, struct sk_buff *skb) {
parse_skb(ctx, skb, 1, TCP_IN);
return BPF_OK;
}


SEC("kprobe/tcp_v6_do_rcv")
int BPF_KPROBE(tcp_v6_do_rcv, struct sock *sk, struct sk_buff *skb) {
parse_skb(ctx, skb, 1, TCP_IN);
return BPF_OK;
}

SEC("kprobe/tcp_v4_rcv")
int BPF_KPROBE(tcp_v4_rcv, struct sk_buff *skb) {
Expand Down Expand Up @@ -890,14 +893,14 @@ static __inline void read_sockaddr_kernel(struct conn_info_t* conn_info,

conn_info->laddr.in6.sin6_port = lport;
conn_info->raddr.in6.sin6_port = rport;
if (family == AF_INET || !use_ipv6(sk_common)) {
if (family == AF_INET) {
conn_info->laddr.in6.sin6_addr.in6_u.u6_addr32[0] = _C(sk_common, skc_rcv_saddr);
conn_info->raddr.in6.sin6_addr.in6_u.u6_addr32[0] = _C(sk_common, skc_daddr);
// BPF_CORE_READ_INTO(&conn_info->laddr.in4.sin_addr.s_addr, sk_common, skc_rcv_saddr);
// BPF_CORE_READ_INTO(&conn_info->raddr.in4.sin_addr.s_addr, sk_common, skc_daddr);
} else if (family == AF_INET6) {
BPF_CORE_READ_INTO(&conn_info->laddr.in6.sin6_addr, sk_common, skc_v6_rcv_saddr);
BPF_CORE_READ_INTO(&conn_info->raddr.in6.sin6_addr, sk_common, skc_v6_daddr);
BPF_CORE_READ_INTO(&conn_info->laddr.in6.sin6_addr, sk_common, skc_v6_rcv_saddr.in6_u.u6_addr32);
BPF_CORE_READ_INTO(&conn_info->raddr.in6.sin6_addr, sk_common, skc_v6_daddr.in6_u.u6_addr32);
}
}

Expand Down Expand Up @@ -1041,7 +1044,6 @@ enum endpoint_role_t role, uint64_t start_ts) {

// print_sock_key(&key);
struct sock_common *sk_common = (struct sock_common *) tcp_sk;
bool is_ipv6 = use_ipv6(sk_common);
if (socket == NULL) {
// conn_info.laddr.in4.sin_addr.s_addr = role == kRoleClient ? key.sip : key.dip;
// conn_info.laddr.in4.sin_port = role == kRoleClient ? key.sport : key.dport;
Expand All @@ -1054,7 +1056,7 @@ enum endpoint_role_t role, uint64_t start_ts) {
uint16_t family = -1;
BPF_CORE_READ_INTO(&family, sk_common, skc_family);
// bpf_printk("AF: %d", family);
if (family == AF_INET || !is_ipv6) {
if (family == AF_INET ) {
// conn_info.laddr.in4.sin_addr.s_addr = (u32)key.sip[0] ;
// conn_info.raddr.in4.sin_addr.s_addr = (u32)key.dip[0];
conn_info.laddr.in6.sin6_addr.in6_u.u6_addr32[0] = (u32)key.sip[0];
Expand All @@ -1066,10 +1068,6 @@ enum endpoint_role_t role, uint64_t start_ts) {
conn_info.laddr.sa.sa_family = family;
conn_info.raddr.sa.sa_family = family;
}
if (!use_ipv6(sk_common)) {
conn_info.laddr.sa.sa_family = AF_INET;
conn_info.raddr.sa.sa_family = AF_INET;
}

// bpf_printk("submit_new_conn laddr: port:%u", conn_info.laddr.in4.sin_port);
// bpf_printk("submit_new_conn raddr: port:%u", conn_info.raddr.in4.sin_port);
Expand Down
25 changes: 25 additions & 0 deletions testdata/test_ipv6.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env bash
. $(dirname "$0")/common.sh
set -ex

CMD="$1"
FILE_PREFIX="/tmp/kyanos"
CLIENT_LNAME="${FILE_PREFIX}_ipv6_client.log"


function test_client() {
# client start after kyanos
timeout 30 ${CMD} watch --debug-output http --comm curl --trace-ssl-event=false 2>&1 | tee "${CLIENT_LNAME}" &
sleep 15
curl -6 'http://ipv6.baidu.com' &>/dev/null || true
wait

cat "${CLIENT_LNAME}"
cat "${CLIENT_LNAME}" | grep "Host: ipv6.baidu.com"
}

function main() {
test_client
}

main

0 comments on commit 9a8c64d

Please sign in to comment.