From aedac2e4d282c938de9bbd0e31c14fb629771340 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Wed, 7 Oct 2026 15:07:03 -0700 Subject: [PATCH] libct: remove dead network stats code Network interface statistics were only collected for "veth" networks, but the veth strategy was removed back in 2018 by commit fe3d5c4c ("Remove unused veth setup code"). Since then, a container with a veth network can not even be started ("unknown strategy type"), so this code is never reached, and the network interface stats are always empty. Remove the dead code, and deprecate libcontainer.Stats.Interfaces and types.Stats.NetworkInterfaces, which are always empty. Network statistics are better obtained by whoever sets up the container network (which runc does not do). Signed-off-by: Kir Kolyshkin --- events.go | 1 - libcontainer/container_linux.go | 10 ------- libcontainer/network_linux.go | 50 --------------------------------- libcontainer/stats_linux.go | 2 ++ types/events.go | 15 +++++----- 5 files changed, 10 insertions(+), 68 deletions(-) diff --git a/events.go b/events.go index 5aa992891..59b6b033e 100644 --- a/events.go +++ b/events.go @@ -178,7 +178,6 @@ func convertLibcontainerStats(ls *libcontainer.Stats) *types.Stats { s.IntelRdt.Schemata = is.Schemata } - s.NetworkInterfaces = ls.Interfaces return &s } diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go index 5d97e9141..830a024ac 100644 --- a/libcontainer/container_linux.go +++ b/libcontainer/container_linux.go @@ -150,16 +150,6 @@ func (c *Container) Stats() (*Stats, error) { return stats, fmt.Errorf("unable to get container Intel RDT stats: %w", err) } } - for _, iface := range c.config.Networks { - switch iface.Type { - case "veth": - istats, err := getNetworkInterfaceStats(iface.HostInterfaceName) - if err != nil { - return stats, fmt.Errorf("unable to get network stats for interface %q: %w", iface.HostInterfaceName, err) - } - stats.Interfaces = append(stats.Interfaces, istats) - } - } return stats, nil } diff --git a/libcontainer/network_linux.go b/libcontainer/network_linux.go index ced962b53..83f9b314f 100644 --- a/libcontainer/network_linux.go +++ b/libcontainer/network_linux.go @@ -1,15 +1,10 @@ package libcontainer import ( - "bytes" "errors" "fmt" - "os" - "path/filepath" - "strconv" "github.com/opencontainers/runc/libcontainer/configs" - "github.com/opencontainers/runc/types" "github.com/sirupsen/logrus" "github.com/vishvananda/netlink" "github.com/vishvananda/netlink/nl" @@ -41,51 +36,6 @@ func getStrategy(tpe string) (networkStrategy, error) { return s, nil } -// Returns the network statistics for the network interfaces represented by the NetworkRuntimeInfo. -func getNetworkInterfaceStats(interfaceName string) (*types.NetworkInterface, error) { - out := &types.NetworkInterface{Name: interfaceName} - // This can happen if the network runtime information is missing - possible if the - // container was created by an old version of libcontainer. - if interfaceName == "" { - return out, nil - } - type netStatsPair struct { - // Where to write the output. - Out *uint64 - // The network stats file to read. - File string - } - // Ingress for host veth is from the container. Hence tx_bytes stat on the host veth is actually number of bytes received by the container. - netStats := []netStatsPair{ - {Out: &out.RxBytes, File: "tx_bytes"}, - {Out: &out.RxPackets, File: "tx_packets"}, - {Out: &out.RxErrors, File: "tx_errors"}, - {Out: &out.RxDropped, File: "tx_dropped"}, - - {Out: &out.TxBytes, File: "rx_bytes"}, - {Out: &out.TxPackets, File: "rx_packets"}, - {Out: &out.TxErrors, File: "rx_errors"}, - {Out: &out.TxDropped, File: "rx_dropped"}, - } - for _, netStat := range netStats { - data, err := readSysfsNetworkStats(interfaceName, netStat.File) - if err != nil { - return nil, err - } - *netStat.Out = data - } - return out, nil -} - -// Reads the specified statistics available under /sys/class/net//statistics -func readSysfsNetworkStats(ethInterface, statsFile string) (uint64, error) { - data, err := os.ReadFile(filepath.Join("/sys/class/net", ethInterface, "statistics", statsFile)) - if err != nil { - return 0, err - } - return strconv.ParseUint(string(bytes.TrimSpace(data)), 10, 64) -} - // loopback is a network strategy that provides a basic loopback device type loopback struct{} diff --git a/libcontainer/stats_linux.go b/libcontainer/stats_linux.go index e776aad43..7d4ee7d0d 100644 --- a/libcontainer/stats_linux.go +++ b/libcontainer/stats_linux.go @@ -7,6 +7,8 @@ import ( ) type Stats struct { + // Deprecated: always empty. Network statistics should be obtained + // by whoever sets up the container network. Interfaces []*types.NetworkInterface CgroupStats *cgroups.Stats IntelRdtStats *intelrdt.Stats diff --git a/types/events.go b/types/events.go index 9dac1cd5d..152f40dfe 100644 --- a/types/events.go +++ b/types/events.go @@ -16,13 +16,14 @@ type Event struct { // Stats is the runc specific stats structure for stability when encoding and decoding stats. type Stats struct { - CPU Cpu `json:"cpu"` - CPUSet CPUSet `json:"cpuset"` - Memory Memory `json:"memory"` - Pids Pids `json:"pids"` - Blkio Blkio `json:"blkio"` - Hugetlb map[string]Hugetlb `json:"hugetlb"` - IntelRdt IntelRdt `json:"intel_rdt"` + CPU Cpu `json:"cpu"` + CPUSet CPUSet `json:"cpuset"` + Memory Memory `json:"memory"` + Pids Pids `json:"pids"` + Blkio Blkio `json:"blkio"` + Hugetlb map[string]Hugetlb `json:"hugetlb"` + IntelRdt IntelRdt `json:"intel_rdt"` + // Deprecated: always empty. NetworkInterfaces []*NetworkInterface `json:"network_interfaces"` }