• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kubeovn / kube-ovn / 20450627652

23 Dec 2025 03:37AM UTC coverage: 22.548% (+0.01%) from 22.538%
20450627652

push

github

web-flow
refactor: unify environment variable names using util package constants (#6061)

Signed-off-by: zhangzujian <zhangzujian.7@gmail.com>

14 of 107 new or added lines in 27 files covered. (13.08%)

1 existing line in 1 file now uncovered.

12088 of 53609 relevant lines covered (22.55%)

0.26 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/pkg/daemon/controller_linux.go
1
package daemon
2

3
import (
4
        "errors"
5
        "fmt"
6
        "net"
7
        "os"
8
        "os/exec"
9
        "path/filepath"
10
        "reflect"
11
        "slices"
12
        "strings"
13
        "syscall"
14

15
        ovsutil "github.com/digitalocean/go-openvswitch/ovs"
16
        nadv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1"
17
        nadutils "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/utils"
18
        "github.com/kubeovn/felix/ipsets"
19
        "github.com/kubeovn/go-iptables/iptables"
20
        "github.com/vishvananda/netlink"
21
        "golang.org/x/sys/unix"
22
        v1 "k8s.io/api/core/v1"
23
        k8serrors "k8s.io/apimachinery/pkg/api/errors"
24
        "k8s.io/apimachinery/pkg/labels"
25
        utilruntime "k8s.io/apimachinery/pkg/util/runtime"
26
        "k8s.io/client-go/tools/cache"
27
        "k8s.io/klog/v2"
28
        k8sipset "k8s.io/kubernetes/pkg/proxy/ipvs/ipset"
29
        k8siptables "k8s.io/kubernetes/pkg/util/iptables"
30

31
        kubeovnv1 "github.com/kubeovn/kube-ovn/pkg/apis/kubeovn/v1"
32
        "github.com/kubeovn/kube-ovn/pkg/ovs"
33
        "github.com/kubeovn/kube-ovn/pkg/util"
34
)
35

36
const (
37
        kernelModuleIPTables  = "ip_tables"
38
        kernelModuleIP6Tables = "ip6_tables"
39
)
40

41
// ControllerRuntime represents runtime specific controller members
42
type ControllerRuntime struct {
43
        iptables         map[string]*iptables.IPTables
44
        iptablesObsolete map[string]*iptables.IPTables
45
        k8siptables      map[string]k8siptables.Interface
46
        k8sipsets        k8sipset.Interface
47
        ipsets           map[string]*ipsets.IPSets
48
        gwCounters       map[string]*util.GwIPtableCounters
49

50
        nmSyncer  *networkManagerSyncer
51
        ovsClient *ovsutil.Client
52
}
53

54
type LbServiceRules struct {
55
        IP          string
56
        Port        uint16
57
        Protocol    string
58
        BridgeName  string
59
        DstMac      string
60
        UnderlayNic string
61
}
62

63
func evalCommandSymlinks(cmd string) (string, error) {
×
64
        path, err := exec.LookPath(cmd)
×
65
        if err != nil {
×
66
                return "", fmt.Errorf("failed to search for command %q: %w", cmd, err)
×
67
        }
×
68
        file, err := filepath.EvalSymlinks(path)
×
69
        if err != nil {
×
70
                return "", fmt.Errorf("failed to read evaluate symbolic links for file %q: %w", path, err)
×
71
        }
×
72

73
        return file, nil
×
74
}
75

76
func isLegacyIptablesMode() (bool, error) {
×
77
        path, err := evalCommandSymlinks("iptables")
×
78
        if err != nil {
×
79
                return false, err
×
80
        }
×
81
        pathLegacy, err := evalCommandSymlinks("iptables-legacy")
×
82
        if err != nil {
×
83
                return false, err
×
84
        }
×
85
        return path == pathLegacy, nil
×
86
}
87

88
func (c *Controller) initRuntime() error {
×
89
        ok, err := isLegacyIptablesMode()
×
90
        if err != nil {
×
91
                klog.Errorf("failed to check iptables mode: %v", err)
×
92
                return err
×
93
        }
×
94
        if !ok {
×
95
                // iptables works in nft mode, we should migrate iptables rules
×
96
                c.iptablesObsolete = make(map[string]*iptables.IPTables, 2)
×
97
        }
×
98

99
        c.iptables = make(map[string]*iptables.IPTables)
×
100
        c.ipsets = make(map[string]*ipsets.IPSets)
×
101
        c.gwCounters = make(map[string]*util.GwIPtableCounters)
×
102
        c.k8siptables = make(map[string]k8siptables.Interface)
×
103
        c.k8sipsets = k8sipset.New()
×
104
        c.ovsClient = ovsutil.New()
×
105

×
106
        if c.protocol == kubeovnv1.ProtocolIPv4 || c.protocol == kubeovnv1.ProtocolDual {
×
107
                ipt, err := iptables.NewWithProtocol(iptables.ProtocolIPv4)
×
108
                if err != nil {
×
109
                        klog.Error(err)
×
110
                        return err
×
111
                }
×
112
                c.iptables[kubeovnv1.ProtocolIPv4] = ipt
×
113
                if c.iptablesObsolete != nil {
×
114
                        ok, err := kernelModuleLoaded(kernelModuleIPTables)
×
115
                        if err != nil {
×
116
                                klog.Errorf("failed to check kernel module %s: %v", kernelModuleIPTables, err)
×
117
                        }
×
118
                        if ok {
×
119
                                if ipt, err = iptables.NewWithProtocolAndMode(iptables.ProtocolIPv4, "legacy"); err != nil {
×
120
                                        klog.Error(err)
×
121
                                        return err
×
122
                                }
×
123
                                c.iptablesObsolete[kubeovnv1.ProtocolIPv4] = ipt
×
124
                        }
125
                }
126
                c.ipsets[kubeovnv1.ProtocolIPv4] = ipsets.NewIPSets(ipsets.NewIPVersionConfig(ipsets.IPFamilyV4, IPSetPrefix, nil, nil))
×
127
                c.k8siptables[kubeovnv1.ProtocolIPv4] = k8siptables.New(k8siptables.ProtocolIPv4)
×
128
        }
129
        if c.protocol == kubeovnv1.ProtocolIPv6 || c.protocol == kubeovnv1.ProtocolDual {
×
130
                ipt, err := iptables.NewWithProtocol(iptables.ProtocolIPv6)
×
131
                if err != nil {
×
132
                        klog.Error(err)
×
133
                        return err
×
134
                }
×
135
                c.iptables[kubeovnv1.ProtocolIPv6] = ipt
×
136
                if c.iptablesObsolete != nil {
×
137
                        ok, err := kernelModuleLoaded(kernelModuleIP6Tables)
×
138
                        if err != nil {
×
139
                                klog.Errorf("failed to check kernel module %s: %v", kernelModuleIP6Tables, err)
×
140
                        }
×
141
                        if ok {
×
142
                                if ipt, err = iptables.NewWithProtocolAndMode(iptables.ProtocolIPv6, "legacy"); err != nil {
×
143
                                        klog.Error(err)
×
144
                                        return err
×
145
                                }
×
146
                                c.iptablesObsolete[kubeovnv1.ProtocolIPv6] = ipt
×
147
                        }
148
                }
149
                c.ipsets[kubeovnv1.ProtocolIPv6] = ipsets.NewIPSets(ipsets.NewIPVersionConfig(ipsets.IPFamilyV6, IPSetPrefix, nil, nil))
×
150
                c.k8siptables[kubeovnv1.ProtocolIPv6] = k8siptables.New(k8siptables.ProtocolIPv6)
×
151
        }
152

153
        c.nmSyncer = newNetworkManagerSyncer()
×
154
        c.nmSyncer.Run(c.transferAddrsAndRoutes)
×
155

×
156
        return nil
×
157
}
158

159
func (c *Controller) handleEnableExternalLBAddressChange(oldSubnet, newSubnet *kubeovnv1.Subnet) error {
×
160
        var subnetName string
×
161
        var action string
×
162

×
163
        switch {
×
164
        case oldSubnet != nil && newSubnet != nil:
×
165
                subnetName = oldSubnet.Name
×
166
                if oldSubnet.Spec.EnableExternalLBAddress != newSubnet.Spec.EnableExternalLBAddress {
×
167
                        klog.Infof("EnableExternalLBAddress changed for subnet %s", newSubnet.Name)
×
168
                        if newSubnet.Spec.EnableExternalLBAddress {
×
169
                                action = "add"
×
170
                        } else {
×
171
                                action = "remove"
×
172
                        }
×
173
                }
174
        case oldSubnet != nil:
×
175
                subnetName = oldSubnet.Name
×
176
                if oldSubnet.Spec.EnableExternalLBAddress {
×
177
                        klog.Infof("EnableExternalLBAddress removed for subnet %s", oldSubnet.Name)
×
178
                        action = "remove"
×
179
                }
×
180
        case newSubnet != nil:
×
181
                subnetName = newSubnet.Name
×
182
                if newSubnet.Spec.EnableExternalLBAddress {
×
183
                        klog.Infof("EnableExternalLBAddress added for subnet %s", newSubnet.Name)
×
184
                        action = "add"
×
185
                }
×
186
        }
187

188
        if action != "" {
×
189
                services, err := c.servicesLister.List(labels.Everything())
×
190
                if err != nil {
×
191
                        klog.Errorf("failed to list services: %v", err)
×
192
                        return err
×
193
                }
×
194

195
                for _, svc := range services {
×
196
                        if svc.Annotations[util.ServiceExternalIPFromSubnetAnnotation] == subnetName {
×
197
                                klog.Infof("Service %s/%s has external LB address pool annotation from subnet %s, action: %s", svc.Namespace, svc.Name, subnetName, action)
×
198
                                switch action {
×
199
                                case "add":
×
200
                                        c.serviceQueue.Add(&serviceEvent{newObj: svc})
×
201
                                case "remove":
×
202
                                        c.serviceQueue.Add(&serviceEvent{oldObj: svc})
×
203
                                }
204
                        }
205
                }
206
        }
207
        return nil
×
208
}
209

210
func (c *Controller) reconcileRouters(event *subnetEvent) error {
×
211
        subnets, err := c.subnetsLister.List(labels.Everything())
×
212
        if err != nil {
×
213
                klog.Errorf("failed to list subnets %v", err)
×
214
                return err
×
215
        }
×
216

217
        if event != nil {
×
218
                var ok bool
×
219
                var oldSubnet, newSubnet *kubeovnv1.Subnet
×
220
                if event.oldObj != nil {
×
221
                        if oldSubnet, ok = event.oldObj.(*kubeovnv1.Subnet); !ok {
×
222
                                klog.Errorf("expected old subnet in subnetEvent but got %#v", event.oldObj)
×
223
                                return nil
×
224
                        }
×
225
                }
226
                if event.newObj != nil {
×
227
                        if newSubnet, ok = event.newObj.(*kubeovnv1.Subnet); !ok {
×
228
                                klog.Errorf("expected new subnet in subnetEvent but got %#v", event.newObj)
×
229
                                return nil
×
230
                        }
×
231
                }
232

233
                isAdd, needAction := c.CheckSubnetU2OChangeAction(oldSubnet, newSubnet)
×
234
                if needAction {
×
235
                        if err := c.HandleU2OForSubnet(newSubnet, isAdd); err != nil {
×
236
                                return err
×
237
                        }
×
238
                }
239

240
                if err = c.handleEnableExternalLBAddressChange(oldSubnet, newSubnet); err != nil {
×
241
                        klog.Errorf("failed to handle enable external lb address change: %v", err)
×
242
                        return err
×
243
                }
×
244
                // handle policy routing
245
                rulesToAdd, rulesToDel, routesToAdd, routesToDel, err := c.diffPolicyRouting(oldSubnet, newSubnet)
×
246
                if err != nil {
×
247
                        klog.Errorf("failed to get policy routing difference: %v", err)
×
248
                        return err
×
249
                }
×
250
                // add new routes first
251
                for _, r := range routesToAdd {
×
252
                        if err = netlink.RouteReplace(&r); err != nil && !errors.Is(err, syscall.EEXIST) {
×
253
                                klog.Errorf("failed to replace route for subnet %s: %v", newSubnet.Name, err)
×
254
                                return err
×
255
                        }
×
256
                }
257
                // next, add new rules
258
                for _, r := range rulesToAdd {
×
259
                        if err = netlink.RuleAdd(&r); err != nil && !errors.Is(err, syscall.EEXIST) {
×
260
                                klog.Errorf("failed to add network rule for subnet %s: %v", newSubnet.Name, err)
×
261
                                return err
×
262
                        }
×
263
                }
264
                // then delete old network rules
265
                for _, r := range rulesToDel {
×
266
                        // loop to delete all matched rules
×
267
                        for {
×
268
                                if err = netlink.RuleDel(&r); err != nil {
×
269
                                        if !errors.Is(err, syscall.ENOENT) {
×
270
                                                klog.Errorf("failed to delete network rule for subnet %s: %v", oldSubnet.Name, err)
×
271
                                                return err
×
272
                                        }
×
273
                                        break
×
274
                                }
275
                        }
276
                }
277
                // last, delete old network routes
278
                for _, r := range routesToDel {
×
279
                        if err = netlink.RouteDel(&r); err != nil && !errors.Is(err, syscall.ENOENT) {
×
280
                                klog.Errorf("failed to delete route for subnet %s: %v", oldSubnet.Name, err)
×
281
                                return err
×
282
                        }
×
283
                }
284
        }
285

286
        node, err := c.nodesLister.Get(c.config.NodeName)
×
287
        if err != nil {
×
288
                klog.Errorf("failed to get node %s %v", c.config.NodeName, err)
×
289
                return err
×
290
        }
×
291
        nodeIPv4, nodeIPv6 := util.GetNodeInternalIP(*node)
×
292
        var joinIPv4, joinIPv6 string
×
293
        if len(node.Annotations) != 0 {
×
294
                joinIPv4, joinIPv6 = util.SplitStringIP(node.Annotations[util.IPAddressAnnotation])
×
295
        }
×
296

297
        joinCIDR := make([]string, 0, 2)
×
298
        cidrs := make([]string, 0, len(subnets)*2)
×
299
        for _, subnet := range subnets {
×
300
                // The route for overlay subnet cidr via ovn0 should not be deleted even though subnet.Status has changed to not ready
×
301
                if subnet.Spec.Vpc != c.config.ClusterRouter ||
×
302
                        (subnet.Spec.Vlan != "" && !subnet.Spec.LogicalGateway && (!subnet.Spec.U2OInterconnection || (subnet.Spec.EnableLb != nil && *subnet.Spec.EnableLb))) ||
×
303
                        !subnet.Status.IsValidated() {
×
304
                        continue
×
305
                }
306

307
                for cidrBlock := range strings.SplitSeq(subnet.Spec.CIDRBlock, ",") {
×
308
                        if _, ipNet, err := net.ParseCIDR(cidrBlock); err != nil {
×
309
                                klog.Errorf("%s is not a valid cidr block", cidrBlock)
×
310
                        } else {
×
311
                                if nodeIPv4 != "" && util.CIDRContainIP(cidrBlock, nodeIPv4) {
×
312
                                        continue
×
313
                                }
314
                                if nodeIPv6 != "" && util.CIDRContainIP(cidrBlock, nodeIPv6) {
×
315
                                        continue
×
316
                                }
317
                                cidrs = append(cidrs, ipNet.String())
×
318
                                if subnet.Name == c.config.NodeSwitch {
×
319
                                        joinCIDR = append(joinCIDR, ipNet.String())
×
320
                                }
×
321
                        }
322
                }
323
        }
324

325
        gateway, ok := node.Annotations[util.GatewayAnnotation]
×
326
        if !ok {
×
NEW
327
                err = fmt.Errorf("gateway annotation for node %s does not exist", node.Name)
×
NEW
328
                klog.Error(err)
×
NEW
329
                return err
×
330
        }
×
331
        nic, err := netlink.LinkByName(util.NodeNic)
×
332
        if err != nil {
×
333
                klog.Errorf("failed to get nic %s", util.NodeNic)
×
334
                return fmt.Errorf("failed to get nic %s", util.NodeNic)
×
335
        }
×
336

337
        allRoutes, err := getNicExistRoutes(nil, gateway)
×
338
        if err != nil {
×
339
                klog.Error(err)
×
340
                return err
×
341
        }
×
342
        nodeNicRoutes, err := getNicExistRoutes(nic, gateway)
×
343
        if err != nil {
×
344
                klog.Error(err)
×
345
                return err
×
346
        }
×
347
        toAdd, toDel := routeDiff(nodeNicRoutes, allRoutes, cidrs, joinCIDR, joinIPv4, joinIPv6, gateway, net.ParseIP(nodeIPv4), net.ParseIP(nodeIPv6))
×
348
        for _, r := range toDel {
×
349
                if err = netlink.RouteDel(&netlink.Route{Dst: r.Dst}); err != nil {
×
350
                        klog.Errorf("failed to del route %v", err)
×
351
                }
×
352
        }
353

354
        for _, r := range toAdd {
×
355
                r.LinkIndex = nic.Attrs().Index
×
356
                if err = netlink.RouteReplace(&r); err != nil {
×
357
                        klog.Errorf("failed to replace route %v: %v", r, err)
×
358
                }
×
359
        }
360

361
        return nil
×
362
}
363

364
func genLBServiceRules(service *v1.Service, bridgeName, underlayNic string) []LbServiceRules {
×
365
        var lbServiceRules []LbServiceRules
×
366
        for _, ingress := range service.Status.LoadBalancer.Ingress {
×
367
                for _, port := range service.Spec.Ports {
×
368
                        lbServiceRules = append(lbServiceRules, LbServiceRules{
×
369
                                IP:          ingress.IP,
×
370
                                Port:        uint16(port.Port), // #nosec G115
×
371
                                Protocol:    string(port.Protocol),
×
372
                                DstMac:      util.MasqueradeExternalLBAccessMac,
×
373
                                UnderlayNic: underlayNic,
×
374
                                BridgeName:  bridgeName,
×
375
                        })
×
376
                }
×
377
        }
378
        return lbServiceRules
×
379
}
380

381
func (c *Controller) diffExternalLBServiceRules(oldService, newService *v1.Service, isSubnetExternalLBEnabled bool) (lbServiceRulesToAdd, lbServiceRulesToDel []LbServiceRules, err error) {
×
382
        var oldlbServiceRules, newlbServiceRules []LbServiceRules
×
383

×
384
        if oldService != nil && oldService.Annotations[util.ServiceExternalIPFromSubnetAnnotation] != "" {
×
385
                oldBridgeName, underlayNic, err := c.getExtInfoBySubnet(oldService.Annotations[util.ServiceExternalIPFromSubnetAnnotation])
×
386
                if err != nil {
×
387
                        klog.Errorf("failed to get provider network by subnet %s: %v", oldService.Annotations[util.ServiceExternalIPFromSubnetAnnotation], err)
×
388
                        return nil, nil, err
×
389
                }
×
390

391
                oldlbServiceRules = genLBServiceRules(oldService, oldBridgeName, underlayNic)
×
392
        }
393

394
        if isSubnetExternalLBEnabled && newService != nil && newService.Annotations[util.ServiceExternalIPFromSubnetAnnotation] != "" {
×
395
                newBridgeName, underlayNic, err := c.getExtInfoBySubnet(newService.Annotations[util.ServiceExternalIPFromSubnetAnnotation])
×
396
                if err != nil {
×
397
                        klog.Errorf("failed to get provider network by subnet %s: %v", newService.Annotations[util.ServiceExternalIPFromSubnetAnnotation], err)
×
398
                        return nil, nil, err
×
399
                }
×
400
                newlbServiceRules = genLBServiceRules(newService, newBridgeName, underlayNic)
×
401
        }
402

403
        for _, oldRule := range oldlbServiceRules {
×
404
                found := slices.Contains(newlbServiceRules, oldRule)
×
405
                if !found {
×
406
                        lbServiceRulesToDel = append(lbServiceRulesToDel, oldRule)
×
407
                }
×
408
        }
409

410
        for _, newRule := range newlbServiceRules {
×
411
                found := slices.Contains(oldlbServiceRules, newRule)
×
412
                if !found {
×
413
                        lbServiceRulesToAdd = append(lbServiceRulesToAdd, newRule)
×
414
                }
×
415
        }
416

417
        return lbServiceRulesToAdd, lbServiceRulesToDel, nil
×
418
}
419

420
func (c *Controller) getExtInfoBySubnet(subnetName string) (string, string, error) {
×
421
        subnet, err := c.subnetsLister.Get(subnetName)
×
422
        if err != nil {
×
423
                klog.Errorf("failed to get subnet %s: %v", subnetName, err)
×
424
                return "", "", err
×
425
        }
×
426

427
        vlanName := subnet.Spec.Vlan
×
428
        if vlanName == "" {
×
429
                return "", "", errors.New("vlan not specified in subnet")
×
430
        }
×
431

432
        vlan, err := c.vlansLister.Get(vlanName)
×
433
        if err != nil {
×
434
                klog.Errorf("failed to get vlan %s: %v", vlanName, err)
×
435
                return "", "", err
×
436
        }
×
437

438
        providerNetworkName := vlan.Spec.Provider
×
439
        if providerNetworkName == "" {
×
440
                return "", "", errors.New("provider network not specified in vlan")
×
441
        }
×
442

443
        pn, err := c.providerNetworksLister.Get(providerNetworkName)
×
444
        if err != nil {
×
445
                klog.Errorf("failed to get provider network %s: %v", providerNetworkName, err)
×
446
                return "", "", err
×
447
        }
×
448

449
        underlayNic := pn.Spec.DefaultInterface
×
450
        for _, item := range pn.Spec.CustomInterfaces {
×
451
                if slices.Contains(item.Nodes, c.config.NodeName) {
×
452
                        underlayNic = item.Interface
×
453
                        break
×
454
                }
455
        }
456
        klog.Infof("Provider network: %s, Underlay NIC: %s", providerNetworkName, underlayNic)
×
457
        return util.ExternalBridgeName(providerNetworkName), underlayNic, nil
×
458
}
459

460
func (c *Controller) reconcileServices(event *serviceEvent) error {
×
461
        if event == nil {
×
462
                return nil
×
463
        }
×
464
        var ok bool
×
465
        var oldService, newService *v1.Service
×
466
        if event.oldObj != nil {
×
467
                if oldService, ok = event.oldObj.(*v1.Service); !ok {
×
468
                        klog.Errorf("expected old service in serviceEvent but got %#v", event.oldObj)
×
469
                        return nil
×
470
                }
×
471
        }
472

473
        if event.newObj != nil {
×
474
                if newService, ok = event.newObj.(*v1.Service); !ok {
×
475
                        klog.Errorf("expected new service in serviceEvent but got %#v", event.newObj)
×
476
                        return nil
×
477
                }
×
478
        }
479

480
        // check is the lb service IP related subnet's EnableExternalLBAddress
481
        isSubnetExternalLBEnabled := false
×
482
        if newService != nil && newService.Annotations[util.ServiceExternalIPFromSubnetAnnotation] != "" {
×
483
                subnet, err := c.subnetsLister.Get(newService.Annotations[util.ServiceExternalIPFromSubnetAnnotation])
×
484
                if err != nil {
×
485
                        klog.Errorf("failed to get subnet %s: %v", newService.Annotations[util.ServiceExternalIPFromSubnetAnnotation], err)
×
486
                        return err
×
487
                }
×
488
                isSubnetExternalLBEnabled = subnet.Spec.EnableExternalLBAddress
×
489
        }
490

491
        lbServiceRulesToAdd, lbServiceRulesToDel, err := c.diffExternalLBServiceRules(oldService, newService, isSubnetExternalLBEnabled)
×
492
        if err != nil {
×
493
                klog.Errorf("failed to get ip port difference: %v", err)
×
494
                return err
×
495
        }
×
496

497
        if len(lbServiceRulesToAdd) > 0 {
×
498
                for _, rule := range lbServiceRulesToAdd {
×
499
                        klog.Infof("Adding LB service rule: %+v", rule)
×
500
                        if err := ovs.AddOrUpdateUnderlaySubnetSvcLocalOpenFlow(c.ovsClient, rule.BridgeName, rule.IP, rule.Protocol, rule.DstMac, rule.UnderlayNic, rule.Port); err != nil {
×
501
                                klog.Errorf("failed to add or update underlay subnet svc local openflow: %v", err)
×
502
                        }
×
503
                }
504
        }
505

506
        if len(lbServiceRulesToDel) > 0 {
×
507
                for _, rule := range lbServiceRulesToDel {
×
508
                        klog.Infof("Delete LB service rule: %+v", rule)
×
509
                        if err := ovs.DeleteUnderlaySubnetSvcLocalOpenFlow(c.ovsClient, rule.BridgeName, rule.IP, rule.Protocol, rule.UnderlayNic, rule.Port); err != nil {
×
510
                                klog.Errorf("failed to delete underlay subnet svc local openflow: %v", err)
×
511
                        }
×
512
                }
513
        }
514

515
        return nil
×
516
}
517

518
func getNicExistRoutes(nic netlink.Link, gateway string) ([]netlink.Route, error) {
×
519
        var routes, existRoutes []netlink.Route
×
520
        var err error
×
521
        for gw := range strings.SplitSeq(gateway, ",") {
×
522
                if util.CheckProtocol(gw) == kubeovnv1.ProtocolIPv4 {
×
523
                        routes, err = netlink.RouteList(nic, netlink.FAMILY_V4)
×
524
                } else {
×
525
                        routes, err = netlink.RouteList(nic, netlink.FAMILY_V6)
×
526
                }
×
527
                if err != nil {
×
528
                        return nil, err
×
529
                }
×
530
                existRoutes = append(existRoutes, routes...)
×
531
        }
532
        return existRoutes, nil
×
533
}
534

535
func routeDiff(nodeNicRoutes, allRoutes []netlink.Route, cidrs, joinCIDR []string, joinIPv4, joinIPv6, gateway string, srcIPv4, srcIPv6 net.IP) (toAdd, toDel []netlink.Route) {
×
536
        // joinIPv6 is not used for now
×
537
        _ = joinIPv6
×
538

×
539
        for _, route := range nodeNicRoutes {
×
540
                if route.Scope == netlink.SCOPE_LINK || route.Dst == nil || route.Dst.IP.IsLinkLocalUnicast() {
×
541
                        continue
×
542
                }
543

544
                found := slices.Contains(cidrs, route.Dst.String())
×
545
                if !found {
×
546
                        toDel = append(toDel, route)
×
547
                }
×
548
                conflict := false
×
549
                for _, ar := range allRoutes {
×
550
                        if ar.Dst != nil && ar.Dst.String() == route.Dst.String() && ar.LinkIndex != route.LinkIndex {
×
551
                                // route conflict
×
552
                                conflict = true
×
553
                                break
×
554
                        }
555
                }
556
                if conflict {
×
557
                        toDel = append(toDel, route)
×
558
                }
×
559
        }
560
        if len(toDel) > 0 {
×
561
                klog.Infof("routes to delete: %v", toDel)
×
562
        }
×
563

564
        ipv4, ipv6 := util.SplitStringIP(gateway)
×
565
        gwV4, gwV6 := net.ParseIP(ipv4), net.ParseIP(ipv6)
×
566
        for _, c := range cidrs {
×
567
                var src, gw net.IP
×
568
                switch util.CheckProtocol(c) {
×
569
                case kubeovnv1.ProtocolIPv4:
×
570
                        src, gw = srcIPv4, gwV4
×
571
                case kubeovnv1.ProtocolIPv6:
×
572
                        src, gw = srcIPv6, gwV6
×
573
                }
574

575
                found := false
×
576
                for _, ar := range allRoutes {
×
577
                        if ar.Dst != nil && ar.Dst.String() == c {
×
578
                                if slices.Contains(joinCIDR, c) {
×
579
                                        // Only compare Dst for join subnets
×
580
                                        found = true
×
581
                                        klog.V(3).Infof("[routeDiff] joinCIDR route already exists in allRoutes: %v", ar)
×
582
                                        break
×
583
                                } else if (ar.Src == nil && src == nil) || (ar.Src != nil && src != nil && ar.Src.Equal(src)) {
×
584
                                        // For non-join subnets, both Dst and Src must be the same
×
585
                                        found = true
×
586
                                        klog.V(3).Infof("[routeDiff] route already exists in allRoutes: %v", ar)
×
587
                                        break
×
588
                                }
589
                        }
590
                }
591
                if found {
×
592
                        continue
×
593
                }
594
                for _, r := range nodeNicRoutes {
×
595
                        if r.Dst == nil || r.Dst.String() != c {
×
596
                                continue
×
597
                        }
598
                        if (src == nil && r.Src == nil) || (src != nil && r.Src != nil && src.Equal(r.Src)) {
×
599
                                found = true
×
600
                                break
×
601
                        }
602
                }
603
                if !found {
×
604
                        var priority int
×
605
                        scope := netlink.SCOPE_UNIVERSE
×
606
                        proto := netlink.RouteProtocol(syscall.RTPROT_STATIC)
×
607
                        if slices.Contains(joinCIDR, c) {
×
608
                                if util.CheckProtocol(c) == kubeovnv1.ProtocolIPv4 {
×
609
                                        src = net.ParseIP(joinIPv4)
×
610
                                } else {
×
611
                                        src, priority = nil, 256
×
612
                                }
×
613
                                gw, scope = nil, netlink.SCOPE_LINK
×
614
                                proto = netlink.RouteProtocol(unix.RTPROT_KERNEL)
×
615
                        }
616
                        _, cidr, _ := net.ParseCIDR(c)
×
617
                        toAdd = append(toAdd, netlink.Route{
×
618
                                Dst:      cidr,
×
619
                                Src:      src,
×
620
                                Gw:       gw,
×
621
                                Protocol: proto,
×
622
                                Scope:    scope,
×
623
                                Priority: priority,
×
624
                        })
×
625
                }
626
        }
627
        if len(toAdd) > 0 {
×
628
                klog.Infof("routes to add: %v", toAdd)
×
629
        }
×
630
        return toAdd, toDel
×
631
}
632

633
func getRulesToAdd(oldRules, newRules []netlink.Rule) []netlink.Rule {
×
634
        var toAdd []netlink.Rule
×
635

×
636
        for _, rule := range newRules {
×
637
                var found bool
×
638
                for _, r := range oldRules {
×
639
                        if r.Family == rule.Family && r.Priority == rule.Priority && r.Table == rule.Table && reflect.DeepEqual(r.Src, rule.Src) {
×
640
                                found = true
×
641
                                break
×
642
                        }
643
                }
644
                if !found {
×
645
                        toAdd = append(toAdd, rule)
×
646
                }
×
647
        }
648

649
        return toAdd
×
650
}
651

652
func getRoutesToAdd(oldRoutes, newRoutes []netlink.Route) []netlink.Route {
×
653
        var toAdd []netlink.Route
×
654

×
655
        for _, route := range newRoutes {
×
656
                var found bool
×
657
                for _, r := range oldRoutes {
×
658
                        if r.Equal(route) {
×
659
                                found = true
×
660
                                break
×
661
                        }
662
                }
663
                if !found {
×
664
                        toAdd = append(toAdd, route)
×
665
                }
×
666
        }
667

668
        return toAdd
×
669
}
670

671
func (c *Controller) diffPolicyRouting(oldSubnet, newSubnet *kubeovnv1.Subnet) (rulesToAdd, rulesToDel []netlink.Rule, routesToAdd, routesToDel []netlink.Route, err error) {
×
672
        oldRules, oldRoutes, err := c.getPolicyRouting(oldSubnet)
×
673
        if err != nil {
×
674
                klog.Error(err)
×
675
                return rulesToAdd, rulesToDel, routesToAdd, routesToDel, err
×
676
        }
×
677
        newRules, newRoutes, err := c.getPolicyRouting(newSubnet)
×
678
        if err != nil {
×
679
                klog.Error(err)
×
680
                return rulesToAdd, rulesToDel, routesToAdd, routesToDel, err
×
681
        }
×
682

683
        rulesToAdd = getRulesToAdd(oldRules, newRules)
×
684
        rulesToDel = getRulesToAdd(newRules, oldRules)
×
685
        routesToAdd = getRoutesToAdd(oldRoutes, newRoutes)
×
686
        routesToDel = getRoutesToAdd(newRoutes, oldRoutes)
×
687

×
688
        return rulesToAdd, rulesToDel, routesToAdd, routesToDel, err
×
689
}
690

691
func (c *Controller) getPolicyRouting(subnet *kubeovnv1.Subnet) ([]netlink.Rule, []netlink.Route, error) {
×
692
        if subnet == nil || subnet.Spec.ExternalEgressGateway == "" || subnet.Spec.Vpc != c.config.ClusterRouter {
×
693
                return nil, nil, nil
×
694
        }
×
695
        if subnet.Spec.GatewayType == kubeovnv1.GWCentralizedType {
×
696
                node, err := c.nodesLister.Get(c.config.NodeName)
×
697
                if err != nil {
×
698
                        klog.Errorf("failed to get node %s: %v", c.config.NodeName, err)
×
699
                        return nil, nil, err
×
700
                }
×
701
                isGatewayNode := util.GatewayContains(subnet.Spec.GatewayNode, c.config.NodeName) ||
×
702
                        (subnet.Spec.GatewayNode == "" && util.MatchLabelSelectors(subnet.Spec.GatewayNodeSelectors, node.Labels))
×
703
                if !isGatewayNode {
×
704
                        return nil, nil, nil
×
705
                }
×
706
        }
707

708
        protocols := make([]string, 1, 2)
×
709
        if protocol := util.CheckProtocol(subnet.Spec.ExternalEgressGateway); protocol == kubeovnv1.ProtocolDual {
×
710
                protocols[0] = kubeovnv1.ProtocolIPv4
×
711
                protocols = append(protocols, kubeovnv1.ProtocolIPv6)
×
712
        } else {
×
713
                protocols[0] = protocol
×
714
        }
×
715

716
        cidr := strings.Split(subnet.Spec.CIDRBlock, ",")
×
717
        egw := strings.Split(subnet.Spec.ExternalEgressGateway, ",")
×
718

×
719
        // rules
×
720
        var rules []netlink.Rule
×
721
        rule := netlink.NewRule()
×
722
        rule.Table = int(subnet.Spec.PolicyRoutingTableID)
×
723
        rule.Priority = int(subnet.Spec.PolicyRoutingPriority)
×
724
        if subnet.Spec.GatewayType == kubeovnv1.GWDistributedType {
×
725
                pods, err := c.podsLister.List(labels.Everything())
×
726
                if err != nil {
×
727
                        klog.Errorf("list pods failed, %+v", err)
×
728
                        return nil, nil, err
×
729
                }
×
730

NEW
731
                nodeName := os.Getenv(util.EnvNodeName)
×
732
                for _, pod := range pods {
×
733
                        if pod.Spec.HostNetwork ||
×
734
                                pod.Status.PodIP == "" ||
×
735
                                pod.Annotations[util.LogicalSwitchAnnotation] != subnet.Name ||
×
NEW
736
                                pod.Spec.NodeName != nodeName {
×
737
                                continue
×
738
                        }
739

740
                        for i := range protocols {
×
741
                                rule.Family, _ = util.ProtocolToFamily(protocols[i])
×
742

×
743
                                var ip net.IP
×
744
                                var maskBits int
×
745
                                if len(pod.Status.PodIPs) == 2 && protocols[i] == kubeovnv1.ProtocolIPv6 {
×
746
                                        ip = net.ParseIP(pod.Status.PodIPs[1].IP)
×
747
                                        maskBits = 128
×
748
                                } else if util.CheckProtocol(pod.Status.PodIP) == protocols[i] {
×
749
                                        ip = net.ParseIP(pod.Status.PodIP)
×
750
                                        maskBits = 32
×
751
                                        if rule.Family == netlink.FAMILY_V6 {
×
752
                                                maskBits = 128
×
753
                                        }
×
754
                                }
755

756
                                rule.Src = &net.IPNet{IP: ip, Mask: net.CIDRMask(maskBits, maskBits)}
×
757
                                rules = append(rules, *rule)
×
758
                        }
759
                }
760
        } else {
×
761
                for i := range protocols {
×
762
                        rule.Family, _ = util.ProtocolToFamily(protocols[i])
×
763
                        if len(cidr) == len(protocols) {
×
764
                                _, rule.Src, _ = net.ParseCIDR(cidr[i])
×
765
                        }
×
766
                        rules = append(rules, *rule)
×
767
                }
768
        }
769

770
        // routes
771
        var routes []netlink.Route
×
772
        for i := range protocols {
×
773
                routes = append(routes, netlink.Route{
×
774
                        Protocol: netlink.RouteProtocol(syscall.RTPROT_STATIC),
×
775
                        Table:    int(subnet.Spec.PolicyRoutingTableID),
×
776
                        Gw:       net.ParseIP(egw[i]),
×
777
                })
×
778
        }
×
779

780
        return rules, routes, nil
×
781
}
782

783
func (c *Controller) GetProviderInfoFromSubnet(subnet *kubeovnv1.Subnet) (bridgeName, chassisMac string, err error) {
×
784
        if subnet == nil {
×
785
                return "", "", nil
×
786
        }
×
787
        if subnet.Spec.Vlan == "" {
×
788
                return "", "", nil
×
789
        }
×
790

791
        vlan, err := c.vlansLister.Get(subnet.Spec.Vlan)
×
792
        if err != nil {
×
793
                return "", "", fmt.Errorf("failed to get vlan %s: %w", subnet.Spec.Vlan, err)
×
794
        }
×
795
        providerName := vlan.Spec.Provider
×
796
        chassisMac, err = GetProviderChassisMac(providerName)
×
797
        if err != nil {
×
798
                return "", "", fmt.Errorf("failed to get chassis mac for provider %s: %w", providerName, err)
×
799
        }
×
800

801
        bridgeName = util.ExternalBridgeName(providerName)
×
802
        return bridgeName, chassisMac, nil
×
803
}
804

805
func HandleU2OForPod(ovsClient *ovsutil.Client, pod *v1.Pod, bridgeName, chassisMac, subnetName string, isAdd bool) error {
×
806
        if pod == nil {
×
807
                return errors.New("pod is nil")
×
808
        }
×
809

810
        podMac := pod.Annotations[util.MacAddressAnnotation]
×
811

×
812
        podIPs := []string{}
×
813
        if pod.Annotations != nil && pod.Annotations[util.IPAddressAnnotation] != "" {
×
814
                podIPs = append(podIPs, strings.Split(pod.Annotations[util.IPAddressAnnotation], ",")...)
×
815

×
816
                for _, podIP := range podIPs {
×
817
                        var err error
×
818
                        if isAdd {
×
819
                                err = ovs.AddOrUpdateU2OKeepSrcMac(ovsClient, bridgeName, podIP, podMac, chassisMac, subnetName)
×
820
                        } else {
×
821
                                err = ovs.DeleteU2OKeepSrcMac(ovsClient, bridgeName, podIP, chassisMac, subnetName)
×
822
                        }
×
823

824
                        if err != nil {
×
825
                                action := "add"
×
826
                                if !isAdd {
×
827
                                        action = "delete"
×
828
                                }
×
829
                                return fmt.Errorf("failed to %s U2O rule for pod %s/%s: %w", action, pod.Namespace, pod.Name, err)
×
830
                        }
831
                }
832
        }
833

834
        return nil
×
835
}
836

837
func (c *Controller) HandleU2OForSubnet(subnet *kubeovnv1.Subnet, isAdd bool) error {
×
838
        klog.Infof("U2O processing for subnet %s, action: %v", subnet.Name, isAdd)
×
839

×
840
        bridgeName, chassisMac, err := c.GetProviderInfoFromSubnet(subnet)
×
841
        if err != nil {
×
842
                return fmt.Errorf("failed to get provider info: %w", err)
×
843
        }
×
844

845
        pods, err := c.podsLister.List(labels.Everything())
×
846
        if err != nil {
×
847
                return fmt.Errorf("failed to list pods: %w", err)
×
848
        }
×
849

850
        for _, pod := range pods {
×
851
                if pod.Annotations[util.LogicalSwitchAnnotation] != subnet.Name {
×
852
                        continue
×
853
                }
854
                if err := HandleU2OForPod(c.ovsClient, pod, bridgeName, chassisMac, subnet.Name, isAdd); err != nil {
×
855
                        klog.Error(err)
×
856
                        return err
×
857
                }
×
858
        }
859

860
        return nil
×
861
}
862

863
func (c *Controller) CheckSubnetU2OChangeAction(oldSubnet, newSubnet *kubeovnv1.Subnet) (bool, bool) {
×
864
        if newSubnet == nil ||
×
865
                (oldSubnet != nil && oldSubnet.Spec.U2OInterconnection == newSubnet.Spec.U2OInterconnection) {
×
866
                return false, false
×
867
        }
×
868

869
        if newSubnet.Spec.Vlan == "" || newSubnet.Spec.LogicalGateway {
×
870
                return false, false
×
871
        }
×
872

873
        return newSubnet.Spec.U2OInterconnection, true
×
874
}
875

876
func (c *Controller) handleUpdatePod(key string) error {
×
877
        namespace, name, err := cache.SplitMetaNamespaceKey(key)
×
878
        if err != nil {
×
879
                utilruntime.HandleError(fmt.Errorf("invalid resource key: %s", key))
×
880
                return nil
×
881
        }
×
882
        klog.Infof("handle qos update for pod %s/%s", namespace, name)
×
883

×
884
        pod, err := c.podsLister.Pods(namespace).Get(name)
×
885
        if err != nil {
×
886
                if k8serrors.IsNotFound(err) {
×
887
                        return nil
×
888
                }
×
889
                klog.Error(err)
×
890
                return err
×
891
        }
892

893
        if err := util.ValidatePodNetwork(pod.Annotations); err != nil {
×
894
                klog.Errorf("validate pod %s/%s failed, %v", namespace, name, err)
×
895
                c.recorder.Eventf(pod, v1.EventTypeWarning, "ValidatePodNetworkFailed", err.Error())
×
896
                return err
×
897
        }
×
898

899
        if _, ok := pod.Annotations[util.LogicalSwitchAnnotation]; ok {
×
900
                subnet, err := c.subnetsLister.Get(pod.Annotations[util.LogicalSwitchAnnotation])
×
901
                if err != nil {
×
902
                        klog.Error(err)
×
903
                        return err
×
904
                }
×
905

906
                if subnet.Spec.U2OInterconnection {
×
907
                        bridgeName, chassisMac, err := c.GetProviderInfoFromSubnet(subnet)
×
908
                        if err != nil {
×
909
                                klog.Error(err)
×
910
                                return err
×
911
                        }
×
912
                        if err := HandleU2OForPod(c.ovsClient, pod, bridgeName, chassisMac, subnet.Name, true); err != nil {
×
913
                                klog.Error(err)
×
914
                                return err
×
915
                        }
×
916
                }
917
        }
918

919
        podName := pod.Name
×
920
        if pod.Annotations[fmt.Sprintf(util.VMAnnotationTemplate, util.OvnProvider)] != "" {
×
921
                podName = pod.Annotations[fmt.Sprintf(util.VMAnnotationTemplate, util.OvnProvider)]
×
922
        }
×
923

924
        // set default nic bandwidth
925
        //  ovsIngress and ovsEgress are derived from the pod's egress and ingress rate annotations respectively, their roles are reversed from the OVS interface perspective.
926
        ifaceID := ovs.PodNameToPortName(podName, pod.Namespace, util.OvnProvider)
×
927
        ovsIngress := pod.Annotations[util.EgressRateAnnotation]
×
928
        ovsEgress := pod.Annotations[util.IngressRateAnnotation]
×
929
        err = ovs.SetInterfaceBandwidth(podName, pod.Namespace, ifaceID, ovsIngress, ovsEgress)
×
930
        if err != nil {
×
931
                klog.Error(err)
×
932
                return err
×
933
        }
×
934
        err = ovs.ConfigInterfaceMirror(c.config.EnableMirror, pod.Annotations[util.MirrorControlAnnotation], ifaceID)
×
935
        if err != nil {
×
936
                klog.Error(err)
×
937
                return err
×
938
        }
×
939
        // set linux-netem qos
940
        err = ovs.SetNetemQos(podName, pod.Namespace, ifaceID, pod.Annotations[util.NetemQosLatencyAnnotation], pod.Annotations[util.NetemQosLimitAnnotation], pod.Annotations[util.NetemQosLossAnnotation], pod.Annotations[util.NetemQosJitterAnnotation])
×
941
        if err != nil {
×
942
                klog.Error(err)
×
943
                return err
×
944
        }
×
945

946
        // set multus-nic bandwidth
947
        attachNets, err := nadutils.ParsePodNetworkAnnotation(pod)
×
948
        if err != nil {
×
949
                if _, ok := err.(*nadv1.NoK8sNetworkError); ok {
×
950
                        return nil
×
951
                }
×
952
                klog.Error(err)
×
953
                return err
×
954
        }
955
        for _, multiNet := range attachNets {
×
956
                provider := fmt.Sprintf("%s.%s.%s", multiNet.Name, multiNet.Namespace, util.OvnProvider)
×
957
                if pod.Annotations[fmt.Sprintf(util.VMAnnotationTemplate, provider)] != "" {
×
958
                        podName = pod.Annotations[fmt.Sprintf(util.VMAnnotationTemplate, provider)]
×
959
                }
×
960
                if pod.Annotations[fmt.Sprintf(util.AllocatedAnnotationTemplate, provider)] == "true" {
×
961
                        ifaceID = ovs.PodNameToPortName(podName, pod.Namespace, provider)
×
962

×
963
                        err = ovs.SetInterfaceBandwidth(podName, pod.Namespace, ifaceID, pod.Annotations[fmt.Sprintf(util.EgressRateAnnotationTemplate, provider)], pod.Annotations[fmt.Sprintf(util.IngressRateAnnotationTemplate, provider)])
×
964
                        if err != nil {
×
965
                                klog.Error(err)
×
966
                                return err
×
967
                        }
×
968
                        err = ovs.ConfigInterfaceMirror(c.config.EnableMirror, pod.Annotations[fmt.Sprintf(util.MirrorControlAnnotationTemplate, provider)], ifaceID)
×
969
                        if err != nil {
×
970
                                klog.Error(err)
×
971
                                return err
×
972
                        }
×
973
                        err = ovs.SetNetemQos(podName, pod.Namespace, ifaceID, pod.Annotations[fmt.Sprintf(util.NetemQosLatencyAnnotationTemplate, provider)], pod.Annotations[fmt.Sprintf(util.NetemQosLimitAnnotationTemplate, provider)], pod.Annotations[fmt.Sprintf(util.NetemQosLossAnnotationTemplate, provider)], pod.Annotations[fmt.Sprintf(util.NetemQosJitterAnnotationTemplate, provider)])
×
974
                        if err != nil {
×
975
                                klog.Error(err)
×
976
                                return err
×
977
                        }
×
978
                }
979
        }
980

981
        return nil
×
982
}
983

984
func (c *Controller) handleDeletePod(event *podEvent) error {
×
985
        var pod *v1.Pod
×
986
        if event.oldObj != nil {
×
987
                pod = event.oldObj.(*v1.Pod)
×
988
        } else {
×
989
                return nil
×
990
        }
×
991

992
        logicalSwitch, ok := pod.Annotations[util.LogicalSwitchAnnotation]
×
993
        if !ok {
×
994
                return nil
×
995
        }
×
996

997
        subnet, err := c.subnetsLister.Get(logicalSwitch)
×
998
        if err != nil {
×
999
                klog.Error(err)
×
1000
                return err
×
1001
        }
×
1002

1003
        if !subnet.Spec.U2OInterconnection {
×
1004
                return nil
×
1005
        }
×
1006

1007
        bridgeName, chassisMac, err := c.GetProviderInfoFromSubnet(subnet)
×
1008
        if err != nil {
×
1009
                klog.Error(err)
×
1010
                return err
×
1011
        }
×
1012

1013
        if err := HandleU2OForPod(c.ovsClient, pod, bridgeName, chassisMac, subnet.Name, false); err != nil {
×
1014
                klog.Error(err)
×
1015
                return err
×
1016
        }
×
1017

1018
        return nil
×
1019
}
1020

1021
func (c *Controller) loopEncapIPCheck() {
×
1022
        node, err := c.nodesLister.Get(c.config.NodeName)
×
1023
        if err != nil {
×
1024
                klog.Errorf("failed to get node %s %v", c.config.NodeName, err)
×
1025
                return
×
1026
        }
×
1027

1028
        if nodeTunnelName := node.GetAnnotations()[util.TunnelInterfaceAnnotation]; nodeTunnelName != "" {
×
1029
                iface, err := findInterface(nodeTunnelName)
×
1030
                if err != nil {
×
1031
                        klog.Errorf("failed to find iface %s, %v", nodeTunnelName, err)
×
1032
                        return
×
1033
                }
×
1034
                if iface.Flags&net.FlagUp == 0 {
×
1035
                        klog.Errorf("iface %v is down", nodeTunnelName)
×
1036
                        return
×
1037
                }
×
1038
                addrs, err := iface.Addrs()
×
1039
                if err != nil {
×
1040
                        klog.Errorf("failed to get iface addr. %v", err)
×
1041
                        return
×
1042
                }
×
1043
                if len(addrs) == 0 {
×
1044
                        klog.Errorf("iface %s has no ip address", nodeTunnelName)
×
1045
                        return
×
1046
                }
×
1047
                if iface.Name != c.config.tunnelIface {
×
1048
                        klog.Infof("use %s as tunnel interface", iface.Name)
×
1049
                        c.config.tunnelIface = iface.Name
×
1050
                }
×
1051

1052
                // if assigned iface in node annotation is down or with no ip, the error msg should be printed periodically
1053
                if c.config.Iface == nodeTunnelName {
×
1054
                        klog.V(3).Infof("node tunnel interface %s not changed", nodeTunnelName)
×
1055
                        return
×
1056
                }
×
1057
                c.config.Iface = nodeTunnelName
×
1058
                klog.Infof("Update node tunnel interface %v", nodeTunnelName)
×
1059

×
1060
                c.config.DefaultEncapIP = strings.Split(addrs[0].String(), "/")[0]
×
1061
                if err = c.config.setEncapIPs(); err != nil {
×
1062
                        klog.Errorf("failed to set encap ip %s for iface %s", c.config.DefaultEncapIP, c.config.Iface)
×
1063
                        return
×
1064
                }
×
1065
        }
1066
}
1067

1068
func (c *Controller) ovnMetricsUpdate() {
×
1069
        c.setOvnSubnetGatewayMetric()
×
1070

×
1071
        resetSysParaMetrics()
×
1072
        c.setIPLocalPortRangeMetric()
×
1073
        c.setCheckSumErrMetric()
×
1074
        c.setDNSSearchMetric()
×
1075
        c.setTCPTwRecycleMetric()
×
1076
        c.setTCPMtuProbingMetric()
×
1077
        c.setConntrackTCPLiberalMetric()
×
1078
        c.setBridgeNfCallIptablesMetric()
×
1079
        c.setIPv6RouteMaxsizeMetric()
×
1080
        c.setTCPMemMetric()
×
1081
}
×
1082

1083
func resetSysParaMetrics() {
×
1084
        metricIPLocalPortRange.Reset()
×
1085
        metricCheckSumErr.Reset()
×
1086
        metricDNSSearch.Reset()
×
1087
        metricTCPTwRecycle.Reset()
×
1088
        metricTCPMtuProbing.Reset()
×
1089
        metricConntrackTCPLiberal.Reset()
×
1090
        metricBridgeNfCallIptables.Reset()
×
1091
        metricTCPMem.Reset()
×
1092
        metricIPv6RouteMaxsize.Reset()
×
1093
}
×
1094

1095
func rotateLog() {
×
1096
        output, err := exec.Command("logrotate", "/etc/logrotate.d/openvswitch").CombinedOutput()
×
1097
        if err != nil {
×
1098
                klog.Errorf("failed to rotate openvswitch log %q", output)
×
1099
        }
×
1100
        output, err = exec.Command("logrotate", "/etc/logrotate.d/ovn").CombinedOutput()
×
1101
        if err != nil {
×
1102
                klog.Errorf("failed to rotate ovn log %q", output)
×
1103
        }
×
1104
        output, err = exec.Command("logrotate", "/etc/logrotate.d/kubeovn").CombinedOutput()
×
1105
        if err != nil {
×
1106
                klog.Errorf("failed to rotate kube-ovn log %q", output)
×
1107
        }
×
1108
}
1109

1110
func kernelModuleLoaded(module string) (bool, error) {
×
1111
        data, err := os.ReadFile("/proc/modules")
×
1112
        if err != nil {
×
1113
                klog.Errorf("failed to read /proc/modules: %v", err)
×
1114
                return false, err
×
1115
        }
×
1116

1117
        for line := range strings.SplitSeq(string(data), "\n") {
×
1118
                if fields := strings.Fields(line); len(fields) != 0 && fields[0] == module {
×
1119
                        return true, nil
×
1120
                }
×
1121
        }
1122

1123
        return false, nil
×
1124
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc