1 package link
2
3 import (
4 "errors"
5 "fmt"
6 "strings"
7
8 "github.com/vishvananda/netlink"
9
10 "slices"
11 )
12
13 var (
14 defaultTqLength = 1000
15 backboneInterfacePrefixes = []string{"eno", "ens", "enp", "enx", "eth", "enX"}
16 )
17
18 type NetLinker interface {
19 GetFromHardwareAddr(hardwareAddr string) (netlink.Link, error)
20 GetAllNetworkDeviceLinks() ([]netlink.Link, error)
21 GetByName(name string) (netlink.Link, error)
22 Ensure(link netlink.Link) (netlink.Link, error)
23 Delete(name string) error
24 NewIfb(name string, mtu int) netlink.Link
25 }
26
27 type NetLink struct{}
28
29
30 func (n *NetLink) GetFromHardwareAddr(hardwareAddr string) (netlink.Link, error) {
31 allLinks, err := n.GetAllNetworkDeviceLinks()
32 if err != nil {
33 return nil, err
34 }
35 for _, link := range allLinks {
36 if link.Attrs().HardwareAddr.String() == hardwareAddr {
37 return link, nil
38 }
39 }
40 return nil, fmt.Errorf("interface not found with hardware address: %s", hardwareAddr)
41 }
42
43
44 func (n *NetLink) GetAllNetworkDeviceLinks() ([]netlink.Link, error) {
45 var links []netlink.Link
46 allLinks, err := netlink.LinkList()
47 if err != nil {
48 return nil, fmt.Errorf("error listing links: %w", err)
49 }
50 for _, link := range allLinks {
51 if slices.ContainsFunc(backboneInterfacePrefixes, func(prefix string) bool {
52 return strings.HasPrefix(link.Attrs().Name, prefix)
53 }) {
54 links = append(links, link)
55 }
56 }
57 return links, nil
58 }
59
60 func (n *NetLink) GetByName(name string) (netlink.Link, error) {
61 link, err := netlink.LinkByName(name)
62 if err != nil {
63 return nil, fmt.Errorf("error getting link %s: %w", name, err)
64 }
65 return link, nil
66 }
67
68
69
70 func (n *NetLink) Ensure(link netlink.Link) (netlink.Link, error) {
71 name := link.Attrs().Name
72 if err := netlink.LinkAdd(link); err != nil && !strings.Contains(err.Error(), "file exists") {
73 return nil, fmt.Errorf("error creating link %s: %w", name, err)
74 }
75 link, err := netlink.LinkByName(name)
76 if err != nil {
77 return nil, fmt.Errorf("error retrieving new link %s: %w", name, err)
78 }
79 if err := netlink.LinkSetUp(link); err != nil {
80 return nil, fmt.Errorf("error setting link %s up: %w", name, err)
81 }
82 return link, nil
83 }
84
85
86 func (n *NetLink) Delete(name string) error {
87 link, err := n.GetByName(name)
88 if err != nil {
89 if errors.As(err, &netlink.LinkNotFoundError{}) {
90 return nil
91 }
92 return fmt.Errorf("error retrieving link %s: %w", name, err)
93 }
94 if err := netlink.LinkDel(link); err != nil {
95 return fmt.Errorf("error deleting link %s: %w", name, err)
96 }
97 return nil
98 }
99
100
101 func (n *NetLink) NewIfb(name string, mtu int) netlink.Link {
102 ifbLinkAttrs := netlink.NewLinkAttrs()
103 ifbLinkAttrs.Name = name
104 defaultIfbLink := &netlink.Ifb{
105 LinkAttrs: ifbLinkAttrs,
106 }
107 defaultIfbLink.TxQLen = defaultTqLength
108 defaultIfbLink.MTU = mtu
109 return defaultIfbLink
110 }
111
View as plain text