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

kubeovn / kube-ovn / 21580078436

02 Feb 2026 06:42AM UTC coverage: 21.391% (-0.007%) from 21.398%
21580078436

push

github

web-flow
fix patch err not Get API (#6245)

Signed-off-by: clyi <clyi@alauda.io>

0 of 12 new or added lines in 1 file covered. (0.0%)

159 existing lines in 2 files now uncovered.

10637 of 49727 relevant lines covered (21.39%)

0.25 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
        "sync"
14
        "syscall"
15

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

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

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

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

51
        nmSyncer  *networkManagerSyncer
52
        ovsClient *ovsutil.Client
53

54
        flowCache      map[string]map[string][]string // key: bridgeName -> flowKey -> flow rules
55
        flowCacheMutex sync.RWMutex
56
        flowChan       chan struct{} // channel to trigger immediate flow sync
57
}
58

59
type LbServiceRules struct {
60
        IP          string
61
        Port        uint16
62
        Protocol    string
63
        BridgeName  string
64
        DstMac      string
65
        UnderlayNic string
66
        SubnetName  string
67
}
68

69
func evalCommandSymlinks(cmd string) (string, error) {
×
70
        path, err := exec.LookPath(cmd)
×
71
        if err != nil {
×
72
                return "", fmt.Errorf("failed to search for command %q: %w", cmd, err)
×
73
        }
×
74
        file, err := filepath.EvalSymlinks(path)
×
75
        if err != nil {
×
76
                return "", fmt.Errorf("failed to read evaluate symbolic links for file %q: %w", path, err)
×
UNCOV
77
        }
×
78

UNCOV
79
        return file, nil
×
80
}
81

82
func isLegacyIptablesMode() (bool, error) {
×
83
        path, err := evalCommandSymlinks("iptables")
×
84
        if err != nil {
×
85
                return false, err
×
86
        }
×
87
        pathLegacy, err := evalCommandSymlinks("iptables-legacy")
×
88
        if err != nil {
×
89
                return false, err
×
90
        }
×
UNCOV
91
        return path == pathLegacy, nil
×
92
}
93

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

105
        c.iptables = make(map[string]*iptables.IPTables)
×
106
        c.ipsets = make(map[string]*ipsets.IPSets)
×
107
        c.gwCounters = make(map[string]*util.GwIPtableCounters)
×
108
        c.k8siptables = make(map[string]k8siptables.Interface)
×
109
        c.k8sipsets = k8sipset.New(c.k8sExec)
×
110
        c.ovsClient = ovsutil.New()
×
111

×
112
        // Initialize OpenFlow flow cache (ovn-kubernetes style)
×
113
        c.flowCache = make(map[string]map[string][]string)
×
114
        c.flowChan = make(chan struct{}, 1)
×
115

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

163
        if err = ovs.ClearU2OFlows(c.ovsClient); err != nil {
×
164
                util.LogFatalAndExit(err, "failed to clear obsolete u2o flows")
×
UNCOV
165
        }
×
166

167
        c.nmSyncer = newNetworkManagerSyncer()
×
168
        c.nmSyncer.Run(c.transferAddrsAndRoutes)
×
169

×
UNCOV
170
        return nil
×
171
}
172

173
func (c *Controller) handleEnableExternalLBAddressChange(oldSubnet, newSubnet *kubeovnv1.Subnet) error {
×
174
        var subnetName string
×
175
        var action string
×
176

×
177
        switch {
×
178
        case oldSubnet != nil && newSubnet != nil:
×
179
                subnetName = oldSubnet.Name
×
180
                if oldSubnet.Spec.EnableExternalLBAddress != newSubnet.Spec.EnableExternalLBAddress {
×
181
                        klog.Infof("EnableExternalLBAddress changed for subnet %s", newSubnet.Name)
×
182
                        if newSubnet.Spec.EnableExternalLBAddress {
×
183
                                action = "add"
×
184
                        } else {
×
185
                                action = "remove"
×
UNCOV
186
                        }
×
187
                }
188
        case oldSubnet != nil:
×
189
                subnetName = oldSubnet.Name
×
190
                if oldSubnet.Spec.EnableExternalLBAddress {
×
191
                        klog.Infof("EnableExternalLBAddress removed for subnet %s", oldSubnet.Name)
×
192
                        action = "remove"
×
193
                }
×
194
        case newSubnet != nil:
×
195
                subnetName = newSubnet.Name
×
196
                if newSubnet.Spec.EnableExternalLBAddress {
×
197
                        klog.Infof("EnableExternalLBAddress added for subnet %s", newSubnet.Name)
×
198
                        action = "add"
×
UNCOV
199
                }
×
200
        }
201

202
        if action != "" {
×
203
                services, err := c.servicesLister.List(labels.Everything())
×
204
                if err != nil {
×
205
                        klog.Errorf("failed to list services: %v", err)
×
206
                        return err
×
UNCOV
207
                }
×
208

209
                for _, svc := range services {
×
210
                        if svc.Annotations[util.ServiceExternalIPFromSubnetAnnotation] == subnetName {
×
211
                                klog.Infof("Service %s/%s has external LB address pool annotation from subnet %s, action: %s", svc.Namespace, svc.Name, subnetName, action)
×
212
                                switch action {
×
213
                                case "add":
×
214
                                        c.serviceQueue.Add(&serviceEvent{newObj: svc})
×
215
                                case "remove":
×
UNCOV
216
                                        c.serviceQueue.Add(&serviceEvent{oldObj: svc})
×
217
                                }
218
                        }
219
                }
220
        }
UNCOV
221
        return nil
×
222
}
223

