Skip to content

Commit 816261f

Browse files
committed
Improve comm output. Improve docs.
1 parent d76446a commit 816261f

File tree

4 files changed

+22
-19
lines changed

4 files changed

+22
-19
lines changed

README.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111

1212
pktstat-bpf is a simple replacement for ncurses/libpcap-based [pktstat](https://github.com/dleonard0/pktstat), using Linux eBPF ([extended Berkeley Packet Filter](https://prototype-kernel.readthedocs.io/en/latest/bpf/)) program, allowing packet statistics gathering even under **very high traffic volume** conditions, typically several million packets per second even on an average server. In this scenario (high volume, DoS attacks etc.) typically regular packet capture solutions start being unreliable due to increasing packet loss.
1313

14-
By default it uses **TC** (Traffic Control) eBPF hooks with TCX attaching requiring at minimum Linux kernel **v6.6** for both ingress and egress traffic statistics. Alternatively it can switch to [XDP](https://github.com/xdp-project/xdp-tutorial) (eXpress Data Path) hook but with a consequence of **losing egress statistics** since **XDP** works only in ingress path. XDP mode due to XDP program to network interface attaching calls requires at minimum Linux kernel **v5.9**. Some distributions might have backported XDP/TC patches (notable example is Red Hat Enterprise Linux kernel) and eBPF program might work on older kernels too.
14+
By default it uses **TC** (Traffic Control) eBPF hooks with TCX attaching requiring at minimum Linux kernel **v6.6** for both ingress and egress traffic statistics for TCP, UDP, ICMPv4 and ICMPv6. It can also switch to even faster [XDP](https://github.com/xdp-project/xdp-tutorial) (eXpress Data Path) hook but with a consequence of **losing egress statistics** since **XDP** works only in ingress path. XDP mode due to XDP program to network interface attaching calls requires at minimum Linux kernel **v5.9**. Some distributions might have backported XDP/TC patches (notable example is Red Hat Enterprise Linux kernel) and eBPF program might work on older kernels too.
15+
16+
Alternatively it can use **KProbes** to monitor TCP, UDP, ICMPv4 and ICMPv6 communication throughout all containers, K8s pods, translations and forwards and display process ID as well as process name, if the traffic was being sent or delivered to userspace application. KProbes traditionally work the slowest, being closest to the userspace -- but they bring sometimes useful process information.
1517

1618
At the end of the execution program will display per-IP and per-protocol statistics sorted by per-connection bps, packets and (source-IP:port, destination-IP:port) tuples.
1719

@@ -37,7 +39,7 @@ The following table maps features, requirements and expected performance for des
3739
| --------------------------------------------------- | ------- | ------ | -------------- | ---------------- | --------------- | ----------------- |
3840
| Generic [PCAP](https://github.com/dkorunic/pktstat) | Yes | Yes | Low | No | Any | No |
3941
| [AF_PACKET](https://github.com/dkorunic/pktstat) | Yes | Yes | Medium | No | v2.2 | No |
40-
| Kprobes | Yes | Yes | Medium+ | **Yes** | v2.6 | No |
42+
| KProbes | Yes | Yes | Medium+ | **Yes** | v2.6 | No |
4143
| TC | Yes | Yes | **High** | No | v6.6 | No |
4244
| XDP Generic | Yes | **No** | **High** | No | v5.9 | No |
4345
| XDP Native | Yes | **No** | **Very high** | No | v5.9 | No |

flags.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ const (
4040

4141
var (
4242
ifname, xdpMode *string
43-
jsonOutput, version, help, useXDP, useKprobes *bool
43+
jsonOutput, version, help, useXDP, useKProbes *bool
4444
timeout *time.Duration
4545
xdpAttachFlags link.XDPAttachFlags
4646
)
@@ -51,7 +51,7 @@ func parseFags() {
5151
help = fs.Bool('?', "help", "display help")
5252
jsonOutput = fs.Bool('j', "json", "if true, output in JSON format")
5353
useXDP = fs.Bool('x', "xdp", "if true, use XDP instead of TC (this disables egress statistics)")
54-
useKprobes = fs.Bool('k', "kprobes", "if true, use kprobes for per-proces TCP/UDP statistics")
54+
useKProbes = fs.Bool('k', "kprobes", "if true, use KProbes for per-proces TCP/UDP statistics")
5555

5656
version = fs.BoolLong("version", "display program version")
5757

main.go

+9-9
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ func main() {
6868
}()
6969

7070
switch {
71-
// Kprobes w/ PID tracking
72-
case *useKprobes:
71+
// KProbes w/ PID tracking
72+
case *useKProbes:
7373
hooks := []kprobeHook{
7474
{kprobe: "tcp_sendmsg", prog: objs.TcpSendmsg},
7575
{kprobe: "tcp_cleanup_rbuf", prog: objs.TcpCleanupRbuf},
@@ -81,7 +81,7 @@ func main() {
8181
{kprobe: "icmpv6_rcv", prog: objs.Icmpv6Rcv},
8282
}
8383

84-
links = startKprobes(hooks, links)
84+
links = startKProbes(hooks, links)
8585
// XDP
8686
case *useXDP:
8787
links = startXDP(objs, iface, links)
@@ -125,28 +125,28 @@ func main() {
125125
}
126126
}
127127

128-
// startKprobes attaches a series of eBPF programs to kernel functions using Kprobes.
128+
// startKProbes attaches a series of eBPF programs to kernel functions using KProbes.
129129
//
130130
// This function iterates over a slice of kprobeHook structs, each containing a kernel function
131131
// name (kprobe) and an associated eBPF program. It attempts to attach each eBPF program to its
132-
// respective kernel function using Kprobes. If a Kprobe cannot be attached, an error message
132+
// respective kernel function using KProbes. If a Kprobe cannot be attached, an error message
133133
// is logged, but the function continues with the next Kprobe.
134134
//
135-
// The function first checks if Kprobes are supported by the current kernel. If not supported,
135+
// The function first checks if KProbes are supported by the current kernel. If not supported,
136136
// it logs a fatal error and terminates the program.
137137
//
138138
// Parameters:
139139
//
140140
// hooks []kprobeHook: A slice of kprobeHook structs, where each struct contains a kernel
141141
// function name and an associated eBPF program.
142142
//
143-
// links []link.Link: A slice of link.Link objects to which successfully attached Kprobes
143+
// links []link.Link: A slice of link.Link objects to which successfully attached KProbes
144144
// are appended.
145145
//
146146
// Returns:
147147
//
148-
// []link.Link: The updated slice of link.Link objects, including any newly attached Kprobes.
149-
func startKprobes(hooks []kprobeHook, links []link.Link) []link.Link {
148+
// []link.Link: The updated slice of link.Link objects, including any newly attached KProbes.
149+
func startKProbes(hooks []kprobeHook, links []link.Link) []link.Link {
150150
var l link.Link
151151

152152
err := features.HaveProgramType(ebpf.Kprobe)

output.go

+7-6
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const (
3838
Mbps = 1000 * Kbps
3939
Gbps = 1000 * Mbps
4040
Tbps = 1000 * Gbps
41-
KernelComm = "kernel"
41+
KernelComm = "[kernel]"
4242
)
4343

4444
// processMap generates statEntry objects from an ebpf.Map using the provided start time.
@@ -120,7 +120,7 @@ func outputPlain(m []statEntry) {
120120
formatBitrate(v.Bitrate), v.Packets, v.Bytes, v.Proto, v.SrcIP, v.SrcPort, v.DstIP, v.DstPort))
121121
}
122122

123-
if *useKprobes {
123+
if *useKProbes {
124124
sb.WriteString(fmt.Sprintf(", pid: %d, comm: %v", v.Pid, v.Comm))
125125
}
126126

@@ -149,16 +149,17 @@ func outputJSON(m []statEntry) {
149149
// Otherwise, it creates a new byte slice, copies the input byte slice into it,
150150
// trims any null bytes from the end of the slice, and returns the result as a string.
151151
func comm2String(bs []int8) string {
152-
if len(bs) == 0 {
153-
return KernelComm
154-
}
155-
156152
b := make([]byte, len(bs))
157153
for i, v := range bs {
158154
b[i] = byte(v)
159155
}
160156

157+
// trim excess NULLs
161158
b = bytes.Trim(b, "\x00")
162159

160+
if len(b) == 0 {
161+
return KernelComm
162+
}
163+
163164
return string(b)
164165
}

0 commit comments

Comments
 (0)