Thursday, September 16, 2021

BPFTrace 範例

BPFTrace
Install and compile
sudo apt-get update
sudo apt-get install -y bison cmake flex g++ git libelf-dev zlib1g-dev libfl-dev systemtap-sdt-dev binutils-dev
sudo apt-get install -y llvm-7-dev llvm-7-runtime libclang-7-dev clang-7
git clone https://github.com/iovisor/bpftrace
mkdir bpftrace/build; cd bpftrace/build;
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j8

make install 

TCP/UDP Tracing

sudo bpftrace -e "$(cat udp_sendmsg2.bt)"
sudo bpftrace -e "$(cat udpconnect.bt)"
sudo python trace.py -I 'net/sock.h' 'udp_sendmsg(struct sock *sk) "daddr: %s, dport: %d", sk->sk_daddr, sk->sk_dport'

sudo bpftrace -e 'k:tcp_sendmsg,k:tcp_recvmsg {@[func,pid,tid,comm,args] = count();}'
sudo bpftrace -e 'k:tcp_sendmsg,k:tcp_recvmsg { @[func, pid, tid, comm] = count(); }'
sudo tcpdump -i any 'dst host 10.217.1.80 or dst host 10.217.1.50 or dst host 10.103.221.119 or dst host 10.110.176.166'

USDT Tracing
sudo bpftrace -e 'usdt:/full-path-to/tracetest:testprobe { printf("%d: time is %d\n", pid, arg0); }'

sudo python tools/trace.py 'u:/home/f1/iii/test/passthrough/dpdk/dpdk-20.02.0-rc0/build/build/app/test-pmd/testpmd:test-probe-exit "%u", arg1' -p $(pidof testpmd)
sudo python tools/trace.py 'u:/home/f1/iii/test/passthrough/dpdk/dpdk-20.02.0-rc0/build/build/app/test-pmd/testpmd:test-probe-tx "%u %u %u %u", arg1, arg2, arg3, arg4' -p $(pidof testpmd)
sudo python tools/trace.py 'u:/home/f1/iii/test/passthrough/dpdk/dpdk-20.02.0-rc0/build/build/app/test-pmd/testpmd:test-probe-rx "%u %u %u %u", arg1, arg2, arg3, arg4' -p $(pidof testpmd)

The example of udp_sendmsg.bt
#!/usr/bin/env bpftrace
#include <net/sock.h>
k:udp_sendmsg
{
@sk[tid] = arg0;
@size[tid] = arg2;
}
kr:udp_sendmsg
/@sk[tid]/
{
$sk = (struct sock *)@sk[tid];
$size = @size[tid];
$af = $sk->__sk_common.skc_family;
if ($af == AF_INET) {
$daddr = ntop($af, $sk->__sk_common.skc_daddr);
$saddr = ntop($af, $sk->__sk_common.skc_rcv_saddr);
$lport = $sk->__sk_common.skc_num;
$dport = $sk->__sk_common.skc_dport;
$dport = ($dport >> 8) | (($dport << 8) & 0xff00);
printf("%-15s %-5d -> %-15s %-5d: %d bytes, retval %d\n",
$saddr, $lport, $daddr, $dport, $size, retval);
} else {
printf("IPv6...\n");
}
delete(@sk[tid]);
delete(@size[tid]);
}

