1
2
3
4
19
20 package ipvs
21
22 import (
23 "fmt"
24 "net"
25
26 "k8s.io/apimachinery/pkg/util/sets"
27 "k8s.io/klog/v2"
28 proxyutil "k8s.io/kubernetes/pkg/proxy/util"
29 netutils "k8s.io/utils/net"
30
31 "github.com/vishvananda/netlink"
32 "golang.org/x/sys/unix"
33 )
34
35 type netlinkHandle struct {
36 netlink.Handle
37 isIPv6 bool
38 }
39
40
41 func NewNetLinkHandle(isIPv6 bool) NetLinkHandle {
42 return &netlinkHandle{netlink.Handle{}, isIPv6}
43 }
44
45
46 func (h *netlinkHandle) EnsureAddressBind(address, devName string) (exist bool, err error) {
47 dev, err := h.LinkByName(devName)
48 if err != nil {
49 return false, fmt.Errorf("error get interface: %s, err: %v", devName, err)
50 }
51 addr := netutils.ParseIPSloppy(address)
52 if addr == nil {
53 return false, fmt.Errorf("error parse ip address: %s", address)
54 }
55 if err := h.AddrAdd(dev, &netlink.Addr{IPNet: netlink.NewIPNet(addr)}); err != nil {
56
57 if err == unix.EEXIST {
58 return true, nil
59 }
60 return false, fmt.Errorf("error bind address: %s to interface: %s, err: %v", address, devName, err)
61 }
62 return false, nil
63 }
64
65
66 func (h *netlinkHandle) UnbindAddress(address, devName string) error {
67 dev, err := h.LinkByName(devName)
68 if err != nil {
69 return fmt.Errorf("error get interface: %s, err: %v", devName, err)
70 }
71 addr := netutils.ParseIPSloppy(address)
72 if addr == nil {
73 return fmt.Errorf("error parse ip address: %s", address)
74 }
75 if err := h.AddrDel(dev, &netlink.Addr{IPNet: netlink.NewIPNet(addr)}); err != nil {
76 if err != unix.ENXIO {
77 return fmt.Errorf("error unbind address: %s from interface: %s, err: %v", address, devName, err)
78 }
79 }
80 return nil
81 }
82
83
84 func (h *netlinkHandle) EnsureDummyDevice(devName string) (bool, error) {
85 _, err := h.LinkByName(devName)
86 if err == nil {
87
88 return true, nil
89 }
90 dummy := &netlink.Dummy{
91 LinkAttrs: netlink.LinkAttrs{Name: devName},
92 }
93 return false, h.LinkAdd(dummy)
94 }
95
96
97 func (h *netlinkHandle) DeleteDummyDevice(devName string) error {
98 link, err := h.LinkByName(devName)
99 if err != nil {
100 _, ok := err.(netlink.LinkNotFoundError)
101 if ok {
102 return nil
103 }
104 return fmt.Errorf("error deleting a non-exist dummy device: %s, %v", devName, err)
105 }
106 dummy, ok := link.(*netlink.Dummy)
107 if !ok {
108 return fmt.Errorf("expect dummy device, got device type: %s", link.Type())
109 }
110 return h.LinkDel(dummy)
111 }
112
113
114 func (h *netlinkHandle) ListBindAddress(devName string) ([]string, error) {
115 dev, err := h.LinkByName(devName)
116 if err != nil {
117 return nil, fmt.Errorf("error get interface: %s, err: %v", devName, err)
118 }
119 addrs, err := h.AddrList(dev, 0)
120 if err != nil {
121 return nil, fmt.Errorf("error list bound address of interface: %s, err: %v", devName, err)
122 }
123 var ips []string
124 for _, addr := range addrs {
125 ips = append(ips, addr.IP.String())
126 }
127 return ips, nil
128 }
129
130
131
132
133 func (h *netlinkHandle) GetAllLocalAddresses() (sets.Set[string], error) {
134 addr, err := net.InterfaceAddrs()
135 if err != nil {
136 return nil, fmt.Errorf("Could not get addresses: %v", err)
137 }
138 return proxyutil.AddressSet(h.isValidForSet, addr), nil
139 }
140
141
142
143
144 func (h *netlinkHandle) GetLocalAddresses(dev string) (sets.Set[string], error) {
145 ifi, err := net.InterfaceByName(dev)
146 if err != nil {
147 return nil, fmt.Errorf("Could not get interface %s: %v", dev, err)
148 }
149 addr, err := ifi.Addrs()
150 if err != nil {
151 return nil, fmt.Errorf("Can't get addresses from %s: %v", ifi.Name, err)
152 }
153 return proxyutil.AddressSet(h.isValidForSet, addr), nil
154 }
155
156 func (h *netlinkHandle) isValidForSet(ip net.IP) bool {
157 if h.isIPv6 != netutils.IsIPv6(ip) {
158 return false
159 }
160 if h.isIPv6 && ip.IsLinkLocalUnicast() {
161 return false
162 }
163 if ip.IsLoopback() {
164 return false
165 }
166 return true
167 }
168
169
170
171
172
173
174 func (h *netlinkHandle) GetAllLocalAddressesExcept(dev string) (sets.Set[string], error) {
175 ifaces, err := net.Interfaces()
176 if err != nil {
177 return nil, err
178 }
179 var addr []net.Addr
180 for _, iface := range ifaces {
181 if iface.Name == dev {
182 continue
183 }
184 ifadr, err := iface.Addrs()
185 if err != nil {
186
187
188 klog.ErrorS(err, "Reading addresses", "interface", iface.Name)
189 continue
190 }
191 addr = append(addr, ifadr...)
192 }
193 return proxyutil.AddressSet(h.isValidForSet, addr), nil
194 }
195
View as plain text