Skip to content

Instantly share code, notes, and snippets.

@StoneMoe
Forked from iAklis/traceicmpsoftirq.py
Created December 19, 2019 11:07
Show Gist options
  • Save StoneMoe/cdd6ea110cbbfbcb29a7ef91bc5c9469 to your computer and use it in GitHub Desktop.
Save StoneMoe/cdd6ea110cbbfbcb29a7ef91bc5c9469 to your computer and use it in GitHub Desktop.
ICMP packet tracer using BCC
#!/usr/bin/python
bpf_text = """
#include <linux/ptrace.h>
#include <linux/sched.h> /* For TASK_COMM_LEN */
#include <linux/icmp.h>
#include <linux/netdevice.h>
struct probe_icmp_data_t
{
u64 timestamp_ns;
u32 tgid;
u32 pid;
char comm[TASK_COMM_LEN];
u16 v0;
};
BPF_PERF_OUTPUT(probe_icmp_events);
static inline unsigned char *my_skb_transport_header(const struct sk_buff *skb)
{
unsigned char *head;
u16 ts;
bpf_probe_read(&ts, sizeof(ts), &skb->transport_header);
bpf_probe_read(&head, sizeof(head), &skb->head);
return (unsigned char*)(head + ts);
}
static inline struct icmphdr *my_icmp_hdr(const struct sk_buff *skb)
{
return (struct icmphdr *)my_skb_transport_header(skb);
}
int probe_icmp(struct pt_regs *ctx, struct sk_buff *skb)
{
u64 __pid_tgid = bpf_get_current_pid_tgid();
u32 __tgid = __pid_tgid >> 32;
u32 __pid = __pid_tgid; // implicit cast to u32 for bottom half
struct probe_icmp_data_t __data = {0};
__data.timestamp_ns = bpf_ktime_get_ns();
__data.tgid = __tgid;
__data.pid = __pid;
bpf_get_current_comm(&__data.comm, sizeof(__data.comm));
__be16 seq;
bpf_probe_read(&seq, sizeof(seq), &my_icmp_hdr(skb)->un.echo.sequence);
__data.v0 = ntohs(seq);
probe_icmp_events.perf_submit(ctx, &__data, sizeof(__data));
return 0;
}
"""
from bcc import BPF
import ctypes as ct
class Data_icmp(ct.Structure):
_fields_ = [
("timestamp_ns", ct.c_ulonglong),
("tgid", ct.c_uint),
("pid", ct.c_uint),
("comm", ct.c_char * 16), # TASK_COMM_LEN
('v0', ct.c_ushort),
]
b = BPF(text=bpf_text)
rtt = 0
def print_icmp_event(cpu, data, size):
global rtt
#event = b["probe_icmp_events"].event(data)
event = ct.cast(data, ct.POINTER(Data_icmp)).contents
print("%-7d %-7d %-15s %s --\t\t %-16d" %
(event.tgid, event.pid,
event.comm.decode('utf-8', 'replace'),
event.v0, (event.timestamp_ns - rtt)/1000000))
rtt = event.timestamp_ns
b.attach_kprobe(event="icmp_echo", fn_name="probe_icmp")
b["probe_icmp_events"].open_perf_buffer(print_icmp_event)
while 1:
try:
b.kprobe_poll()
except KeyboardInterrupt:
exit()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment