Skip to content

Instantly share code, notes, and snippets.

@dalehamel
Created November 24, 2018 01:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dalehamel/2b34a12e66c1975345b7582911db6a0f to your computer and use it in GitHub Desktop.
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)
#!/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);
}
}
#!/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);
}
}
#!/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);
}
}
#!/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