The example of udp_sendmsg.bt
#!/usr/local/bin/bpftrace
#include <net/sock.h>
k:tcp_sendmsg
{
@sk[tid] = arg0;
@size[tid] = arg2;
}
kr:tcp_sendmsg
/@sk[tid]/
{
$sk = (struct sock *)@sk[tid];
$size = @size[tid];
$af = $sk->__sk_common.skc_family;
if ($af == AF_INET) {
$daddr = ntop($af, $sk->__sk_common.skc_daddr);
$saddr = ntop($af, $sk->__sk_common.skc_rcv_saddr);
$lport = $sk->__sk_common.skc_num;
$dport = $sk->__sk_common.skc_dport;
$dport = ($dport >> 8) | (($dport << 8) & 0xff00);
printf("%-15s %-5d -> %-15s %-5d: %d bytes, retval %d\n",
$saddr, $lport, $daddr, $dport, $size, retval);
} else {
printf("IPv6...\n");
}
delete(@sk[tid]);
delete(@size[tid]);
}
The example of udp_sendmsg.bt
#!/usr/bin/env bpftrace
#include <uapi/linux/ptrace.h>
//#include <arpa/inet.h>
#include <linux/socket.h>
#include <net/sock.h>
#include <net/inet_sock.h>
#include <linux/time.h>
#include <linux/sched.h>
// data structs
/*
struct in_addr {
u32 s_addr; // that's a 32-bit int (4 bytes)
};
struct sockaddr_in {
u16 sin_family; // Address family, AF_INET
u16 sin_port; // Port number
struct in_addr sin_addr; // Internet address
u8 sin_zero[8]; // same size as struct sockaddr
};
*/
BEGIN
{
printf("Tracing ANS-TCP. Hit Ctrl-C to end.\n");
printf("%-9s %-16s %-8s %-8s --- ", "TIME", "COMM", "PID", "TID");
printf("%-10s %-10s %-10s --- %-16s %-16s ------ ", "sockfd", "len", "flags", "ip", "port");
// printf("%-6s %s\n", "LATMS", "NAME-TID");
printf("\n");
}
k:udp_sendmsg
//uprobe:/home/f1/iii/test/passthrough/dpdk/ANS/dpdk-ans/test/dpdk_tcp_client/build/dpdk_tcp_client:anssock_sendto
//uprobe:/home/f1/iii/test/passthrough/dpdk/ANS/dpdk-ans/test/dpdk_tcp_client/build/dpdk_tcp_client:anssock_recvfrom
//uprobe:/home/f1/iii/test/passthrough/dpdk/ANS/dpdk-ans/ans/build/ans:sendto
{
@start[tid] = nsecs;
@name[tid] = arg0;
$sockfd = arg0;
$len = arg2;
$flags = arg3;
$sa = (struct sockaddr_in *)arg4;
$ip = ntop(AF_INET, $sa->sin_addr.s_addr);
$port = ($sa->sin_port >> 8) | (($sa->sin_port << 8) & 0x00FF00);
time("%H:%M:%S ");
printf("%-16s %-8d %-8d --- ", comm, pid, tid);
printf("%-10d %-10d %-10d --- %-16s %-16d ------ ", $sockfd, $len, $flags, $ip, $port);
}
kr:udp_sendmsg
//uretprobe:/home/f1/iii/test/passthrough/dpdk/ANS/dpdk-ans/test/dpdk_tcp_client/build/dpdk_tcp_client:anssock_sendto
//uretprobe:/home/f1/iii/test/passthrough/dpdk/ANS/dpdk-ans/test/dpdk_tcp_client/build/dpdk_tcp_client:anssock_recvfrom
//uretprobe:/home/f1/iii/test/passthrough/dpdk/ANS/dpdk-ans/ans/build/ans:sendto
{
$latms = (nsecs - @start[tid]) / 1000000;
// printf("%-6d %s\n", $latms, str(@name[tid]));
printf("\n");
delete(@start[tid]);
delete(@name[tid]);
}
Run kubectl trace with bpftrace file
kubectl trace run ubuntu1804-k8s-2 -f tcp_sendmsg.bt
kubectl trace get fbb5344b-56e4-11ea-8ab8-5254004337db
kubectl trace attach fbb5344b-56e4-11ea-8ab8-5254004337db
kubectl trace logs fbb5344b-56e4-11ea-8ab8-5254004337db -f --timestamps
kubectl trace delete fbb5344b-56e4-11ea-8ab8-5254004337db

No comments: