Skip to content
This repository has been archived by the owner on Oct 24, 2023. It is now read-only.

Commit

Permalink
WIP: trace fd_install on specific pids
Browse files Browse the repository at this point in the history
  • Loading branch information
alban committed May 11, 2017
1 parent a82fffd commit 87a544e
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 10 deletions.
9 changes: 6 additions & 3 deletions pkg/tracer/event_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ type EventType uint32

// These constants should be in sync with the equivalent definitions in the ebpf program.
const (
EventConnect EventType = 1
EventAccept = 2
EventClose = 3
EventConnect EventType = 1
EventAccept = 2
EventClose = 3
EventFdInstall = 4
)

func (e EventType) String() string {
Expand All @@ -21,6 +22,8 @@ func (e EventType) String() string {
return "accept"
case EventClose:
return "close"
case EventFdInstall:
return "fdinstall"
default:
return "unknown"
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/tracer/tcptracer-ebpf.go

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions pkg/tracer/tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package tracer
import (
"bytes"
"fmt"
"unsafe"

bpflib "github.com/iovisor/gobpf/elf"
)
Expand Down Expand Up @@ -111,6 +112,19 @@ func NewTracer(tcpEventCbV4 func(TcpV4), tcpEventCbV6 func(TcpV6), lostCb func(l
}, nil
}

func (t *Tracer) AddFdInstallWatcher(pid uint32) (err error) {
var one uint32 = 1
mapFdInstall := t.m.Map("fdinstall_pids")
err = t.m.UpdateElement(mapFdInstall, unsafe.Pointer(&pid), unsafe.Pointer(&one), 0)
return err
}

func (t *Tracer) RemoveFdInstallWatcher(pid uint32) (err error) {
mapFdInstall := t.m.Map("fdinstall_pids")
err = t.m.DeleteElement(mapFdInstall, unsafe.Pointer(&pid))
return err
}

func (t *Tracer) Stop() {
close(t.stopChan)
t.perfMapIPV4.PollStop()
Expand Down
3 changes: 3 additions & 0 deletions pkg/tracer/tracer_unsupported.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ func TracerAsset() ([]byte, error) {
func NewTracer(tcpEventCbV4 func(TcpV4), tcpEventCbV6 func(TcpV6), lostCb func(lost uint64)) (*Tracer, error) {
return nil, fmt.Errorf("not supported on non-Linux systems")
}
func (t *Tracer) AddFdInstallWatcher(pid uint32) (err error) {
return fmt.Errorf("not supported on non-Linux systems")
}

func (t *Tracer) Stop() {
}
62 changes: 62 additions & 0 deletions tcptracer-bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,26 @@ struct bpf_map_def SEC("maps/tuplepid_ipv6") tuplepid_ipv6 = {
.max_entries = 1024,
};

/* This is a key/value store with the keys being a pid
* and the values being a fd unsigned int.
*/
struct bpf_map_def SEC("maps/fdinstall_ret") fdinstall_ret = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(__u64),
.value_size = sizeof(unsigned int),
.max_entries = 1024,
};

/* This is a key/value store with the keys being a pid (tgid)
* and the values being a boolean.
*/
struct bpf_map_def SEC("maps/fdinstall_pids") fdinstall_pids = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(__u32),
.value_size = sizeof(__u32),
.max_entries = 1024,
};

/* http://stackoverflow.com/questions/1001307/detecting-endianness-programmatically-in-a-c-program */
__attribute__((always_inline))
static bool is_big_endian(void)
Expand Down Expand Up @@ -821,6 +841,48 @@ int kretprobe__inet_csk_accept(struct pt_regs *ctx)
return 0;
}

SEC("kprobe/fd_install")
int kprobe__fd_install(struct pt_regs *ctx)
{
u64 pid = bpf_get_current_pid_tgid();
u32 tgid = pid >> 32;
unsigned long fd = (unsigned long) PT_REGS_PARM1(ctx);
u32 *exists = NULL;

exists = bpf_map_lookup_elem(&fdinstall_pids, &tgid);
if (exists == NULL || !*exists)
return 0;

bpf_map_update_elem(&fdinstall_ret, &pid, &fd, BPF_ANY);

return 0;
}

SEC("kretprobe/fd_install")
int kretprobe__fd_install(struct pt_regs *ctx)
{
u64 pid = bpf_get_current_pid_tgid();
unsigned long *fd;
fd = bpf_map_lookup_elem(&fdinstall_ret, &pid);
if (fd == NULL) {
return 0; // missed entry
}
bpf_map_delete_elem(&fdinstall_ret, &pid);

u32 cpu = bpf_get_smp_processor_id();
struct tcp_ipv4_event_t evt = {
.timestamp = bpf_ktime_get_ns(),
.cpu = cpu,
.type = TCP_EVENT_TYPE_FD_INSTALL,
};
evt.pid = pid >> 32;
evt.netns = *(__u32*)fd;
bpf_get_current_comm(&evt.comm, sizeof(evt.comm));
bpf_perf_event_output(ctx, &tcp_event_ipv4, cpu, &evt, sizeof(evt));

return 0;
}

char _license[] SEC("license") = "GPL";
// this number will be interpreted by gobpf-elf-loader to set the current
// running kernel version
Expand Down
7 changes: 4 additions & 3 deletions tcptracer-bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@

#include <linux/types.h>

#define TCP_EVENT_TYPE_CONNECT 1
#define TCP_EVENT_TYPE_ACCEPT 2
#define TCP_EVENT_TYPE_CLOSE 3
#define TCP_EVENT_TYPE_CONNECT 1
#define TCP_EVENT_TYPE_ACCEPT 2
#define TCP_EVENT_TYPE_CLOSE 3
#define TCP_EVENT_TYPE_FD_INSTALL 4

#define GUESS_SADDR 0
#define GUESS_DADDR 1
Expand Down
14 changes: 12 additions & 2 deletions tests/tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"os"
"os/signal"
"strconv"

"github.com/weaveworks/tcptracer-bpf/pkg/tracer"
)
Expand Down Expand Up @@ -41,8 +42,8 @@ func lostCb(count uint64) {
}

func main() {
if len(os.Args) != 1 {
fmt.Fprintf(os.Stderr, "Usage: %s\n", os.Args[0])
if len(os.Args) > 2 {
fmt.Fprintf(os.Stderr, "Usage: %s pid\n", os.Args[0])
os.Exit(1)
}

Expand All @@ -52,6 +53,15 @@ func main() {
os.Exit(1)
}

if len(os.Args) == 2 {
pid, err := strconv.Atoi(os.Args[1])
if err != nil {
fmt.Fprintf(os.Stderr, "Invalid pid: %v\n", err)
os.Exit(1)
}
t.AddFdInstallWatcher(uint32(pid))
}

fmt.Printf("Ready\n")

sig := make(chan os.Signal, 1)
Expand Down

0 comments on commit 87a544e

Please sign in to comment.