224
// handleU2OInterconnectionMACChange handles U2O interconnection MAC address changes.
225
// When U2O (Underlay to Overlay) interconnection is enabled, the svc local flow's destination
226
// MAC must point to the LRP (Logical Router Port) MAC. Otherwise, without U2O enabled (no LRP exists),
227
// the flow would hit the rules created by build_lswitch_dnat_mod_dl_dst_rules instead.
228
func (c *Controller) handleU2OInterconnectionMACChange(oldSubnet, newSubnet *kubeovnv1.Subnet) error {
×
229
        if oldSubnet == nil || newSubnet == nil {
×
230
                return nil
×
UNCOV
231
        }
×
232

233
        oldMAC := oldSubnet.Status.U2OInterconnectionMAC
×
234
        newMAC := newSubnet.Status.U2OInterconnectionMAC
×
235

×
236
        if oldMAC == newMAC {
×
237
                return nil
×
UNCOV
238
        }
×
239

240
        if newMAC == "" && oldMAC == "" {
×
241
                return nil
×
UNCOV
242
        }
×
243

244
        klog.Infof("U2OInterconnectionMAC changed for subnet %s: %s -> %s",
×
245
                oldSubnet.Name, oldMAC, newMAC)
×
246

×
247
        // Find all services using this subnet and re-sync them
×
248
        services, err := c.servicesLister.List(labels.Everything())
×
249
        if err != nil {
×
250
                klog.Errorf("failed to list services: %v", err)
×
251
                return err
×
UNCOV
252
        }
×
253

254
        for _, svc := range services {
×
255
                if svc.Annotations[util.ServiceExternalIPFromSubnetAnnotation] == oldSubnet.Name {
×
256
                        klog.Infof("Re-syncing service %s/%s due to U2OInterconnectionMAC change in subnet %s",
×
257
                                svc.Namespace, svc.Name, oldSubnet.Name)
×
258
                        c.serviceQueue.Add(&serviceEvent{newObj: svc})
×
UNCOV
259
                }
×
260
        }
UNCOV
261
        return nil
×
262
}
263

264
func (c *Controller) reconcileRouters(event *subnetEvent) error {
×
265
        subnets, err := c.subnetsLister.List(labels.Everything())
×
266
        if err != nil {
×
267
                klog.Errorf("failed to list subnets %v", err)
×
268
                return err
×
UNCOV
269
        }
×
270

271
        if event != nil {
×
272
                var ok bool
×
273
                var oldSubnet, newSubnet *kubeovnv1.Subnet
×
274
                if event.oldObj != nil {
×
275
                        if oldSubnet, ok = event.oldObj.(*kubeovnv1.Subnet); !ok {
×
276
                                klog.Errorf("expected old subnet in subnetEvent but got %#v", event.oldObj)
×
277
                                return nil
×
UNCOV
278
                        }
×
279
                }
280
                if event.newObj != nil {
×
281
                        if newSubnet, ok = event.newObj.(*kubeovnv1.Subnet); !ok {
×
282
                                klog.Errorf("expected new subnet in subnetEvent but got %#v", event.newObj)
×
283
                                return nil
×
UNCOV
284
                        }
×
285
                }
286

287
                if err = c.handleEnableExternalLBAddressChange(oldSubnet, newSubnet); err != nil {
×
288
                        klog.Errorf("failed to handle enable external lb address change: %v", err)
×
289
                        return err
×
UNCOV
290
                }
×
291

292
                if err = c.handleU2OInterconnectionMACChange(oldSubnet, newSubnet); err != nil {
×
293
                        klog.Errorf("failed to handle u2o interconnection mac change: %v", err)
×
294
                        return err
×
UNCOV
295
                }
×
296
                // handle policy routing
297
                rulesToAdd, rulesToDel, routesToAdd, routesToDel, err := c.diffPolicyRouting(oldSubnet, newSubnet)
×
298
                if err != nil {
×
299
                        klog.Errorf("failed to get policy routing difference: %v", err)
×
300
                        return err
×
UNCOV
301
                }
×
302
                // add new routes first
303
                for _, r := range routesToAdd {
×
304
                        if err = netlink.RouteReplace(&r); err != nil && !errors.Is(err, syscall.EEXIST) {
×
305
                                klog.Errorf("failed to replace route for subnet %s: %v", newSubnet.Name, err)
×
306
                                return err
×
UNCOV
307
                        }
×
308
                }
309
                // next, add new rules
310
                for _, r := range rulesToAdd {
×
311
                        if err = netlink.RuleAdd(&r); err != nil && !errors.Is(err, syscall.EEXIST) {
×
312
                                klog.Errorf("failed to add network rule for subnet %s: %v", newSubnet.Name, err)
×
313
                                return err
×
UNCOV
314
                        }
×
315
                }
316
                // then delete old network rules
317
                for _, r := range rulesToDel {
×
318
                        // loop to delete all matched rules
×
319
                        for {
×
320
                                if err = netlink.RuleDel(&r); err != nil {
×
321
                                        if !errors.Is(err, syscall.ENOENT) {
×
322
                                                klog.Errorf("failed to delete network rule for subnet %s: %v", oldSubnet.Name, err)
×
323
                                                return err
×
324
                                        }
×
UNCOV
325
                                        break
×
326
                                }
327
                        }
328
                }
329
                // last, delete old network routes
330
                for _, r := range routesToDel {
×
331
                        if err = netlink.RouteDel(&r); err != nil && !errors.Is(err, syscall.ENOENT) {
×
332
                                klog.Errorf("failed to delete route for subnet %s: %v", oldSubnet.Name, err)
×
333
                                return err
×
UNCOV
334
                        }
×
335
                }
336
        }
337

338
        node, err := c.nodesLister.Get(c.config.NodeName)
×
339
        if err != nil {
×
340
                klog.Errorf("failed to get node %s %v", c.config.NodeName, err)
×
341
                return err
×
342
        }
×
343
        nodeIPv4, nodeIPv6 := util.GetNodeInternalIP(*node)
×
344
        var joinIPv4, joinIPv6 string
×
345
        if len(node.Annotations) != 0 {
×
346
                joinIPv4, joinIPv6 = util.SplitStringIP(node.Annotations[util.IPAddressAnnotation])
×
UNCOV
347
        }
×
348

349
        joinCIDR := make([]string, 0, 2)
×
350
        cidrs := make([]string, 0, len(subnets)*2)
×
351
        for _, subnet := range subnets {
×
352
                // The route for overlay subnet cidr via ovn0 should not be deleted even though subnet.Status has changed to not ready
×
353
                if subnet.Spec.Vpc != c.config.ClusterRouter ||
×
354
                        (subnet.Spec.Vlan != "" && !subnet.Spec.LogicalGateway && (!subnet.Spec.U2OInterconnection || (subnet.Spec.EnableLb != nil && *subnet.Spec.EnableLb))) ||
×
355
                        !subnet.Status.IsValidated() {
×
UNCOV
356
                        continue
×
357
                }
358

359
                for cidrBlock := range strings.SplitSeq(subnet.Spec.CIDRBlock, ",") {
×
360
                        if _, ipNet, err := net.ParseCIDR(cidrBlock); err != nil {
×
361
                                klog.Errorf("%s is not a valid cidr block", cidrBlock)
×
362
                        } else {
×
363
                                if nodeIPv4 != "" && util.CIDRContainIP(cidrBlock, nodeIPv4) {
×
UNCOV
364
                                        continue
×
365
                                }
366
                                if nodeIPv6 != "" && util.CIDRContainIP(cidrBlock, nodeIPv6) {
×
UNCOV
367
                                        continue
×
368
                                }
369
                                cidrs = append(cidrs, ipNet.String())
×
370
                                if subnet.Name == c.config.NodeSwitch {
×
371
                                        joinCIDR = append(joinCIDR, ipNet.String())
×
UNCOV
372
                                }
×
373
                        }
374
                }
375
        }
376

377
        gateway, ok := node.Annotations[util.GatewayAnnotation]
×
378
        if !ok {
×
379
                klog.Errorf("annotation for node %s ovn.kubernetes.io/gateway not exists", node.Name)
×
380
                return errors.New("annotation for node ovn.kubernetes.io/gateway not exists")
×
381
        }
×
382
        nic, err := netlink.LinkByName(util.NodeNic)
×
383
        if err != nil {
×
384
                klog.Errorf("failed to get nic %s", util.NodeNic)
×
385
                return fmt.Errorf("failed to get nic %s", util.NodeNic)
×
UNCOV
386
        }
×
387

388
        allRoutes, err := getNicExistRoutes(nil, gateway)
×
389
        if err != nil {
×
390
                klog.Error(err)
×
391
                return err
×
392
        }
×
393
        nodeNicRoutes, err := getNicExistRoutes(nic, gateway)
×
394
        if err != nil {
×
395
                klog.Error(err)
×
396
                return err
×
397
        }
×
398
        toAdd, toDel := routeDiff(nodeNicRoutes, allRoutes, cidrs, joinCIDR, joinIPv4, joinIPv6, gateway, net.ParseIP(nodeIPv4), net.ParseIP(nodeIPv6))
×
399
        for _, r := range toDel {
×
400
                if err = netlink.RouteDel(&netlink.Route{Dst: r.Dst}); err != nil {
×
401
                        klog.Errorf("failed to del route %v", err)
×
UNCOV
402
                }
×
403
        }
404

405
        for _, r := range toAdd {
×
406
                r.LinkIndex = nic.Attrs().Index
×
407
                if err = netlink.RouteReplace(&r); err != nil {
×
408
                        klog.Errorf("failed to replace route %v: %v", r, err)
×
UNCOV
409
                }
×
410
        }
411

UNCOV
412
        return nil
×
413
}
414

415
func genLBServiceRules(service *v1.Service, bridgeName, underlayNic, dstMac, subnetName string) []LbServiceRules {
×
416
        var lbServiceRules []LbServiceRules
×
417
        for _, ingress := range service.Status.LoadBalancer.Ingress {
×
418
                for _, port := range service.Spec.Ports {
×
419
                        lbServiceRules = append(lbServiceRules, LbServiceRules{
×
420
                                IP:          ingress.IP,
×
421
                                Port:        uint16(port.Port), // #nosec G115
×
422
                                Protocol:    string(port.Protocol),
×
423
                                DstMac:      dstMac,
×
424
                                UnderlayNic: underlayNic,
×
425
                                BridgeName:  bridgeName,
×
426
                                SubnetName:  subnetName,
×
UNCOV
427
                        })
×
428
                }
×
429
        }
UNCOV
430
        return lbServiceRules
×
431
}
432

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

×
436
        if oldService != nil && oldService.Annotations[util.ServiceExternalIPFromSubnetAnnotation] != "" {
×
437
                oldSubnetName := oldService.Annotations[util.ServiceExternalIPFromSubnetAnnotation]
×
438
                oldBridgeName, underlayNic, dstMac, err := c.getExtInfoBySubnet(oldSubnetName)
×
439
                if err != nil {
×
UNCOV
440
                        klog.Errorf("failed to get provider network by subnet %s: %v", oldSubnetName, err)
×
441
                        return nil, nil, err
×
UNCOV
442
                }
×
443

444
                oldlbServiceRules = genLBServiceRules(oldService, oldBridgeName, underlayNic, dstMac, oldSubnetName)
×
445
        }
446

