From 74098259c7d42cb20b16a678f5e7ad6cdf26b166 Mon Sep 17 00:00:00 2001 From: Pranshu Srivastava Date: Sat, 23 Mar 2024 01:08:55 +0530 Subject: [PATCH] feat: Make `net_(tcp|udp)` read limit configurable Defaults to 4GiB otherwise, as earlier. Fixes: #364 Signed-off-by: Pranshu Srivastava --- go.mod | 1 + go.sum | 2 ++ net_ip_socket.go | 22 +++++++++++++++------- net_tcp.go | 24 ++++++++++++------------ net_tcp_test.go | 4 ++-- net_udp.go | 4 ++-- 6 files changed, 34 insertions(+), 23 deletions(-) diff --git a/go.mod b/go.mod index e45aa5739..7b11e1b73 100644 --- a/go.mod +++ b/go.mod @@ -6,4 +6,5 @@ require ( github.com/google/go-cmp v0.6.0 golang.org/x/sync v0.7.0 golang.org/x/sys v0.19.0 + k8s.io/utils v0.0.0-20240310230437-4693a0247e57 ) diff --git a/go.sum b/go.sum index 2e5622054..acdad1cc1 100644 --- a/go.sum +++ b/go.sum @@ -4,3 +4,5 @@ golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +k8s.io/utils v0.0.0-20240310230437-4693a0247e57 h1:gbqbevonBh57eILzModw6mrkbwM0gQBEuevE/AaBsHY= +k8s.io/utils v0.0.0-20240310230437-4693a0247e57/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= diff --git a/net_ip_socket.go b/net_ip_socket.go index b70f1fc7a..8ebe3831a 100644 --- a/net_ip_socket.go +++ b/net_ip_socket.go @@ -22,16 +22,18 @@ import ( "os" "strconv" "strings" + + "k8s.io/utils/ptr" ) -const ( - // readLimit is used by io.LimitReader while reading the content of the +var ( + // defaultReadLimitPtr 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 + defaultReadLimit = ptr.To(4294967296) // Byte -> 4 GiB ) // This contains generic data structures for both udp and tcp sockets. @@ -73,7 +75,7 @@ type ( } ) -func newNetIPSocket(file string) (NetIPSocket, error) { +func newNetIPSocket(file string, readLimit *int) (NetIPSocket, error) { f, err := os.Open(file) if err != nil { return nil, err @@ -83,7 +85,10 @@ func newNetIPSocket(file string) (NetIPSocket, error) { var netIPSocket NetIPSocket isUDP := strings.Contains(file, "udp") - lr := io.LimitReader(f, readLimit) + if readLimit == nil { + readLimit = defaultReadLimit + } + lr := io.LimitReader(f, int64(*readLimit)) s := bufio.NewScanner(lr) s.Scan() // skip first line with headers for s.Scan() { @@ -101,7 +106,7 @@ func newNetIPSocket(file string) (NetIPSocket, error) { } // newNetIPSocketSummary creates a new NetIPSocket{,6} from the contents of the given file. -func newNetIPSocketSummary(file string) (*NetIPSocketSummary, error) { +func newNetIPSocketSummary(file string, readLimit *int) (*NetIPSocketSummary, error) { f, err := os.Open(file) if err != nil { return nil, err @@ -112,7 +117,10 @@ func newNetIPSocketSummary(file string) (*NetIPSocketSummary, error) { var udpPacketDrops uint64 isUDP := strings.Contains(file, "udp") - lr := io.LimitReader(f, readLimit) + if readLimit == nil { + readLimit = defaultReadLimit + } + lr := io.LimitReader(f, int64(*readLimit)) s := bufio.NewScanner(lr) s.Scan() // skip first line with headers for s.Scan() { diff --git a/net_tcp.go b/net_tcp.go index 527762955..73c86aca7 100644 --- a/net_tcp.go +++ b/net_tcp.go @@ -25,37 +25,37 @@ type ( // NetTCP returns the IPv4 kernel/networking statistics for TCP datagrams // read from /proc/net/tcp. -func (fs FS) NetTCP() (NetTCP, error) { - return newNetTCP(fs.proc.Path("net/tcp")) +func (fs FS) NetTCP(readLimit *int) (NetTCP, error) { + return newNetTCP(fs.proc.Path("net/tcp"), readLimit) } // NetTCP6 returns the IPv6 kernel/networking statistics for TCP datagrams // read from /proc/net/tcp6. -func (fs FS) NetTCP6() (NetTCP, error) { - return newNetTCP(fs.proc.Path("net/tcp6")) +func (fs FS) NetTCP6(readLimit *int) (NetTCP, error) { + return newNetTCP(fs.proc.Path("net/tcp6"), readLimit) } // NetTCPSummary returns already computed statistics like the total queue lengths // for TCP datagrams read from /proc/net/tcp. -func (fs FS) NetTCPSummary() (*NetTCPSummary, error) { - return newNetTCPSummary(fs.proc.Path("net/tcp")) +func (fs FS) NetTCPSummary(readLimit *int) (*NetTCPSummary, error) { + return newNetTCPSummary(fs.proc.Path("net/tcp"), readLimit) } // NetTCP6Summary returns already computed statistics like the total queue lengths // for TCP datagrams read from /proc/net/tcp6. -func (fs FS) NetTCP6Summary() (*NetTCPSummary, error) { - return newNetTCPSummary(fs.proc.Path("net/tcp6")) +func (fs FS) NetTCP6Summary(readLimit *int) (*NetTCPSummary, error) { + return newNetTCPSummary(fs.proc.Path("net/tcp6"), readLimit) } // newNetTCP creates a new NetTCP{,6} from the contents of the given file. -func newNetTCP(file string) (NetTCP, error) { - n, err := newNetIPSocket(file) +func newNetTCP(file string, readLimit *int) (NetTCP, error) { + n, err := newNetIPSocket(file, readLimit) n1 := NetTCP(n) return n1, err } -func newNetTCPSummary(file string) (*NetTCPSummary, error) { - n, err := newNetIPSocketSummary(file) +func newNetTCPSummary(file string, readLimit *int) (*NetTCPSummary, error) { + n, err := newNetIPSocketSummary(file, readLimit) if n == nil { return nil, err } diff --git a/net_tcp_test.go b/net_tcp_test.go index 5ff33ef35..2b745de1a 100644 --- a/net_tcp_test.go +++ b/net_tcp_test.go @@ -115,7 +115,7 @@ func Test_newNetTCP(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := newNetTCP(tt.file) + got, err := newNetTCP(tt.file, nil) if (err != nil) != tt.wantErr { t.Errorf("newNetTCP() error = %v, wantErr %v", err, tt.wantErr) return @@ -161,7 +161,7 @@ func Test_newNetTCPSummary(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := newNetTCPSummary(tt.file) + got, err := newNetTCPSummary(tt.file, nil) if (err != nil) != tt.wantErr { t.Errorf("newNetTCPSummary() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/net_udp.go b/net_udp.go index 9ac3daf2d..ff85264fe 100644 --- a/net_udp.go +++ b/net_udp.go @@ -49,13 +49,13 @@ func (fs FS) NetUDP6Summary() (*NetUDPSummary, error) { // newNetUDP creates a new NetUDP{,6} from the contents of the given file. func newNetUDP(file string) (NetUDP, error) { - n, err := newNetIPSocket(file) + n, err := newNetIPSocket(file, nil) n1 := NetUDP(n) return n1, err } func newNetUDPSummary(file string) (*NetUDPSummary, error) { - n, err := newNetIPSocketSummary(file) + n, err := newNetIPSocketSummary(file, nil) if n == nil { return nil, err }