github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/core/network/source_netlink.go (about) 1 // Copyright 2021 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 //go:build linux 5 6 package network 7 8 import ( 9 "net" 10 11 "github.com/juju/collections/set" 12 "github.com/juju/errors" 13 "github.com/vishvananda/netlink" 14 "golang.org/x/sys/unix" 15 ) 16 17 // netlinkAddr implements ConfigSourceAddr based on the 18 // netlink implementation of a network address. 19 type netlinkAddr struct { 20 addr *netlink.Addr 21 } 22 23 // IP (ConfigSourceAddr) is a simple property accessor. 24 func (a *netlinkAddr) IP() net.IP { 25 return a.addr.IP 26 } 27 28 // IPNet (ConfigSourceAddr) is a simple property accessor. 29 func (a *netlinkAddr) IPNet() *net.IPNet { 30 return a.addr.IPNet 31 } 32 33 // IsSecondary (ConfigSourceAddr) uses the IFA_F_SECONDARY flag to return 34 // whether this address is not the primary one for the NIC. 35 func (a *netlinkAddr) IsSecondary() bool { 36 return a.addr.Flags&unix.IFA_F_SECONDARY > 0 37 } 38 39 // String (ConfigSourceAddr) is a simple property accessor. 40 func (a *netlinkAddr) String() string { 41 return a.addr.String() 42 } 43 44 // netlinkNIC implements ConfigSourceNIC by wrapping a netlink Link. 45 type netlinkNIC struct { 46 nic netlink.Link 47 getAddrs func(netlink.Link) ([]netlink.Addr, error) 48 } 49 50 // Name returns the name of the device. 51 func (n netlinkNIC) Name() string { 52 return n.nic.Attrs().Name 53 } 54 55 // Type returns the interface type of the device. 56 func (n netlinkNIC) Type() LinkLayerDeviceType { 57 switch n.nic.Type() { 58 case "bridge": 59 return BridgeDevice 60 case "vlan": 61 return VLAN8021QDevice 62 case "bond": 63 return BondDevice 64 case "vxlan": 65 return VXLANDevice 66 } 67 68 if n.nic.Attrs().Flags&net.FlagLoopback > 0 { 69 return LoopbackDevice 70 } 71 72 // See comment on super-method. 73 // This is incorrect for veth, tuntap, macvtap et al. 74 return EthernetDevice 75 } 76 77 // Index returns the index of the device. 78 func (n netlinkNIC) Index() int { 79 return n.nic.Attrs().Index 80 } 81 82 // HardwareAddr returns the hardware address of the device. 83 func (n netlinkNIC) HardwareAddr() net.HardwareAddr { 84 return n.nic.Attrs().HardwareAddr 85 } 86 87 // Addresses returns all IP addresses associated with the device. 88 func (n netlinkNIC) Addresses() ([]ConfigSourceAddr, error) { 89 rawAddrs, err := n.getAddrs(n.nic) 90 if err != nil { 91 return nil, errors.Trace(err) 92 } 93 94 addrs := make([]ConfigSourceAddr, len(rawAddrs)) 95 for i := range rawAddrs { 96 addrs[i] = &netlinkAddr{addr: &rawAddrs[i]} 97 } 98 return addrs, nil 99 } 100 101 // MTU returns the maximum transmission unit for the device. 102 func (n netlinkNIC) MTU() int { 103 return n.nic.Attrs().MTU 104 } 105 106 // IsUp returns true if the interface is in the "up" state. 107 func (n netlinkNIC) IsUp() bool { 108 return n.nic.Attrs().Flags&net.FlagUp > 0 109 } 110 111 type netlinkConfigSource struct { 112 sysClassNetPath string 113 linkList func() ([]netlink.Link, error) 114 } 115 116 // Interfaces returns the network interfaces on the machine. 117 func (s *netlinkConfigSource) Interfaces() ([]ConfigSourceNIC, error) { 118 links, err := s.linkList() 119 if err != nil { 120 return nil, errors.Trace(err) 121 } 122 123 getAddrs := func(l netlink.Link) ([]netlink.Addr, error) { 124 return netlink.AddrList(l, netlink.FAMILY_ALL) 125 } 126 127 nics := make([]ConfigSourceNIC, len(links)) 128 for i := range links { 129 nics[i] = &netlinkNIC{ 130 nic: links[i], 131 getAddrs: getAddrs, 132 } 133 } 134 return nics, nil 135 } 136 137 // OvsManagedBridges implements NetworkConfigSource. 138 func (*netlinkConfigSource) OvsManagedBridges() (set.Strings, error) { 139 return OvsManagedBridges() 140 } 141 142 // DefaultRoute implements NetworkConfigSource. 143 func (*netlinkConfigSource) DefaultRoute() (net.IP, string, error) { 144 return GetDefaultRoute() 145 } 146 147 // GetBridgePorts implements NetworkConfigSource. 148 func (s *netlinkConfigSource) GetBridgePorts(bridgeName string) []string { 149 return GetBridgePorts(s.sysClassNetPath, bridgeName) 150 } 151 152 // DefaultConfigSource returns a NetworkConfigSource backed by the 153 // netlink library, to be used with GetObservedNetworkConfig(). 154 func DefaultConfigSource() ConfigSource { 155 return &netlinkConfigSource{ 156 sysClassNetPath: SysClassNetPath, 157 linkList: netlink.LinkList, 158 } 159 }