1
16
17 package util
18
19 import (
20 "fmt"
21 "net"
22 "strconv"
23 "strings"
24
25 v1 "k8s.io/api/core/v1"
26 "k8s.io/apimachinery/pkg/types"
27 utilrand "k8s.io/apimachinery/pkg/util/rand"
28 "k8s.io/apimachinery/pkg/util/sets"
29 utilfeature "k8s.io/apiserver/pkg/util/feature"
30 "k8s.io/client-go/tools/events"
31 utilsysctl "k8s.io/component-helpers/node/util/sysctl"
32 "k8s.io/klog/v2"
33 helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
34 "k8s.io/kubernetes/pkg/features"
35 netutils "k8s.io/utils/net"
36 )
37
38 const (
39
40 IPv4ZeroCIDR = "0.0.0.0/0"
41
42
43 IPv6ZeroCIDR = "::/0"
44 )
45
46
47 func isValidEndpoint(host string, port int) bool {
48 return host != "" && port > 0
49 }
50
51
52
53 func BuildPortsToEndpointsMap(endpoints *v1.Endpoints) map[string][]string {
54 portsToEndpoints := map[string][]string{}
55 for i := range endpoints.Subsets {
56 ss := &endpoints.Subsets[i]
57 for i := range ss.Ports {
58 port := &ss.Ports[i]
59 for i := range ss.Addresses {
60 addr := &ss.Addresses[i]
61 if isValidEndpoint(addr.IP, int(port.Port)) {
62 portsToEndpoints[port.Name] = append(portsToEndpoints[port.Name], net.JoinHostPort(addr.IP, strconv.Itoa(int(port.Port))))
63 }
64 }
65 }
66 }
67 return portsToEndpoints
68 }
69
70
71
72 func IsZeroCIDR(cidr string) bool {
73 if cidr == IPv4ZeroCIDR || cidr == IPv6ZeroCIDR {
74 return true
75 }
76 return false
77 }
78
79
80 func IsLoopBack(ip string) bool {
81 netIP := netutils.ParseIPSloppy(ip)
82 if netIP != nil {
83 return netIP.IsLoopback()
84 }
85 return false
86 }
87
88
89 func GetLocalAddrs() ([]net.IP, error) {
90 var localAddrs []net.IP
91
92 addrs, err := net.InterfaceAddrs()
93 if err != nil {
94 return nil, err
95 }
96
97 for _, addr := range addrs {
98 ip, _, err := netutils.ParseCIDRSloppy(addr.String())
99 if err != nil {
100 return nil, err
101 }
102
103 localAddrs = append(localAddrs, ip)
104 }
105
106 return localAddrs, nil
107 }
108
109
110
111 func GetLocalAddrSet() netutils.IPSet {
112 localAddrs, err := GetLocalAddrs()
113 if err != nil {
114 klog.ErrorS(err, "Failed to get local addresses assuming no local IPs")
115 } else if len(localAddrs) == 0 {
116 klog.InfoS("No local addresses were found")
117 }
118
119 localAddrSet := netutils.IPSet{}
120 localAddrSet.Insert(localAddrs...)
121 return localAddrSet
122 }
123
124
125 func ShouldSkipService(service *v1.Service) bool {
126
127 if !helper.IsServiceIPSet(service) {
128 klog.V(3).InfoS("Skipping service due to cluster IP", "service", klog.KObj(service), "clusterIP", service.Spec.ClusterIP)
129 return true
130 }
131
132 if service.Spec.Type == v1.ServiceTypeExternalName {
133 klog.V(3).InfoS("Skipping service due to Type=ExternalName", "service", klog.KObj(service))
134 return true
135 }
136 return false
137 }
138
139
140
141 func AddressSet(isValid func(ip net.IP) bool, addrs []net.Addr) sets.Set[string] {
142 ips := sets.New[string]()
143 for _, a := range addrs {
144 var ip net.IP
145 switch v := a.(type) {
146 case *net.IPAddr:
147 ip = v.IP
148 case *net.IPNet:
149 ip = v.IP
150 default:
151 continue
152 }
153 if isValid(ip) {
154 ips.Insert(ip.String())
155 }
156 }
157 return ips
158 }
159
160
161 func LogAndEmitIncorrectIPVersionEvent(recorder events.EventRecorder, fieldName, fieldValue, svcNamespace, svcName string, svcUID types.UID) {
162 errMsg := fmt.Sprintf("%s in %s has incorrect IP version", fieldValue, fieldName)
163 klog.ErrorS(nil, "Incorrect IP version", "service", klog.KRef(svcNamespace, svcName), "field", fieldName, "value", fieldValue)
164 if recorder != nil {
165 recorder.Eventf(
166 &v1.ObjectReference{
167 Kind: "Service",
168 Name: svcName,
169 Namespace: svcNamespace,
170 UID: svcUID,
171 }, nil, v1.EventTypeWarning, "KubeProxyIncorrectIPVersion", "GatherEndpoints", errMsg)
172 }
173 }
174
175
176 func MapIPsByIPFamily(ipStrings []string) map[v1.IPFamily][]net.IP {
177 ipFamilyMap := map[v1.IPFamily][]net.IP{}
178 for _, ipStr := range ipStrings {
179 ip := netutils.ParseIPSloppy(ipStr)
180 if ip != nil {
181
182 ipFamily := GetIPFamilyFromIP(ip)
183 ipFamilyMap[ipFamily] = append(ipFamilyMap[ipFamily], ip)
184 } else {
185
186
187
188 if len(strings.TrimSpace(ipStr)) != 0 {
189 klog.ErrorS(nil, "Skipping invalid IP", "ip", ipStr)
190 }
191 }
192 }
193 return ipFamilyMap
194 }
195
196
197 func MapCIDRsByIPFamily(cidrsStrings []string) map[v1.IPFamily][]*net.IPNet {
198 ipFamilyMap := map[v1.IPFamily][]*net.IPNet{}
199 for _, cidrStrUntrimmed := range cidrsStrings {
200 cidrStr := strings.TrimSpace(cidrStrUntrimmed)
201 _, cidr, err := netutils.ParseCIDRSloppy(cidrStr)
202 if err != nil {
203
204 if len(cidrStr) != 0 {
205 klog.ErrorS(err, "Invalid CIDR ignored", "CIDR", cidrStr)
206 }
207 continue
208 }
209
210 ipFamily := convertToV1IPFamily(netutils.IPFamilyOfCIDR(cidr))
211 ipFamilyMap[ipFamily] = append(ipFamilyMap[ipFamily], cidr)
212 }
213 return ipFamilyMap
214 }
215
216
217 func GetIPFamilyFromIP(ip net.IP) v1.IPFamily {
218 return convertToV1IPFamily(netutils.IPFamilyOf(ip))
219 }
220
221
222 func convertToV1IPFamily(ipFamily netutils.IPFamily) v1.IPFamily {
223 switch ipFamily {
224 case netutils.IPv4:
225 return v1.IPv4Protocol
226 case netutils.IPv6:
227 return v1.IPv6Protocol
228 }
229
230 return v1.IPFamilyUnknown
231 }
232
233
234 func OtherIPFamily(ipFamily v1.IPFamily) v1.IPFamily {
235 if ipFamily == v1.IPv6Protocol {
236 return v1.IPv4Protocol
237 }
238
239 return v1.IPv6Protocol
240 }
241
242
243
244 func AppendPortIfNeeded(addr string, port int32) string {
245
246 if _, _, err := net.SplitHostPort(addr); err == nil {
247 return addr
248 }
249
250
251 ip := netutils.ParseIPSloppy(addr)
252 if ip == nil {
253 return addr
254 }
255
256
257 if ip.To4() != nil {
258 return fmt.Sprintf("%s:%d", addr, port)
259 }
260 return fmt.Sprintf("[%s]:%d", addr, port)
261 }
262
263
264
265 func ShuffleStrings(s []string) []string {
266 if s == nil {
267 return nil
268 }
269 shuffled := make([]string, len(s))
270 perm := utilrand.Perm(len(s))
271 for i, j := range perm {
272 shuffled[j] = s[i]
273 }
274 return shuffled
275 }
276
277
278 func EnsureSysctl(sysctl utilsysctl.Interface, name string, newVal int) error {
279 if oldVal, _ := sysctl.GetSysctl(name); oldVal != newVal {
280 if err := sysctl.SetSysctl(name, newVal); err != nil {
281 return fmt.Errorf("can't set sysctl %s to %d: %v", name, newVal, err)
282 }
283 klog.V(1).InfoS("Changed sysctl", "name", name, "before", oldVal, "after", newVal)
284 }
285 return nil
286 }
287
288
289 func GetClusterIPByFamily(ipFamily v1.IPFamily, service *v1.Service) string {
290
291 if len(service.Spec.IPFamilies) == 0 {
292 if len(service.Spec.ClusterIP) == 0 || service.Spec.ClusterIP == v1.ClusterIPNone {
293 return ""
294 }
295
296 IsIPv6Family := (ipFamily == v1.IPv6Protocol)
297 if IsIPv6Family == netutils.IsIPv6String(service.Spec.ClusterIP) {
298 return service.Spec.ClusterIP
299 }
300
301 return ""
302 }
303
304 for idx, family := range service.Spec.IPFamilies {
305 if family == ipFamily {
306 if idx < len(service.Spec.ClusterIPs) {
307 return service.Spec.ClusterIPs[idx]
308 }
309 }
310 }
311
312 return ""
313 }
314
315
316
317 func RevertPorts(replacementPortsMap, originalPortsMap map[netutils.LocalPort]netutils.Closeable) {
318 for k, v := range replacementPortsMap {
319
320 if originalPortsMap[k] == nil {
321 klog.V(2).InfoS("Closing local port", "port", k.String())
322 v.Close()
323 }
324 }
325 }
326
327 func IsVIPMode(ing v1.LoadBalancerIngress) bool {
328 if !utilfeature.DefaultFeatureGate.Enabled(features.LoadBalancerIPMode) {
329 return true
330 }
331 if ing.IPMode == nil {
332 return true
333 }
334 return *ing.IPMode == v1.LoadBalancerIPModeVIP
335 }
336
View as plain text