447
        if isSubnetExternalLBEnabled && newService != nil && newService.Annotations[util.ServiceExternalIPFromSubnetAnnotation] != "" {
×
448
                newSubnetName := newService.Annotations[util.ServiceExternalIPFromSubnetAnnotation]
×
449
                newBridgeName, underlayNic, dstMac, err := c.getExtInfoBySubnet(newSubnetName)
×
450
                if err != nil {
×
UNCOV
451
                        klog.Errorf("failed to get provider network by subnet %s: %v", newSubnetName, err)
×
UNCOV
452
                        return nil, nil, err
×
453
                }
×
454
                newlbServiceRules = genLBServiceRules(newService, newBridgeName, underlayNic, dstMac, newSubnetName)
×
455
        }
456

457
        for _, oldRule := range oldlbServiceRules {
×
UNCOV
458
                found := slices.Contains(newlbServiceRules, oldRule)
×
UNCOV
459
                if !found {
×
460
                        lbServiceRulesToDel = append(lbServiceRulesToDel, oldRule)
×
461
                }
×
462
        }
463

464
        for _, newRule := range newlbServiceRules {
×
UNCOV
465
                found := slices.Contains(oldlbServiceRules, newRule)
×
UNCOV
466
                if !found {
×
467
                        lbServiceRulesToAdd = append(lbServiceRulesToAdd, newRule)
×
UNCOV
468
                }
×
469
        }
470

471
        return lbServiceRulesToAdd, lbServiceRulesToDel, nil
×
472
}
473

474
func (c *Controller) getExtInfoBySubnet(subnetName string) (string, string, string, error) {
×
475
        subnet, err := c.subnetsLister.Get(subnetName)
×
UNCOV
476
        if err != nil {
×
477
                klog.Errorf("failed to get subnet %s: %v", subnetName, err)
×
478
                return "", "", "", err
×
479
        }
×
480

481
        dstMac := subnet.Status.U2OInterconnectionMAC
×
482
        if dstMac == "" {
×
483
                dstMac = util.MasqueradeExternalLBAccessMac
×
UNCOV
484
                klog.Infof("Subnet %s has no U2OInterconnectionMAC, using default MAC %s", subnetName, dstMac)
×
485
        } else {
×
486
                klog.Infof("Using U2OInterconnectionMAC %s for subnet %s", dstMac, subnetName)
×
487
        }
×
488

UNCOV
489
        vlanName := subnet.Spec.Vlan
×
490
        if vlanName == "" {
×
491
                return "", "", "", errors.New("vlan not specified in subnet")
×
492
        }
×
493

494
        vlan, err := c.vlansLister.Get(vlanName)
×
UNCOV
495
        if err != nil {
×
496
                klog.Errorf("failed to get vlan %s: %v", vlanName, err)
×
497
                return "", "", "", err
×
498
        }
×
499

UNCOV
500
        providerNetworkName := vlan.Spec.Provider
×
501
        if providerNetworkName == "" {
×
502
                return "", "", "", errors.New("provider network not specified in vlan")
×
503
        }
×
504

505
        pn, err := c.providerNetworksLister.Get(providerNetworkName)
×
UNCOV
506
        if err != nil {
×
507
                klog.Errorf("failed to get provider network %s: %v", providerNetworkName, err)
×
508
                return "", "", "", err
×
509
        }
×
510

511
        underlayNic := pn.Spec.DefaultInterface
×
UNCOV
512
        for _, item := range pn.Spec.CustomInterfaces {
×
UNCOV
513
                if slices.Contains(item.Nodes, c.config.NodeName) {
×
514
                        underlayNic = item.Interface
×
515
                        break
×
516
                }
517
        }
UNCOV
518
        bridgeName := util.ExternalBridgeName(providerNetworkName)
×
519
        klog.Infof("Provider network: %s, Underlay NIC: %s, DstMac: %s", providerNetworkName, underlayNic, dstMac)
×
520
        return bridgeName, underlayNic, dstMac, nil
×
521
}
522

523
func (c *Controller) reconcileServices(event *serviceEvent) error {
×
524
        if event == nil {
×
525
                return nil
×
526
        }
×
527
        var ok bool
×
528
        var oldService, newService *v1.Service
×
529
        if event.oldObj != nil {
×
UNCOV
530
                if oldService, ok = event.oldObj.(*v1.Service); !ok {
×
UNCOV
531
                        klog.Errorf("expected old service in serviceEvent but got %#v", event.oldObj)
×
532
                        return nil
×
533
                }
×
534
        }
535

536
        if event.newObj != nil {
×
UNCOV
537
                if newService, ok = event.newObj.(*v1.Service); !ok {
×
UNCOV
538
                        klog.Errorf("expected new service in serviceEvent but got %#v", event.newObj)
×
UNCOV
539
                        return nil
×
540
                }
×
541
        }
542

543
        // check is the lb service IP related subnet's EnableExternalLBAddress
544
        isSubnetExternalLBEnabled := false
×
545
        if newService != nil && newService.Annotations[util.ServiceExternalIPFromSubnetAnnotation] != "" {
×
546
                subnet, err := c.subnetsLister.Get(newService.Annotations[util.ServiceExternalIPFromSubnetAnnotation])
×
547
                if err != nil {
×
UNCOV
548
                        klog.Errorf("failed to get subnet %s: %v", newService.Annotations[util.ServiceExternalIPFromSubnetAnnotation], err)
×
UNCOV
549
                        return err
×
550
                }
×
551
                isSubnetExternalLBEnabled = subnet.Spec.EnableExternalLBAddress
×
552
        }
553

554
        lbServiceRulesToAdd, lbServiceRulesToDel, err := c.diffExternalLBServiceRules(oldService, newService, isSubnetExternalLBEnabled)
×
UNCOV
555
        if err != nil {
×
556
                klog.Errorf("failed to get ip port difference: %v", err)
×
557
                return err
×
558
        }
×
559

560
        if len(lbServiceRulesToAdd) > 0 {
×
561
                for _, rule := range lbServiceRulesToAdd {
×
562
                        klog.Infof("Adding LB service rule: %+v", rule)
×
UNCOV
563
                        if err := c.AddOrUpdateUnderlaySubnetSvcLocalFlowCache(rule.IP, rule.Port, rule.Protocol, rule.DstMac, rule.UnderlayNic, rule.BridgeName, rule.SubnetName); err != nil {
×
UNCOV
564
                                klog.Errorf("failed to update underlay subnet svc local openflow cache: %v", err)
×
UNCOV
565
                                return err
×
566
                        }
×
567
                }
568
        }
569

570
        if len(lbServiceRulesToDel) > 0 {
×
UNCOV
571
                for _, rule := range lbServiceRulesToDel {
×
UNCOV
572
                        klog.Infof("Delete LB service rule: %+v", rule)
×
573
                        c.deleteUnderlaySubnetSvcLocalFlowCache(rule.BridgeName, rule.IP, rule.Port, rule.Protocol)
×
UNCOV
574
                }
×
575
        }
576

577
        return nil
×
578
}
579

580
func getNicExistRoutes(nic netlink.Link, gateway string) ([]netlink.Route, error) {
×
581
        var routes, existRoutes []netlink.Route
×
582
        var err error
×
583
        for gw := range strings.SplitSeq(gateway, ",") {
×
584
                if util.CheckProtocol(gw) == kubeovnv1.ProtocolIPv4 {
×
585
                        routes, err = netlink.RouteList(nic, netlink.FAMILY_V4)
×
586
                } else {
×
587
                        routes, err = netlink.RouteList(nic, netlink.FAMILY_V6)
×
588
                }
×
UNCOV
589
                if err != nil {
×
590
                        return nil, err
×
UNCOV
591
                }
×
UNCOV
592
                existRoutes = append(existRoutes, routes...)
×
593
        }
594
        return existRoutes, nil
×
595
}
596

597
func routeDiff(nodeNicRoutes, allRoutes []netlink.Route, cidrs, joinCIDR []string, joinIPv4, joinIPv6, gateway string, srcIPv4, srcIPv6 net.IP) (toAdd, toDel []netlink.Route) {
×
598
        // joinIPv6 is not used for now
×
599
        _ = joinIPv6
×
UNCOV
600

×
UNCOV
601
        for _, route := range nodeNicRoutes {
×
602
                if route.Scope == netlink.SCOPE_LINK || route.Dst == nil || route.Dst.IP.IsLinkLocalUnicast() {
×
603
                        continue
×
604
                }
605

606
                found := slices.Contains(cidrs, route.Dst.String())
×
607
                if !found {
×
608
                        toDel = append(toDel, route)
×
609
                }
×
610
                conflict := false
×
611
                for _, ar := range allRoutes {
×
UNCOV
612
                        if ar.Dst != nil && ar.Dst.String() == route.Dst.String() && ar.LinkIndex != route.LinkIndex {
×
UNCOV
613
                                // route conflict
×
614
                                conflict = true
×
615
                                break
×
616
                        }
617
                }
618
                if conflict {
×
619
                        toDel = append(toDel, route)
×
620
                }
×
621
        }
622
        if len(toDel) > 0 {
×
623
                klog.Infof("routes to delete: %v", toDel)
×
624
        }
×
625

626
        ipv4, ipv6 := util.SplitStringIP(gateway)
×
627
        gwV4, gwV6 := net.ParseIP(ipv4), net.ParseIP(ipv6)
×
628
        for _, c := range cidrs {
×
629
                var src, gw net.IP
×
630
                switch util.CheckProtocol(c) {
×
UNCOV
631
                case kubeovnv1.ProtocolIPv4:
×
UNCOV
632
                        src, gw = srcIPv4, gwV4
×
633
                case kubeovnv1.ProtocolIPv6:
×
634
                        src, gw = srcIPv6, gwV6
×
635
                }
636

637
                found := false
×
638
                for _, ar := range allRoutes {
×
639
                        if ar.Dst != nil && ar.Dst.String() == c {
×
640
                                if slices.Contains(joinCIDR, c) {
×
641
                                        // Only compare Dst for join subnets
×
642
                                        found = true
×
643
                                        klog.V(3).Infof("[routeDiff] joinCIDR route already exists in allRoutes: %v", ar)
×
644
                                        break
×
645
                                } else if (ar.Src == nil && src == nil) || (ar.Src != nil && src != nil && ar.Src.Equal(src)) {
×
UNCOV
646
                                        // For non-join subnets, both Dst and Src must be the same
×
UNCOV
647
                                        found = true
×
UNCOV
648
                                        klog.V(3).Infof("[routeDiff] route already exists in allRoutes: %v", ar)
×
649
                                        break
×
650
                                }
651
                        }
652
                }
653
                if found {
×
654
                        continue
×
655
                }
656
                for _, r := range nodeNicRoutes {
×
657
                        if r.Dst == nil || r.Dst.String() != c {
×
658
                                continue
×
659
                        }
UNCOV
660
                        if (src == nil && r.Src == nil) || (src != nil && r.Src != nil && src.Equal(r.Src)) {
×
661
                                found = true
×
662
                                break
×
663
                        }
664
                }
665
                if !found {
×
666
                        var priority int
×
667
                        scope := netlink.SCOPE_UNIVERSE
×
668
                        proto := netlink.RouteProtocol(syscall.RTPROT_STATIC)
×
669
                        if slices.Contains(joinCIDR, c) {
×
670
                                if util.CheckProtocol(c) == kubeovnv1.ProtocolIPv4 {
×
671
                                        src = net.ParseIP(joinIPv4)
×
672
                                } else {
×
UNCOV
673
                                        src, priority = nil, 256
×
674
                                }
×
675
                                gw, scope = nil, netlink.SCOPE_LINK
×
676
                                proto = netlink.RouteProtocol(unix.RTPROT_KERNEL)
×
677
                        }
678
                        _, cidr, _ := net.ParseCIDR(c)
×
679
                        toAdd = append(toAdd, netlink.Route{
×
680
                                Dst:      cidr,
×
681
                                Src:      src,
×
682
                                Gw:       gw,
×
UNCOV
683
                                Protocol: proto,
×
UNCOV
684
                                Scope:    scope,
×
685
                                Priority: priority,
×
686
                        })
×
687
                }
688
        }
UNCOV
689
        if len(toAdd) > 0 {
×
UNCOV
690
                klog.Infof("routes to add: %v", toAdd)
×
691
        }
×
692
        return
×
693
}
694

695
func getRulesToAdd(oldRules, newRules []netlink.Rule) []netlink.Rule {
×
696
        var toAdd []netlink.Rule
×
697

×
698
        for _, rule := range newRules {
×
699
                var found bool
×
UNCOV
700
                for _, r := range oldRules {
×
UNCOV
701
                        if r.Family == rule.Family && r.Priority == rule.Priority && r.Table == rule.Table && reflect.DeepEqual(r.Src, rule.Src) {
×
702
                                found = true
×
703
                                break
×
704
                        }
705
                }
UNCOV
706
                if !found {
×
707
                        toAdd = append(toAdd, rule)
×
UNCOV
708
                }
×
709
        }
710

711
        return toAdd
×
712
}
713

714
func getRoutesToAdd(oldRoutes, newRoutes []netlink.Route) []netlink.Route {
×
715
        var toAdd []netlink.Route
×
716

×
717
        for _, route := range newRoutes {
×
718
                var found bool
×
UNCOV
719
                for _, r := range oldRoutes {
×
UNCOV
720
                        if r.Equal(route) {
×
721
                                found = true
×
722
                                break
×
723
                        }
724
                }
UNCOV
725
                if !found {
×
726
                        toAdd = append(toAdd, route)
×
UNCOV
727
                }
×
728
        }
729

730
        return toAdd
×
731
}
732

733
func (c *Controller) diffPolicyRouting(oldSubnet, newSubnet *kubeovnv1.Subnet) (rulesToAdd, rulesToDel []netlink.Rule, routesToAdd, routesToDel []netlink.Route, err error) {
×
734
        oldRules, oldRoutes, err := c.getPolicyRouting(oldSubnet)
×
735
        if err != nil {
×
736
                klog.Error(err)
×
737
                return
×
738
        }
×
739
        newRules, newRoutes, err := c.getPolicyRouting(newSubnet)
×
UNCOV
740
        if err != nil {
×
741
                klog.Error(err)
×
742
                return
×
743
        }
×
744

745
        rulesToAdd = getRulesToAdd(oldRules, newRules)
×
746
        rulesToDel = getRulesToAdd(newRules, oldRules)
×
UNCOV
747
        routesToAdd = getRoutesToAdd(oldRoutes, newRoutes)
×
UNCOV
748
        routesToDel = getRoutesToAdd(newRoutes, oldRoutes)
×
749

×
750
        return
×
751
}
752

753
func (c *Controller) getPolicyRouting(subnet *kubeovnv1.Subnet) ([]netlink.Rule, []netlink.Route, error) {
×
754
        if subnet == nil || subnet.Spec.ExternalEgressGateway == "" || subnet.Spec.Vpc != c.config.ClusterRouter {
×
755
                return nil, nil, nil
×
UNCOV
756
        }
×
757
        if subnet.Spec.GatewayType == kubeovnv1.GWCentralizedType && !util.GatewayContains(subnet.Spec.GatewayNode, c.config.NodeName) {
×
758
                return nil, nil, nil
×
759
        }
×
760

761
        protocols := make([]string, 1, 2)
×
762
        if protocol := util.CheckProtocol(subnet.Spec.ExternalEgressGateway); protocol == kubeovnv1.ProtocolDual {
×
763
                protocols[0] = kubeovnv1.ProtocolIPv4
×
UNCOV
764
                protocols = append(protocols, kubeovnv1.ProtocolIPv6)
×
765
        } else {
×
766
                protocols[0] = protocol
×
767
        }
×
768

769
        cidr := strings.Split(subnet.Spec.CIDRBlock, ",")
×
770
        egw := strings.Split(subnet.Spec.ExternalEgressGateway, ",")
×
771

×
772
        // rules
×
773
        var rules []netlink.Rule
×
774
        rule := netlink.NewRule()
×
775
        rule.Table = int(subnet.Spec.PolicyRoutingTableID)
×
776
        rule.Priority = int(subnet.Spec.PolicyRoutingPriority)
×
777
        if subnet.Spec.GatewayType == kubeovnv1.GWDistributedType {
×
778
                pods, err := c.podsLister.List(labels.Everything())
×
UNCOV
779
                if err != nil {
×
780
                        klog.Errorf("list pods failed, %+v", err)
×
781
                        return nil, nil, err
×
782
                }
×
783

784
                hostname := os.Getenv(util.HostnameEnv)
×
785
                for _, pod := range pods {
×
786
                        if pod.Spec.HostNetwork ||
×
UNCOV
787
                                pod.Status.PodIP == "" ||
×
UNCOV
788
                                pod.Annotations[util.LogicalSwitchAnnotation] != subnet.Name ||
×
789
                                pod.Spec.NodeName != hostname {
×
790
                                continue
×
791
                        }
792

793
                        for i := range protocols {
×
794
                                rule.Family, _ = util.ProtocolToFamily(protocols[i])
×
795

×
796
                                var ip net.IP
×
797
                                var maskBits int
×
798
                                if len(pod.Status.PodIPs) == 2 && protocols[i] == kubeovnv1.ProtocolIPv6 {
×
799
                                        ip = net.ParseIP(pod.Status.PodIPs[1].IP)
×
800
                                        maskBits = 128
×
801
                                } else if util.CheckProtocol(pod.Status.PodIP) == protocols[i] {
×
802
                                        ip = net.ParseIP(pod.Status.PodIP)
×
UNCOV
803
                                        maskBits = 32
×
UNCOV
804
                                        if rule.Family == netlink.FAMILY_V6 {
×
805
                                                maskBits = 128
×
806
                                        }
×
807
                                }
808

809
                                rule.Src = &net.IPNet{IP: ip, Mask: net.CIDRMask(maskBits, maskBits)}
×
810
                                rules = append(rules, *rule)
×
811
                        }
812
                }
813
        } else {
×
814
                for i := range protocols {
×
815
                        rule.Family, _ = util.ProtocolToFamily(protocols[i])
×
UNCOV
816
                        if len(cidr) == len(protocols) {
×
UNCOV
817
                                _, rule.Src, _ = net.ParseCIDR(cidr[i])
×
UNCOV
818
                        }
×
UNCOV
819
                        rules = append(rules, *rule)
×
820
                }
821
        }
822

823
        // routes
824
        var routes []netlink.Route
×
825
        for i := range protocols {
×
826
                routes = append(routes, netlink.Route{
×
827
                        Protocol: netlink.RouteProtocol(syscall.RTPROT_STATIC),
×
UNCOV
828
                        Table:    int(subnet.Spec.PolicyRoutingTableID),
×
829
                        Gw:       net.ParseIP(egw[i]),
×
UNCOV
830
                })
×
UNCOV
831
        }
×
832

833
        return rules, routes, nil
×
834
}
835

836
func (c *Controller) handleUpdatePod(key string) error {
×
837
        namespace, name, err := cache.SplitMetaNamespaceKey(key)
×
838
        if err != nil {
×
839
                utilruntime.HandleError(fmt.Errorf("invalid resource key: %s", key))
×
840
                return nil
×
841
        }
×
842
        klog.Infof("handle qos update for pod %s/%s", namespace, name)
×
843

×
844
        pod, err := c.podsLister.Pods(namespace).Get(name)
×
845
        if err != nil {
×
846
                if k8serrors.IsNotFound(err) {
×
UNCOV
847
                        return nil
×
UNCOV
848
                }
×
849
                klog.Error(err)
×
850
                return err
×
851
        }
852

853
        if err := util.ValidatePodNetwork(pod.Annotations); err != nil {
×
UNCOV
854
                klog.Errorf("validate pod %s/%s failed, %v", namespace, name, err)
×
855
                c.recorder.Eventf(pod, v1.EventTypeWarning, "ValidatePodNetworkFailed", err.Error())
×
856
                return err
×
857
        }
×
858

UNCOV
859
        podName := pod.Name
×
UNCOV
860
        if pod.Annotations[fmt.Sprintf(util.VMAnnotationTemplate, util.OvnProvider)] != "" {
×
UNCOV
861
                podName = pod.Annotations[fmt.Sprintf(util.VMAnnotationTemplate, util.OvnProvider)]
×
862
        }
×
863

864
        // set default nic bandwidth
865
        //  ovsIngress and ovsEgress are derived from the pod's egress and ingress rate annotations respectively, their roles are reversed from the OVS interface perspective.
866
        ifaceID := ovs.PodNameToPortName(podName, pod.Namespace, util.OvnProvider)
×
867
        ovsIngress := pod.Annotations[util.EgressRateAnnotation]
×
868
        ovsEgress := pod.Annotations[util.IngressRateAnnotation]
×
869
        err = ovs.SetInterfaceBandwidth(podName, pod.Namespace, ifaceID, ovsIngress, ovsEgress)
×
870
        if err != nil {
×
871
                klog.Error(err)
×
872
                return err
×
873
        }
×
874
        err = ovs.ConfigInterfaceMirror(c.config.EnableMirror, pod.Annotations[util.MirrorControlAnnotation], ifaceID)
×
UNCOV
875
        if err != nil {
×
876
                klog.Error(err)
×
877
                return err
×
878
        }
×
879
        // set linux-netem qos
880
        err = ovs.SetNetemQos(podName, pod.Namespace, ifaceID, pod.Annotations[util.NetemQosLatencyAnnotation], pod.Annotations[util.NetemQosLimitAnnotation], pod.Annotations[util.NetemQosLossAnnotation], pod.Annotations[util.NetemQosJitterAnnotation])
×
UNCOV
881
        if err != nil {
×
UNCOV
882
                klog.Error(err)
×
883
                return err
×
884
        }
×
885

886
        // set multus-nic bandwidth
887
        attachNets, err := nadutils.ParsePodNetworkAnnotation(pod)
×
888
        if err != nil {
×
889
                if _, ok := err.(*nadv1.NoK8sNetworkError); ok {
×
UNCOV
890
                        return nil
×
891
                }
×
892
                klog.Error(err)
×
893
                return err
×
894
        }
895
        for _, multiNet := range attachNets {
×
896
                provider := fmt.Sprintf("%s.%s.%s", multiNet.Name, multiNet.Namespace, util.OvnProvider)
×
897
                if pod.Annotations[fmt.Sprintf(util.VMAnnotationTemplate, provider)] != "" {
×
898
                        podName = pod.Annotations[fmt.Sprintf(util.VMAnnotationTemplate, provider)]
×
899
                }
×
900
                if pod.Annotations[fmt.Sprintf(util.AllocatedAnnotationTemplate, provider)] == "true" {
×
901
                        ifaceID = ovs.PodNameToPortName(podName, pod.Namespace, provider)
×
902

×
903
                        err = ovs.SetInterfaceBandwidth(podName, pod.Namespace, ifaceID, pod.Annotations[fmt.Sprintf(util.EgressRateAnnotationTemplate, provider)], pod.Annotations[fmt.Sprintf(util.IngressRateAnnotationTemplate, provider)])
×
904
                        if err != nil {
×
905
                                klog.Error(err)
×
906
                                return err
×
907
                        }
×
908
                        err = ovs.ConfigInterfaceMirror(c.config.EnableMirror, pod.Annotations[fmt.Sprintf(util.MirrorControlAnnotationTemplate, provider)], ifaceID)
×
909
                        if err != nil {
×
910
                                klog.Error(err)
×
911
                                return err
×
912
                        }
×
913
                        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)])
