Created
November 24, 2018 01:44
-
-
Save dalehamel/2b34a12e66c1975345b7582911db6a0f to your computer and use it in GitHub Desktop.
Re-implement several tcp.* utils from iovisor/bcc in bpftrace (with some limitations)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bpftrace | |
/* | |
Watches for all ipv4 tcp accepts, displays: | |
- remote and local addresses of the accepted connection | |
- accept queue size and maximum | |
*/ | |
#include <linux/tcp.h> | |
#include <net/sock.h> | |
BEGIN | |
{ | |
printf("Tracing tcp accepts. Hit Ctrl-C to end.\n"); | |
printf("%-8s %-16s %-8s ", "TIME", "COMM", "PID"); | |
printf("%-21s %-20s %-6s %-6s\n", "DEST:PORT", "SRC:PORT", "QLEN", "QMAX") | |
} | |
kretprobe:inet_csk_accept | |
{ | |
$sk = ((sock *) retval); | |
if ($sk->__sk_common.skc_family ==2) { | |
$daddr = $sk->__sk_common.skc_daddr; | |
$saddr = $sk->__sk_common.skc_rcv_saddr; | |
$lport = $sk->__sk_common.skc_num; | |
$dport = $sk->__sk_common.skc_dport; | |
$qlen = $sk->sk_ack_backlog; | |
$qmax = $sk->sk_max_ack_backlog; | |
// Destination port is big endian, it must be flipped | |
$flipmask=0x00FF00; // shifting left doesn't truncate so we must manually | |
$dport = ($dport >> 8) | (($dport << 8) & $flipmask); | |
$mask1 = 0x000000FF; | |
$mask2 = 0x0000FF00; | |
$mask3 = 0x00FF0000; | |
$mask4 = 0xFF000000; | |
$d_q1 = ($daddr & $mask1) >> 0; | |
$d_q2 = ($daddr & $mask2) >> 8; | |
$d_q3 = ($daddr & $mask3) >> 16; | |
$d_q4 = ($daddr & $mask4) >> 24; | |
$s_q1 = ($saddr & $mask1) >> 0; | |
$s_q2 = ($saddr & $mask2) >> 8; | |
$s_q3 = ($saddr & $mask3) >> 16; | |
$s_q4 = ($saddr & $mask4) >> 24; | |
time("%H:%M:%S "); | |
printf("%-16s %-8d ", comm, pid); | |
printf("%d.%d.%d.%d:%-4d\t", $d_q1, $d_q2, $d_q3, $d_q4, $dport); | |
printf("%d.%d.%d.%d:%-10d ", $s_q1, $s_q2, $s_q3, $s_q4, $lport); | |
printf("%d %d\n", $qlen, $qmax); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bpftrace | |
/* | |
Watches for outgoing tcp connections | |
*/ | |
#include <linux/tcp.h> | |
#include <net/sock.h> | |
BEGIN | |
{ | |
printf("Tracing tcp connections. Hit Ctrl-C to end.\n"); | |
printf("%-8s %-16s %-8s %-20s %-20s\n", "TIME", "COMM", "PID", "SRC:PORT", "DEST:PORT" ) | |
} | |
kprobe:tcp_connect | |
{ | |
$sk = ((sock *) arg0); | |
if ($sk->__sk_common.skc_family ==2) { | |
$daddr = $sk->__sk_common.skc_daddr; | |
$saddr = $sk->__sk_common.skc_rcv_saddr; | |
$lport = $sk->__sk_common.skc_num; | |
$dport = $sk->__sk_common.skc_dport; | |
// Destination port is big endian, it must be flipped | |
$flipmask=0x00FF00; // shifting left doesn't truncate so we must manually | |
$dport = ($dport >> 8) | (($dport << 8) & $flipmask); | |
$mask1 = 0x000000FF; | |
$mask2 = 0x0000FF00; | |
$mask3 = 0x00FF0000; | |
$mask4 = 0xFF000000; | |
$d_q1 = ($daddr & $mask1) >> 0; | |
$d_q2 = ($daddr & $mask2) >> 8; | |
$d_q3 = ($daddr & $mask3) >> 16; | |
$d_q4 = ($daddr & $mask4) >> 24; | |
$s_q1 = ($saddr & $mask1) >> 0; | |
$s_q2 = ($saddr & $mask2) >> 8; | |
$s_q3 = ($saddr & $mask3) >> 16; | |
$s_q4 = ($saddr & $mask4) >> 24; | |
time("%H:%M:%S "); | |
printf("%-16s %-8d ", comm, pid); | |
printf("%d.%d.%d.%d:%-4d\t", $d_q1, $d_q2, $d_q3, $d_q4, $dport); | |
printf("%d.%d.%d.%d:%-8d\n", $s_q1, $s_q2, $s_q3, $s_q4, $lport); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bpftrace | |
/* | |
Watches for all tcp_drops and examines socket state | |
*/ | |
#include <linux/tcp.h> | |
#include <net/sock.h> | |
BEGIN | |
{ | |
printf("Tracing tcp drops. Hit Ctrl-C to end.\n"); | |
printf("%-8s %-16s %-8s %-20s %-20s\n", "TIME", "COMM", "PID", "DEST:PORT", "SRC:PORT") | |
} | |
kprobe:tcp_drop | |
{ | |
$sk = ((sock *) arg0); | |
if ($sk->__sk_common.skc_family ==2) { | |
$daddr = $sk->__sk_common.skc_daddr; | |
$saddr = $sk->__sk_common.skc_rcv_saddr; | |
$lport = $sk->__sk_common.skc_num; | |
$dport = $sk->__sk_common.skc_dport; | |
// Destination port is big endian, it must be flipped | |
$flipmask=0x00FF00; // shifting left doesn't truncate so we must manually | |
$dport = ($dport >> 8) | (($dport << 8) & $flipmask); | |
$mask1 = 0x000000FF; | |
$mask2 = 0x0000FF00; | |
$mask3 = 0x00FF0000; | |
$mask4 = 0xFF000000; | |
$d_q1 = ($daddr & $mask1) >> 0; | |
$d_q2 = ($daddr & $mask2) >> 8; | |
$d_q3 = ($daddr & $mask3) >> 16; | |
$d_q4 = ($daddr & $mask4) >> 24; | |
$s_q1 = ($saddr & $mask1) >> 0; | |
$s_q2 = ($saddr & $mask2) >> 8; | |
$s_q3 = ($saddr & $mask3) >> 16; | |
$s_q4 = ($saddr & $mask4) >> 24; | |
time("%H:%M:%S "); | |
printf("%-16s %-8d ", comm, pid); | |
printf("%d.%d.%d.%d:%-4d\t", $d_q1, $d_q2, $d_q3, $d_q4, $dport); | |
printf("%d.%d.%d.%d:%-8d\n", $s_q1, $s_q2, $s_q3, $s_q4, $lport); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bpftrace | |
/* | |
Watches for tcp retransmissions | |
*/ | |
#include <linux/tcp.h> | |
#include <net/sock.h> | |
BEGIN | |
{ | |
printf("Tracing tcp retransmits. Hit Ctrl-C to end.\n"); | |
printf("%-8s %-8s %-22s %-20s %s\n", "TIME", "PID", "LADDR:LPORT", "RADDR:RPORT", "STATE" ) | |
} | |
kprobe:tcp_retransmit_skb | |
{ | |
$sk = ((sock *) arg0); | |
if ($sk->__sk_common.skc_family ==2) { | |
$daddr = $sk->__sk_common.skc_daddr; | |
$saddr = $sk->__sk_common.skc_rcv_saddr; | |
$lport = $sk->__sk_common.skc_num; | |
$dport = $sk->__sk_common.skc_dport; | |
// Destination port is big endian, it must be flipped | |
$flipmask=0x00FF00; // shifting left doesn't truncate so we must manually | |
$dport = ($dport >> 8) | (($dport << 8) & $flipmask); | |
$state = $sk->__sk_common.skc_state; | |
$statestr = ""; | |
$statestr = $state == 1 ? "ESTABLISHED" : $statestr; | |
$statestr = $state == 2 ? "SYN_SENT" : $statestr; | |
$statestr = $state == 3 ? "SYN_RECV" : $statestr; | |
$statestr = $state == 4 ? "FIN_WAIT1" : $statestr; | |
$statestr = $state == 5 ? "FIN_WAIT2" : $statestr; | |
$statestr = $state == 6 ? "TIME_WAIT" : $statestr; | |
$statestr = $state == 7 ? "CLOSE" : $statestr; | |
$statestr = $state == 8 ? "CLOSE_WAIT" : $statestr; | |
$statestr = $state == 9 ? "LAST_ACK" : $statestr; | |
$statestr = $state == 10 ? "LISTEN" : $statestr; | |
$statestr = $state == 11 ? "CLOSING" : $statestr; | |
$statestr = $state == 12 ? "NEW_SYN_RECV" : $statestr; | |
$mask1 = 0x000000FF; | |
$mask2 = 0x0000FF00; | |
$mask3 = 0x00FF0000; | |
$mask4 = 0xFF000000; | |
$d_q1 = ($daddr & $mask1) >> 0; | |
$d_q2 = ($daddr & $mask2) >> 8; | |
$d_q3 = ($daddr & $mask3) >> 16; | |
$d_q4 = ($daddr & $mask4) >> 24; | |
$s_q1 = ($saddr & $mask1) >> 0; | |
$s_q2 = ($saddr & $mask2) >> 8; | |
$s_q3 = ($saddr & $mask3) >> 16; | |
$s_q4 = ($saddr & $mask4) >> 24; | |
time("%H:%M:%S "); | |
printf("%-8d ", pid); | |
printf("%d.%d.%d.%d:%-8d", $s_q1, $s_q2, $s_q3, $s_q4, $lport); | |
printf("%d.%d.%d.%d:%-8d", $d_q1, $d_q2, $d_q3, $d_q4, $dport); | |
printf("%6s\n", $statestr); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment