Skip to content

Commit

Permalink
Add udp drops (#538)
Browse files Browse the repository at this point in the history
* Add drops field in /proc/net/udp{,6} files for parsing

Signed-off-by: Aleksandr Lebedev <lebedevam88@gmail.com>
Signed-off-by: Александр Лебедев <allebedev@samokat.ru>

* Add count of UDP dropped packets

Signed-off-by: Aleksandr Lebedev <lebedevam88@gmail.com>
Signed-off-by: Александр Лебедев <allebedev@samokat.ru>

* Change the type of variable isUDP to local

Signed-off-by: Александр Лебедев <allebedev@samokat.ru>

* Update net_ip_socket.go

Co-authored-by: Ben Kochie <superq@gmail.com>
Signed-off-by: Aleksandr Lebedev <49903054+alebsys@users.noreply.github.com>

* Update net_ip_socket.go

Co-authored-by: Ben Kochie <superq@gmail.com>
Signed-off-by: Aleksandr Lebedev <49903054+alebsys@users.noreply.github.com>

---------

Signed-off-by: Aleksandr Lebedev <lebedevam88@gmail.com>
Signed-off-by: Александр Лебедев <allebedev@samokat.ru>
Signed-off-by: Aleksandr Lebedev <49903054+alebsys@users.noreply.github.com>
Co-authored-by: Ben Kochie <superq@gmail.com>
  • Loading branch information
alebsys and SuperQ committed Nov 28, 2023
1 parent f11f6e4 commit 9fdfbe8
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 6 deletions.
26 changes: 23 additions & 3 deletions net_ip_socket.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,13 @@ type (
// UsedSockets shows the total number of parsed lines representing the
// number of used sockets.
UsedSockets uint64
// Drops shows the total number of dropped packets of all UPD sockets.
Drops *uint64
}

// netIPSocketLine represents the fields parsed from a single line
// in /proc/net/{t,u}dp{,6}. Fields which are not used by IPSocket are skipped.
// Drops is non-nil for udp{,6}, but nil for tcp{,6}.
// For the proc file format details, see https://linux.die.net/man/5/proc.
netIPSocketLine struct {
Sl uint64
Expand All @@ -66,6 +69,7 @@ type (
RxQueue uint64
UID uint64
Inode uint64
Drops *uint64
}
)

Expand All @@ -77,13 +81,14 @@ func newNetIPSocket(file string) (NetIPSocket, error) {
defer f.Close()

var netIPSocket NetIPSocket
isUDP := strings.Contains(file, "udp")

lr := io.LimitReader(f, readLimit)
s := bufio.NewScanner(lr)
s.Scan() // skip first line with headers
for s.Scan() {
fields := strings.Fields(s.Text())
line, err := parseNetIPSocketLine(fields)
line, err := parseNetIPSocketLine(fields, isUDP)
if err != nil {
return nil, err
}
Expand All @@ -104,19 +109,25 @@ func newNetIPSocketSummary(file string) (*NetIPSocketSummary, error) {
defer f.Close()

var netIPSocketSummary NetIPSocketSummary
var udpPacketDrops uint64
isUDP := strings.Contains(file, "udp")

lr := io.LimitReader(f, readLimit)
s := bufio.NewScanner(lr)
s.Scan() // skip first line with headers
for s.Scan() {
fields := strings.Fields(s.Text())
line, err := parseNetIPSocketLine(fields)
line, err := parseNetIPSocketLine(fields, isUDP)
if err != nil {
return nil, err
}
netIPSocketSummary.TxQueueLength += line.TxQueue
netIPSocketSummary.RxQueueLength += line.RxQueue
netIPSocketSummary.UsedSockets++
if isUDP {
udpPacketDrops += *line.Drops
netIPSocketSummary.Drops = &udpPacketDrops
}
}
if err := s.Err(); err != nil {
return nil, err
Expand Down Expand Up @@ -149,7 +160,7 @@ func parseIP(hexIP string) (net.IP, error) {
}

// parseNetIPSocketLine parses a single line, represented by a list of fields.
func parseNetIPSocketLine(fields []string) (*netIPSocketLine, error) {
func parseNetIPSocketLine(fields []string, isUDP bool) (*netIPSocketLine, error) {
line := &netIPSocketLine{}
if len(fields) < 10 {
return nil, fmt.Errorf(
Expand Down Expand Up @@ -224,5 +235,14 @@ func parseNetIPSocketLine(fields []string) (*netIPSocketLine, error) {
return nil, fmt.Errorf("%s: Cannot parse inode value in %q: %w", ErrFileParse, line.Inode, err)
}

// drops
if isUDP {
drops, err := strconv.ParseUint(fields[12], 0, 64)
if err != nil {
return nil, fmt.Errorf("%s: Cannot parse drops value in %q: %w", ErrFileParse, drops, err)
}
line.Drops = &drops
}

return line, nil
}
10 changes: 9 additions & 1 deletion net_ip_socket_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func Test_parseNetIPSocketLine(t *testing.T) {
name string
want *netIPSocketLine
wantErr bool
isUDP bool
}{
{
name: "reading valid lines, no issue should happened",
Expand Down Expand Up @@ -96,10 +97,17 @@ func Test_parseNetIPSocketLine(t *testing.T) {
want: nil,
wantErr: true,
},
{
name: "error case - parse Drops - not a valid uint",
fields: []string{"1:", "00000000:0000", "00000000:0000", "07", "00000000:00000001", "0:0", "0", "10", "0", "39309", "2", "000000009bd60d72", "-5"},
want: nil,
wantErr: true,
isUDP: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := parseNetIPSocketLine(tt.fields)
got, err := parseNetIPSocketLine(tt.fields, tt.isUDP)
if (err != nil) != tt.wantErr {
t.Errorf("parseNetIPSocketLine() error = %v, wantErr %v", err, tt.wantErr)
return
Expand Down
15 changes: 13 additions & 2 deletions net_udp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func Test_newNetUDP(t *testing.T) {
RxQueue: 1,
UID: 0,
Inode: 2740,
Drops: intToU64(100),
},
&netIPSocketLine{
Sl: 1,
Expand All @@ -53,6 +54,7 @@ func Test_newNetUDP(t *testing.T) {
RxQueue: 0,
UID: 0,
Inode: 2740,
Drops: intToU64(100),
},
&netIPSocketLine{
Sl: 2,
Expand All @@ -65,6 +67,7 @@ func Test_newNetUDP(t *testing.T) {
RxQueue: 1,
UID: 0,
Inode: 2740,
Drops: intToU64(100),
},
},
wantErr: false,
Expand All @@ -84,6 +87,7 @@ func Test_newNetUDP(t *testing.T) {
RxQueue: 0,
UID: 981,
Inode: 21040,
Drops: intToU64(0),
},
&netIPSocketLine{
Sl: 6073,
Expand All @@ -96,6 +100,7 @@ func Test_newNetUDP(t *testing.T) {
RxQueue: 0,
UID: 1000,
Inode: 11337031,
Drops: intToU64(0),
},
},
wantErr: false,
Expand Down Expand Up @@ -137,13 +142,13 @@ func Test_newNetUDPSummary(t *testing.T) {
{
name: "udp file found, no error should come up",
file: "testdata/fixtures/proc/net/udp",
want: &NetUDPSummary{TxQueueLength: 2, RxQueueLength: 2, UsedSockets: 3},
want: &NetUDPSummary{TxQueueLength: 2, RxQueueLength: 2, UsedSockets: 3, Drops: intToU64(300)},
wantErr: false,
},
{
name: "udp6 file found, no error should come up",
file: "testdata/fixtures/proc/net/udp6",
want: &NetUDPSummary{TxQueueLength: 0, RxQueueLength: 0, UsedSockets: 2},
want: &NetUDPSummary{TxQueueLength: 0, RxQueueLength: 0, UsedSockets: 2, Drops: intToU64(0)},
wantErr: false,
},
{
Expand Down Expand Up @@ -172,3 +177,9 @@ func Test_newNetUDPSummary(t *testing.T) {
})
}
}

// intToU64 convert int to uint64 and return it pointer.
func intToU64(i int) *uint64 {
cast := uint64(i)
return &cast
}

0 comments on commit 9fdfbe8

Please sign in to comment.