×
UNCOV
914
                        if err != nil {
×
UNCOV
915
                                klog.Error(err)
×
UNCOV
916
                                return err
×
917
                        }
×
918
                }
919
        }
920

921
        return nil
×
922
}
923

924
func (c *Controller) loopEncapIPCheck() {
×
925
        node, err := c.nodesLister.Get(c.config.NodeName)
×
UNCOV
926
        if err != nil {
×
927
                klog.Errorf("failed to get node %s %v", c.config.NodeName, err)
×
928
                return
×
929
        }
×
930

931
        if nodeTunnelName := node.GetAnnotations()[util.TunnelInterfaceAnnotation]; nodeTunnelName != "" {
×
932
                iface, err := findInterface(nodeTunnelName)
×
933
                if err != nil {
×
934
                        klog.Errorf("failed to find iface %s, %v", nodeTunnelName, err)
×
935
                        return
×
936
                }
×
937
                if iface.Flags&net.FlagUp == 0 {
×
938
                        klog.Errorf("iface %v is down", nodeTunnelName)
×
939
                        return
×
940
                }
×
941
                addrs, err := iface.Addrs()
×
942
                if err != nil {
×
943
                        klog.Errorf("failed to get iface addr. %v", err)
×
944
                        return
×
945
                }
×
946
                if len(addrs) == 0 {
×
947
                        klog.Errorf("iface %s has no ip address", nodeTunnelName)
×
948
                        return
×
949
                }
×
UNCOV
950
                if iface.Name != c.config.tunnelIface {
×
UNCOV
951
                        klog.Infof("use %s as tunnel interface", iface.Name)
×
952
                        c.config.tunnelIface = iface.Name
×
953
                }
×
954

955
                // if assigned iface in node annotation is down or with no ip, the error msg should be printed periodically
956
                if c.config.Iface == nodeTunnelName {
×
957
                        klog.V(3).Infof("node tunnel interface %s not changed", nodeTunnelName)
×
958
                        return
×
959
                }
×
960
                c.config.Iface = nodeTunnelName
×
961
                klog.Infof("Update node tunnel interface %v", nodeTunnelName)
×
962

×
963
                encapIP := strings.Split(addrs[0].String(), "/")[0]
×
UNCOV
964
                if err = setEncapIP(encapIP); err != nil {
×
UNCOV
965
                        klog.Errorf("failed to set encap ip %s for iface %s", encapIP, c.config.Iface)
×
UNCOV
966
                        return
×
967
                }
×
968
        }
969
}
970

971
func (c *Controller) ovnMetricsUpdate() {
×
972
        c.setOvnSubnetGatewayMetric()
×
973

×
974
        resetSysParaMetrics()
×
975
        c.setIPLocalPortRangeMetric()
×
976
        c.setCheckSumErrMetric()
×
977
        c.setDNSSearchMetric()
×
978
        c.setTCPTwRecycleMetric()
×
979
        c.setTCPMtuProbingMetric()
×
980
        c.setConntrackTCPLiberalMetric()
×
UNCOV
981
        c.setBridgeNfCallIptablesMetric()
×
982
        c.setIPv6RouteMaxsizeMetric()
×
983
        c.setTCPMemMetric()
×
984
}
×
985

986
func resetSysParaMetrics() {
×
987
        metricIPLocalPortRange.Reset()
×
988
        metricCheckSumErr.Reset()
×
989
        metricDNSSearch.Reset()
×
990
        metricTCPTwRecycle.Reset()
×
991
        metricTCPMtuProbing.Reset()
×
992
        metricConntrackTCPLiberal.Reset()
×
UNCOV
993
        metricBridgeNfCallIptables.Reset()
×
994
        metricTCPMem.Reset()
×
995
        metricIPv6RouteMaxsize.Reset()
×
996
}
×
997

998
func rotateLog() {
×
999
        output, err := exec.Command("logrotate", "/etc/logrotate.d/openvswitch").CombinedOutput()
×
1000
        if err != nil {
×
1001
                klog.Errorf("failed to rotate openvswitch log %q", output)
×
1002
        }
×
1003
        output, err = exec.Command("logrotate", "/etc/logrotate.d/ovn").CombinedOutput()
×
1004
        if err != nil {
×
1005
                klog.Errorf("failed to rotate ovn log %q", output)
×
1006
        }
×
UNCOV
1007
        output, err = exec.Command("logrotate", "/etc/logrotate.d/kubeovn").CombinedOutput()
×
UNCOV
1008
        if err != nil {
×
1009
                klog.Errorf("failed to rotate kube-ovn log %q", output)
×
1010
        }
×
1011
}
1012

1013
func kernelModuleLoaded(module string) (bool, error) {
×
1014
        data, err := os.ReadFile("/proc/modules")
×
UNCOV
1015
        if err != nil {
×
1016
                klog.Errorf("failed to read /proc/modules: %v", err)
×
1017
                return false, err
×
1018
        }
×
1019

UNCOV
1020
        for line := range strings.SplitSeq(string(data), "\n") {
×
UNCOV
1021
                if fields := strings.Fields(line); len(fields) != 0 && fields[0] == module {
×
1022
                        return true, nil
×
UNCOV
1023
                }
×
1024
        }
1025

UNCOV
1026
        return false, nil
×
1027
}
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