Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-arrange output columns #376

Merged
merged 15 commits into from
May 28, 2024
8 changes: 4 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ jobs:
traffic-setup: |
iptables -I OUTPUT 1 -m tcp --proto tcp --dst 1.0.0.1/32 --dport 8080 -j DROP
curl -vvv -sS --fail --connect-timeout "1" -o /dev/null http://1.0.0.1:8080 || true
expected-output-pattern: '(kfree_skb_reason|kfree_skb\b).*1.0.0.1:8080'
expected-output-pattern: '1.0.0.1:8080.*(kfree_skb_reason|kfree_skb\b)'

- name: Test basic IPv6
uses: ./.github/actions/pwru-test
Expand All @@ -82,7 +82,7 @@ jobs:
traffic-setup: |
ip6tables -I OUTPUT 1 -m tcp --proto tcp --dst 2606:4700:4700::1001 --dport 8080 -j DROP
curl -vvv -sS --fail --connect-timeout "1" -o /dev/null http://[2606:4700:4700::1001]:8080 || true
expected-output-pattern: '(kfree_skb_reason|kfree_skb\b).*\[2606:4700:4700::1001\]:8080'
expected-output-pattern: '\[2606:4700:4700::1001\]:8080.*(kfree_skb_reason|kfree_skb\b)'

- name: Test advanced IPv4
uses: ./.github/actions/pwru-test
Expand All @@ -92,7 +92,7 @@ jobs:
traffic-setup: |
iptables -I OUTPUT 1 -m tcp --proto tcp --dst 1.0.0.2/32 --dport 8080 -j DROP
curl -vvv -sS --fail --connect-timeout "1" -o /dev/null http://1.0.0.2:8080 || true
expected-output-pattern: '(kfree_skb_reason|kfree_skb\b).*1.0.0.2:8080'
expected-output-pattern: '1.0.0.2:8080.*(kfree_skb_reason|kfree_skb\b)'

- name: Test advanced IPv6
uses: ./.github/actions/pwru-test
Expand All @@ -102,7 +102,7 @@ jobs:
traffic-setup: |
ip6tables -I OUTPUT 1 -m tcp --proto tcp --dst 2606:4700:4700::1002 --dport 8080 -j DROP
curl -vvv -sS --fail --connect-timeout "1" -o /dev/null http://[2606:4700:4700::1002]:8080 || true
expected-output-pattern: '(kfree_skb_reason|kfree_skb\b).*\[2606:4700:4700::1002\]:8080'
expected-output-pattern: '\[2606:4700:4700::1002\]:8080.*(kfree_skb_reason|kfree_skb\b)'

- name: Test pcap filter using stack
uses: ./.github/actions/pwru-test
Expand Down
75 changes: 60 additions & 15 deletions internal/pwru/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"path/filepath"
"runtime"
"strconv"
"strings"
"syscall"
"time"

Expand Down Expand Up @@ -70,6 +71,15 @@ type jsonTuple struct {
Proto uint8 `json:"proto,omitempty"`
}

func centerAlignString(s string, width int) string {
if len(s) >= width {
return s
}
leftPadding := (width - len(s)) / 2
rightPadding := width - len(s) - leftPadding
return fmt.Sprintf("%s%s%s", strings.Repeat(" ", leftPadding), s, strings.Repeat(" ", rightPadding))
}

