github.com/opencontainers/runc@v1.2.0-rc.1.0.20240520010911-492dc558cdd6/libcontainer/network_linux.go (about) 1 package libcontainer 2 3 import ( 4 "bytes" 5 "fmt" 6 "os" 7 "path/filepath" 8 "strconv" 9 10 "github.com/opencontainers/runc/libcontainer/configs" 11 "github.com/opencontainers/runc/types" 12 "github.com/vishvananda/netlink" 13 ) 14 15 var strategies = map[string]networkStrategy{ 16 "loopback": &loopback{}, 17 } 18 19 // networkStrategy represents a specific network configuration for 20 // a container's networking stack 21 type networkStrategy interface { 22 create(*network, int) error 23 initialize(*network) error 24 detach(*configs.Network) error 25 attach(*configs.Network) error 26 } 27 28 // getStrategy returns the specific network strategy for the 29 // provided type. 30 func getStrategy(tpe string) (networkStrategy, error) { 31 s, exists := strategies[tpe] 32 if !exists { 33 return nil, fmt.Errorf("unknown strategy type %q", tpe) 34 } 35 return s, nil 36 } 37 38 // Returns the network statistics for the network interfaces represented by the NetworkRuntimeInfo. 39 func getNetworkInterfaceStats(interfaceName string) (*types.NetworkInterface, error) { 40 out := &types.NetworkInterface{Name: interfaceName} 41 // This can happen if the network runtime information is missing - possible if the 42 // container was created by an old version of libcontainer. 43 if interfaceName == "" { 44 return out, nil 45 } 46 type netStatsPair struct { 47 // Where to write the output. 48 Out *uint64 49 // The network stats file to read. 50 File string 51 } 52 // 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. 53 netStats := []netStatsPair{ 54 {Out: &out.RxBytes, File: "tx_bytes"}, 55 {Out: &out.RxPackets, File: "tx_packets"}, 56 {Out: &out.RxErrors, File: "tx_errors"}, 57 {Out: &out.RxDropped, File: "tx_dropped"}, 58 59 {Out: &out.TxBytes, File: "rx_bytes"}, 60 {Out: &out.TxPackets, File: "rx_packets"}, 61 {Out: &out.TxErrors, File: "rx_errors"}, 62 {Out: &out.TxDropped, File: "rx_dropped"}, 63 } 64 for _, netStat := range netStats { 65 data, err := readSysfsNetworkStats(interfaceName, netStat.File) 66 if err != nil { 67 return nil, err 68 } 69 *(netStat.Out) = data 70 } 71 return out, nil 72 } 73 74 // Reads the specified statistics available under /sys/class/net/<EthInterface>/statistics 75 func readSysfsNetworkStats(ethInterface, statsFile string) (uint64, error) { 76 data, err := os.ReadFile(filepath.Join("/sys/class/net", ethInterface, "statistics", statsFile)) 77 if err != nil { 78 return 0, err 79 } 80 return strconv.ParseUint(string(bytes.TrimSpace(data)), 10, 64) 81 } 82 83 // loopback is a network strategy that provides a basic loopback device 84 type loopback struct{} 85 86 func (l *loopback) create(n *network, nspid int) error { 87 return nil 88 } 89 90 func (l *loopback) initialize(config *network) error { 91 return netlink.LinkSetUp(&netlink.Device{LinkAttrs: netlink.LinkAttrs{Name: "lo"}}) 92 } 93 94 func (l *loopback) attach(n *configs.Network) (err error) { 95 return nil 96 } 97 98 func (l *loopback) detach(n *configs.Network) (err error) { 99 return nil 100 }