Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ require (
github.com/cheggaaa/pb/v3 v3.1.7
github.com/cilium/ebpf v0.17.3
github.com/cloudflare/cbpfc v0.0.0-20240920015331-ff978e94500b
github.com/gdamore/tcell/v2 v2.7.1
github.com/jsimonetti/rtnetlink v1.4.2
github.com/rivo/tview v0.0.0-20241227133733-17b7edb88c57
github.com/spf13/pflag v1.0.6
github.com/tklauser/ps v0.0.3
github.com/vishvananda/netns v0.0.5
Expand All @@ -19,13 +21,17 @@ require (
require (
github.com/VividCortex/ewma v1.2.0 // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/gdamore/encoding v1.0.0 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/josharian/native v1.1.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/mdlayher/netlink v1.7.2 // indirect
github.com/mdlayher/socket v0.4.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
golang.org/x/term v0.29.0 // indirect
golang.org/x/text v0.22.0 // indirect
)
47 changes: 47 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ github.com/cloudflare/cbpfc v0.0.0-20240920015331-ff978e94500b h1:EgR1t4Lnq6uP6Q
github.com/cloudflare/cbpfc v0.0.0-20240920015331-ff978e94500b/go.mod h1:X/9cHz8JVzKlvoZyKBgMgrogKZlLf+pWjmm5gSUm5dI=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
github.com/gdamore/tcell/v2 v2.7.1 h1:TiCcmpWHiAU7F0rA2I3S2Y4mmLmO9KHxJ7E1QhYzQbc=
github.com/gdamore/tcell/v2 v2.7.1/go.mod h1:dSXtXTSK0VsW1biw65DZLZ2NKr7j0qP/0J7ONmsraWg=
github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
Expand All @@ -22,10 +26,13 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g=
Expand All @@ -34,7 +41,10 @@ github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/rivo/tview v0.0.0-20241227133733-17b7edb88c57 h1:LmsF7Fk5jyEDhJk0fYIqdWNuTxSyid2W42A0L2YWjGE=
github.com/rivo/tview v0.0.0-20241227133733-17b7edb88c57/go.mod h1:02iFIz7K/A9jGCvrizLPvoqr4cEIx7q54RH5Qudkrss=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
Expand All @@ -45,12 +55,49 @@ github.com/tklauser/ps v0.0.3 h1:mn9T6eaAb0VoWkjFGMhs1LDLiIxIArvDepEQo0CU+zU=
github.com/tklauser/ps v0.0.3/go.mod h1:Dbtzb3oSPyYLGMPrz2a5mW+CfzEP6aYugfyfvtw5zdU=
github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY=
github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/arch v0.14.0 h1:z9JUEZWr8x4rR0OU6c4/4t6E6jOZ8/QBS2bBYBm4tx4=
golang.org/x/arch v0.14.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
4 changes: 4 additions & 0 deletions internal/pwru/ksym.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ type ksym struct {
name string
}

func (k *ksym) Name() string {
return k.name
}

type byAddr []*ksym

func (a byAddr) Len() int { return len(a) }
Expand Down
8 changes: 8 additions & 0 deletions internal/pwru/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,14 @@ func getAddrByArch(event *Event, o *output) (addr uint64) {
return addr
}

func GetTupleData(event *Event, outputTCPFlags bool) (tupleData string) {
return getTupleData(event, outputTCPFlags)
}

func GetTuple(tpl Tuple, outputTCPFlags bool) (tupleData string) {
return getTuple(tpl, outputTCPFlags)
}

func getTuple(tpl Tuple, outputTCPFlags bool) (tupleData string) {
var l4Info string
if tpl.L4Proto == syscall.IPPROTO_TCP && tpl.TCPFlag != 0 && outputTCPFlags {
Expand Down
5 changes: 5 additions & 0 deletions internal/pwru/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ type Flags struct {
ReadyFile string

Backend string

OutputExperimentalTUI bool
TUIFolds string
}

func (f *Flags) SetFlags() {
Expand Down Expand Up @@ -98,6 +101,8 @@ func (f *Flags) SetFlags() {
flag.StringVar(&f.OutputFile, "output-file", "", "write traces to file")

flag.BoolVar(&f.OutputJson, "output-json", false, "output traces in JSON format")
flag.BoolVar(&f.OutputExperimentalTUI, "output-experimental-tui", false, "start experimental terminal ui")
flag.StringVar(&f.TUIFolds, "tui-folds", "tunnel.tun-dir", "folding")

flag.StringVar(&f.ReadyFile, "ready-file", "", "create file after all BPF progs are attached")
flag.Lookup("ready-file").Hidden = true
Expand Down
6 changes: 3 additions & 3 deletions internal/pwru/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,9 @@ func HaveBPFLinkTracing() bool {
return true
}

func HaveAvailableFilterFunctions() bool {
_, err := getAvailableFilterFunctions()
return err == nil
func AvailableFilterFunctions() (map[string]struct{}, bool) {
fns, err := getAvailableFilterFunctions()
return fns, err == nil
}

func HaveSnprintfBtf(kernelBtf *btf.Spec) bool {
Expand Down
43 changes: 38 additions & 5 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ import (
"errors"
"fmt"
"log"
"maps"
"os"
"os/signal"
"runtime"
"slices"
"strings"
"syscall"
"time"

Expand All @@ -22,6 +25,7 @@ import (

"github.com/cilium/pwru/internal/libpcap"
"github.com/cilium/pwru/internal/pwru"
"github.com/cilium/pwru/tui"
)

func main() {
Expand Down Expand Up @@ -89,11 +93,13 @@ func main() {
if flags.Backend != "" && (flags.Backend != pwru.BackendKprobe && flags.Backend != pwru.BackendKprobeMulti) {
log.Fatalf("Invalid tracing backend %s", flags.Backend)
}

availFuncs, haveAvailableFuncs := pwru.AvailableFilterFunctions()
// Until https://lore.kernel.org/bpf/[email protected]/
// has been backported to the stable, kprobe-multi cannot be used when attaching
// to kmods.
if flags.Backend == "" {
useKprobeMulti = pwru.HaveBPFLinkKprobeMulti() && pwru.HaveAvailableFilterFunctions()
useKprobeMulti = pwru.HaveBPFLinkKprobeMulti() && haveAvailableFuncs
} else if flags.Backend == pwru.BackendKprobeMulti {
useKprobeMulti = true
}
Expand Down Expand Up @@ -293,7 +299,7 @@ func main() {
}
defer output.Close()

if !flags.OutputJson {
if !flags.OutputJson && !flags.OutputExperimentalTUI {
output.PrintHeader()
}

Expand All @@ -305,24 +311,47 @@ func main() {
log.Printf("Printed %d events, exiting program..\n", flags.OutputLimitLines)
}
}()

var event pwru.Event
app, err := tui.New(addr2name,
strings.Split(flags.TUIFolds, "."), funcs, slices.Collect(maps.Keys(availFuncs)))
if err != nil {
log.Fatal(err)
}
ctx, cancel := context.WithCancel(context.Background())
go func() {
app.Run(context.Background())
}()
events := coll.Maps["events"]
runForever := flags.OutputLimitLines == 0

c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
<-c
fmt.Println("handle ctrl-c")
cancel()
}()

for i := flags.OutputLimitLines; i > 0 || runForever; i-- {
var event pwru.Event
for {
if err := events.LookupAndDelete(nil, &event); err == nil {
break
}
select {
case <-c:
fmt.Println("ctrl-c!")
cancel()
return
case <-ctx.Done():
return
case <-time.After(time.Microsecond):
continue
}
}

if flags.OutputJson {
if flags.OutputExperimentalTUI {
app.InsertGroup(&event)
} else if flags.OutputJson {
output.PrintJson(&event)
} else {
output.Print(&event)
Expand All @@ -331,6 +360,10 @@ func main() {
select {
case <-ctx.Done():
return
case <-c:
fmt.Println("ctrl-c!")
cancel()
return
default:
}
}
Expand Down
32 changes: 32 additions & 0 deletions tui/draw/draw.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package draw

import (
"strings"

"github.com/mattn/go-runewidth"
)

func repeatSafe(s string, n int) string {
if n < 0 {
return ""
}
return strings.Repeat(s, n)
}

func Line(w int, txt string) string {
b := "│"
tw := runewidth.StringWidth(txt)
return b + txt + repeatSafe(" ", w-2-tw) + b
}

func Break(w int) string {
return "├" + repeatSafe("─", w-2) + "┤"
}

func Header(w int) string {
return "┌" + repeatSafe("─", w-2) + "┐"
}

func Footer(w int) string {
return "└" + repeatSafe("─", w-2) + "┘"
}
Binary file added tui/main
Binary file not shown.
Loading