func NewOutput(flags *Flags, printSkbMap, printShinfoMap, printStackMap *ebpf.Map, addr2Name Addr2Name, kprobeMulti bool, btfSpec *btf.Spec) (*output, error) {
writer := os.Stdout

Expand Down Expand Up @@ -117,12 +127,19 @@ func (o *output) Close() {

func (o *output) PrintHeader() {
if o.flags.OutputTS == "absolute" {
fmt.Fprintf(o.writer, "%12s ", "TIME")
fmt.Fprintf(o.writer, "%-12s ", "TIME")
}
fmt.Fprintf(o.writer, "%18s %6s %16s %24s", "SKB", "CPU", "PROCESS", "FUNC")
fmt.Fprintf(o.writer, "%-18s %-3s %-16s", "SKB", "CPU", "PROCESS")
if o.flags.OutputTS != "none" {
fmt.Fprintf(o.writer, " %16s", "TIMESTAMP")
fmt.Fprintf(o.writer, " %-16s", "TIMESTAMP")
}
if o.flags.OutputMeta {
fmt.Fprintf(o.writer, " %-10s %-8s %16s %-6s %-5s %-5s", "NETNS", "MARK/x", centerAlignString("IFACE", 16), "PROTO", "MTU", "LEN")
}
if o.flags.OutputTuple {
fmt.Fprintf(o.writer, " %s", "TUPLE")
}
fmt.Fprintf(o.writer, " %s", "FUNC")
fmt.Fprintf(o.writer, "\n")
}

Expand Down Expand Up @@ -209,9 +226,15 @@ func getRelativeTs(event *Event, o *output) uint64 {

func getExecName(pid int) string {
p, err := ps.FindProcess(pid)
execName := fmt.Sprintf("<empty>:(%d)", pid)
execName := fmt.Sprintf("<empty>:%d", pid)
if err == nil && p != nil {
return fmt.Sprintf("%s:%d", p.ExecutablePath(), pid)
execName = fmt.Sprintf("%s:%d", p.ExecutablePath(), pid)
if len(execName) > 16 {
execName = execName[len(execName)-16:]
bexecName := []byte(execName)
bexecName[0] = '~'
execName = string(bexecName)
}
}
return execName
}
Expand Down Expand Up @@ -288,10 +311,13 @@ func getShinfoData(event *Event, o *output) (shinfoData string) {
}

func getMetaData(event *Event, o *output) (metaData string) {
metaData = fmt.Sprintf("netns=%d mark=%#x iface=%s proto=%#04x mtu=%d len=%d",
event.Meta.Netns, event.Meta.Mark,
o.getIfaceName(event.Meta.Netns, event.Meta.Ifindex),
byteorder.NetworkToHost16(event.Meta.Proto), event.Meta.MTU, event.Meta.Len)
metaData = fmt.Sprintf("%-10s %-8s %16s %#04x %-5s %-5s",
fmt.Sprintf("%d", event.Meta.Netns),
fmt.Sprintf("%x", event.Meta.Mark),
centerAlignString(o.getIfaceName(event.Meta.Netns, event.Meta.Ifindex), 16),
byteorder.NetworkToHost16(event.Meta.Proto),
fmt.Sprintf("%d", event.Meta.MTU),
fmt.Sprintf("%d", event.Meta.Len))
return metaData
}

Expand Down Expand Up @@ -321,9 +347,19 @@ func getOutFuncName(o *output, event *Event, addr uint64) string {
return outFuncName
}

var maxTupleLengthSeen int

func fprintTupleData(writer *os.File, tupleData string) {
if len(tupleData) > maxTupleLengthSeen {
maxTupleLengthSeen = len(tupleData)
}
formatter := fmt.Sprintf(" %%-%ds", maxTupleLengthSeen)
fmt.Fprintf(writer, formatter, tupleData)
}

func (o *output) Print(event *Event) {
if o.flags.OutputTS == "absolute" {
fmt.Fprintf(o.writer, "%12s ", getAbsoluteTs())
fmt.Fprintf(o.writer, "%-12s ", getAbsoluteTs())
}

execName := getExecName(int(event.PID))
Expand All @@ -338,10 +374,10 @@ func (o *output) Print(event *Event) {

outFuncName := getOutFuncName(o, event, addr)

fmt.Fprintf(o.writer, "%18s %6s %16s %24s", fmt.Sprintf("%#x", event.SAddr),
fmt.Sprintf("%d", event.CPU), fmt.Sprintf("[%s]", execName), outFuncName)
fmt.Fprintf(o.writer, "%-18s %-3s %-16s", fmt.Sprintf("%#x", event.SAddr),
fmt.Sprintf("%d", event.CPU), fmt.Sprintf("%s", execName))
if o.flags.OutputTS != "none" {
fmt.Fprintf(o.writer, " %16d", ts)
fmt.Fprintf(o.writer, " %-16d", ts)
}
o.lastSeenSkb[event.SAddr] = event.Timestamp

Expand All @@ -350,9 +386,11 @@ func (o *output) Print(event *Event) {
}

if o.flags.OutputTuple {
fmt.Fprintf(o.writer, " %s", getTupleData(event))
fprintTupleData(o.writer, getTupleData(event))
}

fmt.Fprintf(o.writer, " %s", outFuncName)

if o.flags.OutputStack && event.PrintStackId > 0 {
fmt.Fprintf(o.writer, "%s", getStackData(event, o))
}
Expand All @@ -371,7 +409,14 @@ func (o *output) Print(event *Event) {
func (o *output) getIfaceName(netnsInode, ifindex uint32) string {
if ifaces, ok := o.ifaceCache[uint64(netnsInode)]; ok {
if name, ok := ifaces[ifindex]; ok {
return fmt.Sprintf("%d(%s)", ifindex, name)
ifname := fmt.Sprintf("%s:%d", name, ifindex)
if len(ifname) > 16 {
ifname = ifname[len(ifname)-16:]
bifname := []byte(ifname)
bifname[0] = '~'
ifname = string(bifname)
}
return ifname
}
}
return fmt.Sprintf("%d", ifindex)
Expand Down
Loading