-
Notifications
You must be signed in to change notification settings - Fork 286
/
superping.bt
executable file
·105 lines (98 loc) · 2.83 KB
/
superping.bt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#!/usr/local/bin/bpftrace
/*
* superping - Measure ICMP echo times from the network stack.
*
* See BPF Performance Tools, Chapter 10, for an explanation of this tool.
*
* Copyright (c) 2019 Brendan Gregg.
* Licensed under the Apache License, Version 2.0 (the "License").
* This was originally created for the BPF Performance Tools book
* published by Addison Wesley. ISBN-13: 9780136554820
* When copying or porting, include this comment.
*
* 20-Apr-2019 Brendan Gregg Created this.
*/
#include <linux/skbuff.h>
#include <linux/icmp.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/in.h>
BEGIN
{
printf("Tracing ICMP ping latency. Hit Ctrl-C to end.\n");
}
/*
* IPv4
*/
kprobe:ip_send_skb
{
$skb = (struct sk_buff *)arg1;
// get IPv4 header; see skb_network_header():
$iph = (struct iphdr *)($skb->head + $skb->network_header);
if ($iph->protocol == IPPROTO_ICMP) {
// get ICMP header; see skb_transport_header():
$icmph = (struct icmphdr *)($skb->head +
$skb->transport_header);
if ($icmph->type == ICMP_ECHO) {
$id = $icmph->un.echo.id;
$seq = $icmph->un.echo.sequence;
@start[$id, $seq] = nsecs;
}
}
}
kprobe:icmp_rcv
{
$skb = (struct sk_buff *)arg0;
// get ICMP header; see skb_transport_header():
$icmph = (struct icmphdr *)($skb->head + $skb->transport_header);
if ($icmph->type == ICMP_ECHOREPLY) {
$id = $icmph->un.echo.id;
$seq = $icmph->un.echo.sequence;
$start = @start[$id, $seq];
if ($start > 0) {
$idhost = ($id >> 8) | (($id << 8) & 0xff00);
$seqhost = ($seq >> 8) | (($seq << 8) & 0xff00);
printf("IPv4 ping, ID %d seq %d: %d us\n",
$idhost, $seqhost, (nsecs - $start) / 1000);
delete(@start[$id, $seq]);
}
}
}
/*
* IPv6
*/
kprobe:ip6_send_skb
{
$skb = (struct sk_buff *)arg0;
// get IPv6 header; see skb_network_header():
$ip6h = (struct ipv6hdr *)($skb->head + $skb->network_header);
if ($ip6h->nexthdr == IPPROTO_ICMPV6) {
// get ICMP header; see skb_transport_header():
$icmp6h = (struct icmp6hdr *)($skb->head +
$skb->transport_header);
if ($icmp6h->icmp6_type == ICMPV6_ECHO_REQUEST) {
$id = $icmp6h->icmp6_dataun.u_echo.identifier;
$seq = $icmp6h->icmp6_dataun.u_echo.sequence;
@start[$id, $seq] = nsecs;
}
}
}
kprobe:icmpv6_rcv
{
$skb = (struct sk_buff *)arg0;
// get ICMPv6 header; see skb_transport_header():
$icmp6h = (struct icmp6hdr *)($skb->head + $skb->transport_header);
if ($icmp6h->icmp6_type == ICMPV6_ECHO_REPLY) {
$id = $icmp6h->icmp6_dataun.u_echo.identifier;
$seq = $icmp6h->icmp6_dataun.u_echo.sequence;
$start = @start[$id, $seq];
if ($start > 0) {
$idhost = ($id >> 8) | (($id << 8) & 0xff00);
$seqhost = ($seq >> 8) | (($seq << 8) & 0xff00);
printf("IPv6 ping, ID %d seq %d: %d us\n",
$idhost, $seqhost, (nsecs - $start) / 1000);
delete(@start[$id, $seq]);
}
}
}
END { clear(@start); }