Skip to content

Commit

Permalink
fix: same TCP connection appears twice (#631)
Browse files Browse the repository at this point in the history
```
TCP, TCP6, UDP, and UDP6 are dynamically changing,
and when we read these files, we should read them all at once.
there will be data consistency issues if using line by lin reading

fix: #576
```

Signed-off-by: weidongkl <[email protected]>
  • Loading branch information
wd3993 authored Apr 15, 2024
1 parent ee70db2 commit 987bedc
Showing 1 changed file with 25 additions and 39 deletions.
64 changes: 25 additions & 39 deletions net_ip_socket.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,14 @@
package procfs

import (
"bufio"
"encoding/hex"
"fmt"
"io"
"net"
"os"
"strconv"
"strings"
)

const (
// readLimit is used by io.LimitReader while reading the content of the
// /proc/net/udp{,6} files. The number of lines inside such a file is dynamic
// as each line represents a single used socket.
// In theory, the number of available sockets is 65535 (2^16 - 1) per IP.
// With e.g. 150 Byte per line and the maximum number of 65535,
// the reader needs to handle 150 Byte * 65535 =~ 10 MB for a single IP.
readLimit = 4294967296 // Byte -> 4 GiB
)

// This contains generic data structures for both udp and tcp sockets.
type (
// NetIPSocket represents the contents of /proc/net/{t,u}dp{,6} file without the header.
Expand Down Expand Up @@ -74,49 +62,50 @@ type (
)

func newNetIPSocket(file string) (NetIPSocket, error) {
f, err := os.Open(file)
var netIPSocket NetIPSocket
isUDP := strings.Contains(file, "udp")
content, err := os.ReadFile(file)
if err != nil {
return nil, err
}
defer f.Close()

var netIPSocket NetIPSocket
isUDP := strings.Contains(file, "udp")
lines := strings.Split(string(content), "\n")
if len(lines) < 1 {
return nil, ErrFileParse
}

lr := io.LimitReader(f, readLimit)
s := bufio.NewScanner(lr)
s.Scan() // skip first line with headers
for s.Scan() {
fields := strings.Fields(s.Text())
for _, line := range lines[1:] {
fields := strings.Fields(line)
if len(fields) == 0 {
continue
}
line, err := parseNetIPSocketLine(fields, isUDP)
if err != nil {
return nil, err
}
netIPSocket = append(netIPSocket, line)
}
if err := s.Err(); err != nil {
return nil, err
}
return netIPSocket, nil
}

// newNetIPSocketSummary creates a new NetIPSocket{,6} from the contents of the given file.
func newNetIPSocketSummary(file string) (*NetIPSocketSummary, error) {
f, err := os.Open(file)
if err != nil {
return nil, err
}
defer f.Close()

var netIPSocketSummary NetIPSocketSummary
var udpPacketDrops uint64
isUDP := strings.Contains(file, "udp")
content, err := os.ReadFile(file)
if err != nil {
return nil, err
}
lines := strings.Split(string(content), "\n")
if len(lines) < 1 {
return nil, ErrFileParse
}

lr := io.LimitReader(f, readLimit)
s := bufio.NewScanner(lr)
s.Scan() // skip first line with headers
for s.Scan() {
fields := strings.Fields(s.Text())
for _, line := range lines[1:] {
fields := strings.Fields(line)
if len(fields) == 0 {
continue
}
line, err := parseNetIPSocketLine(fields, isUDP)
if err != nil {
return nil, err
Expand All @@ -129,9 +118,6 @@ func newNetIPSocketSummary(file string) (*NetIPSocketSummary, error) {
netIPSocketSummary.Drops = &udpPacketDrops
}
}
if err := s.Err(); err != nil {
return nil, err
}
return &netIPSocketSummary, nil
}

Expand Down

0 comments on commit 987bedc

Please sign in to comment.