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  }