Skip to content

Commit c4bdfb4

Browse files
committed
Allow table sorting
1 parent 93773a6 commit c4bdfb4

File tree

3 files changed

+81
-9
lines changed

3 files changed

+81
-9
lines changed

main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ func main() {
120120

121121
<-c1.Done()
122122

123-
m, err := processMap(objs.PktCount, startTime)
123+
m, err := processMap(objs.PktCount, startTime, bitrateSort)
124124
if err != nil {
125125
log.Fatalf("Error reading eBPF map: %v", err)
126126
}

output.go

+55-2
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ const (
4545
// Parameters:
4646
//
4747
// m *ebpf.Map - the eb
48-
func processMap(m *ebpf.Map, start time.Time) ([]statEntry, error) {
48+
func processMap(m *ebpf.Map, start time.Time, sortFunc func([]statEntry)) ([]statEntry, error) {
4949
var (
5050
key counterStatkey
5151
val counterStatvalue
@@ -71,11 +71,64 @@ func processMap(m *ebpf.Map, start time.Time) ([]statEntry, error) {
7171
})
7272
}
7373

74+
sortFunc(stats)
75+
76+
return stats, iter.Err()
77+
}
78+
79+
// bitrateSort sorts a slice of statEntry objects by their Bitrate field in descending order.
80+
//
81+
// Parameters:
82+
//
83+
// stats []statEntry - the slice of statEntry objects to be sorted
84+
func bitrateSort(stats []statEntry) {
7485
sort.Slice(stats, func(i, j int) bool {
7586
return stats[i].Bitrate > stats[j].Bitrate
7687
})
88+
}
7789

78-
return stats, iter.Err()
90+
// packetSort sorts a slice of statEntry objects by their Packets field in descending order.
91+
//
92+
// Parameters:
93+
//
94+
// stats []statEntry - the slice of statEntry objects to be sorted
95+
func packetSort(stats []statEntry) {
96+
sort.Slice(stats, func(i, j int) bool {
97+
return stats[i].Packets > stats[j].Packets
98+
})
99+
}
100+
101+
// bytesSort sorts a slice of statEntry objects by their Bytes field in descending order.
102+
//
103+
// Parameters:
104+
//
105+
// stats []statEntry - the slice of statEntry objects to be sorted
106+
func bytesSort(stats []statEntry) {
107+
sort.Slice(stats, func(i, j int) bool {
108+
return stats[i].Bytes > stats[j].Bytes
109+
})
110+
}
111+
112+
// srcIPSort sorts a slice of statEntry objects by their SrcIP field in descending order.
113+
//
114+
// Parameters:
115+
//
116+
// stats []statEntry - the slice of statEntry objects to be sorted
117+
func srcIPSort(stats []statEntry) {
118+
sort.Slice(stats, func(i, j int) bool {
119+
return stats[i].SrcIP.Compare(stats[j].SrcIP) < 0
120+
})
121+
}
122+
123+
// dstIPSort sorts a slice of statEntry objects by their DstIP field in descending order.
124+
//
125+
// Parameters:
126+
//
127+
// stats []statEntry - the slice of statEntry objects to be sorted
128+
func dstIPSort(stats []statEntry) {
129+
sort.Slice(stats, func(i, j int) bool {
130+
return stats[i].DstIP.Compare(stats[j].DstIP) < 0
131+
})
79132
}
80133

81134
// formatBitrate formats the bitrate value into a human-readable string.

tui.go

+25-6
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import (
5050
// do nothing.
5151
func drawTUI(objs counterObjects, startTime time.Time) {
5252
app := tview.NewApplication()
53+
tableSort := bitrateSort
5354

5455
// packet statistics
5556
statsTable := tview.NewTable().
@@ -64,9 +65,25 @@ func drawTUI(objs counterObjects, startTime time.Time) {
6465

6566
statsTable.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
6667
switch event.Rune() {
68+
case '0':
69+
tableSort = bitrateSort
70+
statsTable.Select(0, 0)
71+
case '1':
72+
tableSort = packetSort
73+
statsTable.Select(0, 0)
74+
case '2':
75+
tableSort = bytesSort
76+
statsTable.Select(0, 0)
77+
case '3':
78+
tableSort = srcIPSort
79+
statsTable.Select(0, 0)
80+
case '4':
81+
tableSort = dstIPSort
82+
statsTable.Select(0, 0)
6783
case 'q', 'x', 'Q', 'X':
6884
app.Stop()
69-
case 'r', 'R', 'l', 'L':
85+
case 'r', 'R':
86+
statsTable.Select(0, 0)
7087
app.ForceDraw()
7188
}
7289

@@ -90,16 +107,16 @@ func drawTUI(objs counterObjects, startTime time.Time) {
90107
// navigation
91108
naviView := tview.NewTextView().
92109
SetTextColor(tcell.ColorYellow)
93-
naviView.SetText("Use cursor keys to move through the table. Press 'q' or 'x' to exit. Press 'r' or 'l' for a redraw.")
110+
naviView.SetText("Use cursor keys to move through the table. Press 'q' or 'x' to exit, 'r' for a jump to the beginning and a redraw.\nPress '0' for bitrate desc sort, '1' for packet desc sort, '2' for bytes desc sort, '3' for source IP asc sort, '4' for destination IP asc sort.")
94111

95112
// grid layout
96-
grid := tview.NewGrid().SetRows(2, 0, 2).
113+
grid := tview.NewGrid().SetRows(2, 0, 3).
97114
AddItem(infoView, 0, 0, 1, 1, 0, 0, false).
98115
AddItem(statsTable, 1, 0, 1, 1, 0, 0, true).
99116
AddItem(naviView, 2, 0, 1, 1, 0, 0, false)
100117

101118
// start the update loop
102-
go updateStatsTable(app, statsTable, objs, startTime)
119+
go updateStatsTable(app, statsTable, &tableSort, objs, startTime)
103120

104121
_ = app.SetRoot(grid, true).
105122
SetFocus(statsTable).
@@ -125,7 +142,9 @@ func drawTUI(objs counterObjects, startTime time.Time) {
125142
//
126143
// Note that the table is cleared and recreated on each iteration, so any cell
127144
// attributes are lost on each iteration.
128-
func updateStatsTable(app *tview.Application, table *tview.Table, objs counterObjects, startTime time.Time) {
145+
func updateStatsTable(app *tview.Application, table *tview.Table, tableSort *func(stats []statEntry),
146+
objs counterObjects, startTime time.Time,
147+
) {
129148
headers := []string{
130149
"bitrate", // column 0
131150
"packets", // column 1
@@ -153,7 +172,7 @@ func updateStatsTable(app *tview.Application, table *tview.Table, objs counterOb
153172
})
154173
}
155174

156-
m, _ := processMap(objs.PktCount, startTime)
175+
m, _ := processMap(objs.PktCount, startTime, *tableSort)
157176

158177
for i, v := range m {
159178
// populate bitrate, packets, bytes and proto

0 commit comments

Comments
 (0)