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

kubeovn / kube-ovn / 14372473322

10 Apr 2025 04:42AM UTC coverage: 21.704% (-0.3%) from 22.009%
14372473322

Pull #5110

github

zbb88888
fix fmt

Signed-off-by: zbb88888 <jmdxjsjgcxy@gmail.com>
Pull Request #5110: enable check vlan conflict

0 of 178 new or added lines in 6 files covered. (0.0%)

1053 existing lines in 9 files now uncovered.

10263 of 47286 relevant lines covered (21.7%)

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
        "syscall"
14

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

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

34
const (
35
        kernelModuleIPTables  = "ip_tables"
36
        kernelModuleIP6Tables = "ip6_tables"
37
)
38

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

48
        nmSyncer *networkManagerSyncer
49
}
50

51
func evalCommandSymlinks(cmd string) (string, error) {
52
        path, err := exec.LookPath(cmd)
53
        if err != nil {
54
                return "", fmt.Errorf("failed to search for command %q: %w", cmd, err)
55
        }
56
        file, err := filepath.EvalSymlinks(path)
57
        if err != nil {
58
                return "", fmt.Errorf("failed to read evaluate symbolic links for file %q: %w", path, err)
59
        }
60

61
        return file, nil
UNCOV
62
}
×
UNCOV
63

×
64
func isLegacyIptablesMode() (bool, error) {
×
65
        path, err := evalCommandSymlinks("iptables")
×
66
        if err != nil {
×
67
                return false, err
×
68
        }
×
69
        pathLegacy, err := evalCommandSymlinks("iptables-legacy")
×
70
        if err != nil {
×
71
                return false, err
72
        }
×
73
        return path == pathLegacy, nil
74
}
UNCOV
75

×
76
func (c *Controller) initRuntime() error {
×
77
        ok, err := isLegacyIptablesMode()
×
78
        if err != nil {
×
79
                klog.Errorf("failed to check iptables mode: %v", err)
×
80
                return err
×
81
        }
×
82
        if !ok {
×
83
                // iptables works in nft mode, we should migrate iptables rules
×
84
                c.iptablesObsolete = make(map[string]*iptables.IPTables, 2)
×
85
        }
86

87
        c.iptables = make(map[string]*iptables.IPTables)
×
88
        c.ipsets = make(map[string]*ipsets.IPSets)
×
89
        c.gwCounters = make(map[string]*util.GwIPtableCounters)
×
90
        c.k8siptables = make(map[string]k8siptables.Interface)
×
91
        c.k8sipsets = k8sipset.New(c.k8sExec)
×
92

×
93
        if c.protocol == kubeovnv1.ProtocolIPv4 || c.protocol == kubeovnv1.ProtocolDual {
×
94
                ipt, err := iptables.NewWithProtocol(iptables.ProtocolIPv4)
×
95
                if err != nil {
×
96
                        klog.Error(err)
×
97
                        return err
98
                }
×
99
                c.iptables[kubeovnv1.ProtocolIPv4] = ipt
×
100
                if c.iptablesObsolete != nil {
×
101
                        ok, err := kernelModuleLoaded(kernelModuleIPTables)
×
102
                        if err != nil {
×
103
                                klog.Errorf("failed to check kernel module %s: %v", kernelModuleIPTables, err)
×
104
                        }
×
105
                        if ok {
×
106
                                if ipt, err = iptables.NewWithProtocolAndMode(iptables.ProtocolIPv4, "legacy"); err != nil {
×
107
                                        klog.Error(err)
×
108
                                        return err
×
109
                                }
×
110
                                c.iptablesObsolete[kubeovnv1.ProtocolIPv4] = ipt
×
UNCOV
111
                        }
×
UNCOV
112
                }
×
113
                c.ipsets[kubeovnv1.ProtocolIPv4] = ipsets.NewIPSets(ipsets.NewIPVersionConfig(ipsets.IPFamilyV4, IPSetPrefix, nil, nil))
×
114
                c.k8siptables[kubeovnv1.ProtocolIPv4] = k8siptables.New(c.k8sExec, k8siptables.ProtocolIPv4)
×
UNCOV
115
        }
×
116
        if c.protocol == kubeovnv1.ProtocolIPv6 || c.protocol == kubeovnv1.ProtocolDual {
×
117
                ipt, err := iptables.NewWithProtocol(iptables.ProtocolIPv6)
×
118
                if err != nil {
×
119
                        klog.Error(err)
×
120
                        return err
×
121
                }
×
122
                c.iptables[kubeovnv1.ProtocolIPv6] = ipt
×
123
                if c.iptablesObsolete != nil {
124
                        ok, err := kernelModuleLoaded(kernelModuleIP6Tables)
125
                        if err != nil {
×
126
                                klog.Errorf("failed to check kernel module %s: %v", kernelModuleIP6Tables, err)
×
127
                        }
128
                        if ok {
×
129
                                if ipt, err = iptables.NewWithProtocolAndMode(iptables.ProtocolIPv6, "legacy"); err != nil {
×
130
                                        klog.Error(err)
×
131
                                        return err
×
132
                                }
×
133
                                c.iptablesObsolete[kubeovnv1.ProtocolIPv6] = ipt
×
UNCOV
134
                        }
×
UNCOV
135
                }
×
136
                c.ipsets[kubeovnv1.ProtocolIPv6] = ipsets.NewIPSets(ipsets.NewIPVersionConfig(ipsets.IPFamilyV6, IPSetPrefix, nil, nil))
×
137
                c.k8siptables[kubeovnv1.ProtocolIPv6] = k8siptables.New(c.k8sExec, k8siptables.ProtocolIPv6)
×
UNCOV
138
        }
×
UNCOV
139

×
140
        c.nmSyncer = newNetworkManagerSyncer()
×
141
        c.nmSyncer.Run(c.transferAddrsAndRoutes)
×
142

×
143
        return nil
×
UNCOV
144
}
×
UNCOV
145

×
146
func (c *Controller) reconcileRouters(event *subnetEvent) error {
147
        subnets, err := c.subnetsLister.List(labels.Everything())
148
        if err != nil {
×
149
                klog.Errorf("failed to list subnets %v", err)
×
150
                return err
151
        }
UNCOV
152

×
153
        if event != nil {
×
154
                var ok bool
×
155
                var oldSubnet, newSubnet *kubeovnv1.Subnet
×
156
                if event.oldObj != nil {
157
                        if oldSubnet, ok = event.oldObj.(*kubeovnv1.Subnet); !ok {
158
                                klog.Errorf("expected old subnet in subnetEvent but got %#v", event.oldObj)
×
159
                                return nil
×
160
                        }
×
UNCOV
161
                }
×
162
                if event.newObj != nil {
×
163
                        if newSubnet, ok = event.newObj.(*kubeovnv1.Subnet); !ok {
×
164
                                klog.Errorf("expected new subnet in subnetEvent but got %#v", event.newObj)
×
165
                                return nil
×
166
                        }
×
UNCOV
167
                }
×
UNCOV
168

×
UNCOV
169
                // handle policy routing
×
170
                rulesToAdd, rulesToDel, routesToAdd, routesToDel, err := c.diffPolicyRouting(oldSubnet, newSubnet)
×
171
                if err != nil {
×
172
                        klog.Errorf("failed to get policy routing difference: %v", err)
173
                        return err
×
174
                }
×
UNCOV
175
                // add new routes first
×
176
                for _, r := range routesToAdd {
×
177
                        if err = netlink.RouteReplace(&r); err != nil && !errors.Is(err, syscall.EEXIST) {
×
178
                                klog.Errorf("failed to replace route for subnet %s: %v", newSubnet.Name, err)
×
179
                                return err
×
180
                        }
×
UNCOV
181
                }
×
UNCOV
182
                // next, add new rules
×
183
                for _, r := range rulesToAdd {
×
184
                        if err = netlink.RuleAdd(&r); err != nil && !errors.Is(err, syscall.EEXIST) {
×
185
                                klog.Errorf("failed to add network rule for subnet %s: %v", newSubnet.Name, err)
186
                                return err
187
                        }
×
UNCOV
188
                }
×
UNCOV
189
                // then delete old network rules
×
190
                for _, r := range rulesToDel {
×
191
                        // loop to delete all matched rules
×
192
                        for {
×
193
                                if err = netlink.RuleDel(&r); err != nil {
194
                                        if !errors.Is(err, syscall.ENOENT) {
×
195
                                                klog.Errorf("failed to delete network rule for subnet %s: %v", oldSubnet.Name, err)
×
196
                                                return err
×
197
                                        }
×
198
                                        break
×
UNCOV
199
                                }
×
UNCOV
200
                        }
×
UNCOV
201
                }
×
202
                // last, delete old network routes
203
                for _, r := range routesToDel {
204
                        if err = netlink.RouteDel(&r); err != nil && !errors.Is(err, syscall.ENOENT) {
205
                                klog.Errorf("failed to delete route for subnet %s: %v", oldSubnet.Name, err)
206
                                return err
×
207
                        }
208
                }
UNCOV
209
        }
×
UNCOV
210

×
211
        node, err := c.nodesLister.Get(c.config.NodeName)
×
212
        if err != nil {
×
213
                klog.Errorf("failed to get node %s %v", c.config.NodeName, err)
×
214
                return err
×
215
        }
216
        nodeIPv4, nodeIPv6 := util.GetNodeInternalIP(*node)
×
217
        var joinIPv4, joinIPv6 string
×
218
        if len(node.Annotations) != 0 {
×
219
                joinIPv4, joinIPv6 = util.SplitStringIP(node.Annotations[util.IPAddressAnnotation])
×
220
        }
×
UNCOV
221

×
222
        joinCIDR := make([]string, 0, 2)
×
223
        cidrs := make([]string, 0, len(subnets)*2)
×
224
        for _, subnet := range subnets {
225
                // The route for overlay subnet cidr via ovn0 should not be deleted even though subnet.Status has changed to not ready
×
226
                if subnet.Spec.Vpc != c.config.ClusterRouter ||
×
227
                        (subnet.Spec.Vlan != "" && !subnet.Spec.LogicalGateway && (!subnet.Spec.U2OInterconnection || (subnet.Spec.EnableLb != nil && *subnet.Spec.EnableLb))) ||
×
228
                        !subnet.Status.IsValidated() {
×
229
                        continue
×
230
                }
231

232
                for _, cidrBlock := range strings.Split(subnet.Spec.CIDRBlock, ",") {
×
233
                        if _, ipNet, err := net.ParseCIDR(cidrBlock); err != nil {
×
234
                                klog.Errorf("%s is not a valid cidr block", cidrBlock)
×
235
                        } else {
×
236
                                if nodeIPv4 != "" && util.CIDRContainIP(cidrBlock, nodeIPv4) {
237
                                        continue
×
UNCOV
238
                                }
×
239
                                if nodeIPv6 != "" && util.CIDRContainIP(cidrBlock, nodeIPv6) {
×
240
                                        continue
×
UNCOV
241
                                }
×
242
                                cidrs = append(cidrs, ipNet.String())
243
                                if subnet.Name == c.config.NodeSwitch {
×
244
                                        joinCIDR = append(joinCIDR, ipNet.String())
×
245
                                }
×
UNCOV
246
                        }
×
UNCOV
247
                }
×
248
        }
249

250
        gateway, ok := node.Annotations[util.GatewayAnnotation]
×
251
        if !ok {
×
252
                klog.Errorf("annotation for node %s ovn.kubernetes.io/gateway not exists", node.Name)
×
253
                return errors.New("annotation for node ovn.kubernetes.io/gateway not exists")
×
254
        }
×
255
        nic, err := netlink.LinkByName(util.NodeNic)
256
        if err != nil {
257
                klog.Errorf("failed to get nic %s", util.NodeNic)
×
258
                return fmt.Errorf("failed to get nic %s", util.NodeNic)
×
259
        }
×
UNCOV
260

×
261
        allRoutes, err := getNicExistRoutes(nil, gateway)
×
262
        if err != nil {
×
263
                klog.Error(err)
×
264
                return err
×
265
        }
×
266
        nodeNicRoutes, err := getNicExistRoutes(nic, gateway)
267
        if err != nil {
268
                klog.Error(err)
269
                return err
270
        }
×
271
        toAdd, toDel := routeDiff(nodeNicRoutes, allRoutes, cidrs, joinCIDR, joinIPv4, joinIPv6, gateway, net.ParseIP(nodeIPv4), net.ParseIP(nodeIPv6))
×
272
        for _, r := range toDel {
×
273
                if err = netlink.RouteDel(&netlink.Route{Dst: r.Dst}); err != nil {
×
274
                        klog.Errorf("failed to del route %v", err)
×
275
                }
276
        }
277

278
        for _, r := range toAdd {
×
279
                r.LinkIndex = nic.Attrs().Index
×
280
                if err = netlink.RouteReplace(&r); err != nil {
×
281
                        klog.Errorf("failed to replace route %v: %v", r, err)
×
282
                }
×
UNCOV
283
        }
×
UNCOV
284

×
285
        return nil
×
UNCOV
286
}
×
UNCOV
287

×
288
func getNicExistRoutes(nic netlink.Link, gateway string) ([]netlink.Route, error) {
289
        var routes, existRoutes []netlink.Route
×
290
        var err error
×
291
        for _, gw := range strings.Split(gateway, ",") {
×
292
                if util.CheckProtocol(gw) == kubeovnv1.ProtocolIPv4 {
×
293
                        routes, err = netlink.RouteList(nic, netlink.FAMILY_V4)
×
294
                } else {
×
295
                        routes, err = netlink.RouteList(nic, netlink.FAMILY_V6)
×
296
                }
×
297
                if err != nil {
298
                        return nil, err
299
                }
×
300
                existRoutes = append(existRoutes, routes...)
×
UNCOV
301
        }
×
302
        return existRoutes, nil
×
UNCOV
303
}
×
UNCOV
304

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

309
        for _, route := range nodeNicRoutes {
×
310
                if route.Scope == netlink.SCOPE_LINK || route.Dst == nil || route.Dst.IP.IsLinkLocalUnicast() {
×
311
                        continue
×
UNCOV
312
                }
×
313

314
                found := false
315
                for _, c := range cidrs {
316
                        if route.Dst.String() == c {
317
                                found = true
×
318
                                break
×
UNCOV
319
                        }
×
UNCOV
320
                }
×
321
                if !found {
×
322
                        toDel = append(toDel, route)
×
323
                }
×
324
                conflict := false
×
325
                for _, ar := range allRoutes {
×
326
                        if ar.Dst != nil && ar.Dst.String() == route.Dst.String() && ar.LinkIndex != route.LinkIndex {
×
327
                                // route conflict
328
                                conflict = true
×
329
                                break
×
UNCOV
330
                        }
×
UNCOV
331
                }
×
332
                if conflict {
×
333
                        toDel = append(toDel, route)
×
334
                }
×
UNCOV
335
        }
×
336
        if len(toDel) > 0 {
×
337
                klog.Infof("routes to delete: %v", toDel)
×
338
        }
×
UNCOV
339

×
340
        ipv4, ipv6 := util.SplitStringIP(gateway)
×
341
        gwV4, gwV6 := net.ParseIP(ipv4), net.ParseIP(ipv6)
×
342
        for _, c := range cidrs {
×
343
                var src, gw net.IP
344
                switch util.CheckProtocol(c) {
345
                case kubeovnv1.ProtocolIPv4:
×
346
                        src, gw = srcIPv4, gwV4
×
347
                case kubeovnv1.ProtocolIPv6:
×
348
                        src, gw = srcIPv6, gwV6
×
UNCOV
349
                }
×
350

351
                found := false
352
                for _, ar := range allRoutes {
×
353
                        if ar.Dst != nil && ar.Dst.String() == c {
354
                                // route already exist
355
                                found = true
×
356
                                break
×
UNCOV
357
                        }
×
UNCOV
358
                }
×
359
                if found {
×
360
                        continue
×
UNCOV
361
                }
×
362
                for _, r := range nodeNicRoutes {
×
363
                        if r.Dst == nil || r.Dst.String() != c {
×
364
                                continue
×
UNCOV
365
                        }
×
366
                        if src == nil {
×
367
                                if r.Src == nil {
×
368
                                        found = true
369
                                        break
×
370
                                }
371
                        } else if src.Equal(r.Src) {
372
                                found = true
×
373
                                break
×
UNCOV
374
                        }
×
UNCOV
375
                }
×
376
                if !found {
×
377
                        var priority int
×
378
                        scope := netlink.SCOPE_UNIVERSE
×
379
                        proto := netlink.RouteProtocol(syscall.RTPROT_STATIC)
×
380
                        if slices.Contains(joinCIDR, c) {
×
381
                                if util.CheckProtocol(c) == kubeovnv1.ProtocolIPv4 {
382
                                        src = net.ParseIP(joinIPv4)
×
383
                                } else {
384
                                        src, priority = nil, 256
385
                                }
×
386
                                gw, scope = nil, netlink.SCOPE_LINK
×
387
                                proto = netlink.RouteProtocol(unix.RTPROT_KERNEL)
×
UNCOV
388
                        }
×
389
                        _, cidr, _ := net.ParseCIDR(c)
×
390
                        toAdd = append(toAdd, netlink.Route{
×
391
                                Dst:      cidr,
×
392
                                Src:      src,
393
                                Gw:       gw,
394
                                Protocol: proto,
×
395
                                Scope:    scope,
×
396
                                Priority: priority,
×
397
                        })
×
UNCOV
398
                }
×
UNCOV
399
        }
×
400
        if len(toAdd) > 0 {
401
                klog.Infof("routes to add: %v", toAdd)
402
        }
×
403
        return
×
UNCOV
404
}
×
405

406
func getRulesToAdd(oldRules, newRules []netlink.Rule) []netlink.Rule {
407
        var toAdd []netlink.Rule
×
408

×
409
        for _, rule := range newRules {
×
410
                var found bool
×
411
                for _, r := range oldRules {
×
412
                        if r.Family == rule.Family && r.Priority == rule.Priority && r.Table == rule.Table && reflect.DeepEqual(r.Src, rule.Src) {
×
413
                                found = true
414
                                break
UNCOV
415
                        }
×
UNCOV
416
                }
×
417
                if !found {
×
418
                        toAdd = append(toAdd, rule)
419
                }
UNCOV
420
        }
×
421

422
        return toAdd
UNCOV
423
}
×
UNCOV
424

×
425
func getRoutesToAdd(oldRoutes, newRoutes []netlink.Route) []netlink.Route {
×
426
        var toAdd []netlink.Route
×
427

×
428
        for _, route := range newRoutes {
×
429
                var found bool
430
                for _, r := range oldRoutes {
×
431
                        if r.Equal(route) {
×
432
                                found = true
×
433
                                break
×
434
                        }
UNCOV
435
                }
×
436
                if !found {
×
437
                        toAdd = append(toAdd, route)
×
438
                }
×
UNCOV
439
        }
×
440

441
        return toAdd
×
UNCOV
442
}
×
UNCOV
443

×
444
func (c *Controller) diffPolicyRouting(oldSubnet, newSubnet *kubeovnv1.Subnet) (rulesToAdd, rulesToDel []netlink.Rule, routesToAdd, routesToDel []netlink.Route, err error) {
×
445
        oldRules, oldRoutes, err := c.getPolicyRouting(oldSubnet)
446
        if err != nil {
×
447
                klog.Error(err)
×
448
                return
×
449
        }
×
450
        newRules, newRoutes, err := c.getPolicyRouting(newSubnet)
×
451
        if err != nil {
452
                klog.Error(err)
×
453
                return
×
454
        }
×
UNCOV
455

×
456
        rulesToAdd = getRulesToAdd(oldRules, newRules)
×
457
        rulesToDel = getRulesToAdd(newRules, oldRules)
458
        routesToAdd = getRoutesToAdd(oldRoutes, newRoutes)
459
        routesToDel = getRoutesToAdd(newRoutes, oldRoutes)
×
460

×
461
        return
462
}
UNCOV
463

×
464
func (c *Controller) getPolicyRouting(subnet *kubeovnv1.Subnet) ([]netlink.Rule, []netlink.Route, error) {
×
465
        if subnet == nil || subnet.Spec.ExternalEgressGateway == "" || subnet.Spec.Vpc != c.config.ClusterRouter {
×
466
                return nil, nil, nil
×
467
        }
×
468
        if subnet.Spec.GatewayType == kubeovnv1.GWCentralizedType && !util.GatewayContains(subnet.Spec.GatewayNode, c.config.NodeName) {
×
469
                return nil, nil, nil
×
470
        }
×
UNCOV
471

×
472
        protocols := make([]string, 1, 2)
×
473
        if protocol := util.CheckProtocol(subnet.Spec.ExternalEgressGateway); protocol == kubeovnv1.ProtocolDual {
×
474
                protocols[0] = kubeovnv1.ProtocolIPv4
475
                protocols = append(protocols, kubeovnv1.ProtocolIPv6)
476
        } else {
×
477
                protocols[0] = protocol
×
478
        }
×
UNCOV
479

×
480
        cidr := strings.Split(subnet.Spec.CIDRBlock, ",")
×
481
        egw := strings.Split(subnet.Spec.ExternalEgressGateway, ",")
482

483
        // rules
484
        var rules []netlink.Rule
×
485
        rule := netlink.NewRule()
×
486
        rule.Table = int(subnet.Spec.PolicyRoutingTableID)
×
487
        rule.Priority = int(subnet.Spec.PolicyRoutingPriority)
×
488
        if subnet.Spec.GatewayType == kubeovnv1.GWDistributedType {
×
489
                pods, err := c.podsLister.List(labels.Everything())
×
490
                if err != nil {
×
491
                        klog.Errorf("list pods failed, %+v", err)
×
492
                        return nil, nil, err
493
                }
UNCOV
494

×
495
                hostname := os.Getenv(util.HostnameEnv)
×
496
                for _, pod := range pods {
×
497
                        if pod.Spec.HostNetwork ||
×
498
                                pod.Status.PodIP == "" ||
×
499
                                pod.Annotations[util.LogicalSwitchAnnotation] != subnet.Name ||
500
                                pod.Spec.NodeName != hostname {
×
501
                                continue
×
UNCOV
502
                        }
×
UNCOV
503

×
504
                        for i := range protocols {
×
505
                                rule.Family, _ = util.ProtocolToFamily(protocols[i])
×
506

507
                                var ip net.IP
508
                                var maskBits int
509
                                if len(pod.Status.PodIPs) == 2 && protocols[i] == kubeovnv1.ProtocolIPv6 {
×
510
                                        ip = net.ParseIP(pod.Status.PodIPs[1].IP)
×
511
                                        maskBits = 128
×
512
                                } else if util.CheckProtocol(pod.Status.PodIP) == protocols[i] {
×
513
                                        ip = net.ParseIP(pod.Status.PodIP)
×
514
                                        maskBits = 32
×
515
                                        if rule.Family == netlink.FAMILY_V6 {
516
                                                maskBits = 128
517
                                        }
UNCOV
518
                                }
×
519

520
                                rule.Src = &net.IPNet{IP: ip, Mask: net.CIDRMask(maskBits, maskBits)}
521
                                rules = append(rules, *rule)
×
UNCOV
522
                        }
×
UNCOV
523
                }
×
524
        } else {
×
525
                for i := range protocols {
×
526
                        rule.Family, _ = util.ProtocolToFamily(protocols[i])
×
527
                        if len(cidr) == len(protocols) {
×
528
                                _, rule.Src, _ = net.ParseCIDR(cidr[i])
×
529
                        }
×
530
                        rules = append(rules, *rule)
×
UNCOV
531
                }
×
UNCOV
532
        }
×
UNCOV
533

×
534
        // routes
535
        var routes []netlink.Route
×
536
        for i := range protocols {
537
                routes = append(routes, netlink.Route{
538
                        Protocol: netlink.RouteProtocol(syscall.RTPROT_STATIC),
×
539
                        Table:    int(subnet.Spec.PolicyRoutingTableID),
×
540
                        Gw:       net.ParseIP(egw[i]),
×
541
                })
×
542
        }
×
UNCOV
543

×
544
        return rules, routes, nil
×
545
}
546

547
func (c *Controller) handlePod(key string) error {
×
548
        namespace, name, err := cache.SplitMetaNamespaceKey(key)
×
549
        if err != nil {
×
550
                utilruntime.HandleError(fmt.Errorf("invalid resource key: %s", key))
×
551
                return nil
×
552
        }
553
        klog.Infof("handle qos update for pod %s/%s", namespace, name)
554

×
555
        pod, err := c.podsLister.Pods(namespace).Get(name)
×
556
        if err != nil {
×
557
                if k8serrors.IsNotFound(err) {
×
558
                        return nil
×
559
                }
×
560
                klog.Error(err)
×
561
                return err
×
UNCOV
562
        }
×
563

564
        if err := util.ValidatePodNetwork(pod.Annotations); err != nil {
565
                klog.Errorf("validate pod %s/%s failed, %v", namespace, name, err)
×
566
                c.recorder.Eventf(pod, v1.EventTypeWarning, "ValidatePodNetworkFailed", err.Error())
×
567
                return err
×
568
        }
UNCOV
569

×
570
        podName := pod.Name
×
571
        if pod.Annotations[fmt.Sprintf(util.VMAnnotationTemplate, util.OvnProvider)] != "" {
×
572
                podName = pod.Annotations[fmt.Sprintf(util.VMAnnotationTemplate, util.OvnProvider)]
573
        }
×
UNCOV
574

×
UNCOV
575
        // set default nic bandwidth
×
UNCOV
576
        //  ovsIngress and ovsEgress are derived from the pod's egress and ingress rate annotations respectively, their roles are reversed from the OVS interface perspective.
×
577
        ifaceID := ovs.PodNameToPortName(podName, pod.Namespace, util.OvnProvider)
×
578
        ovsIngress := pod.Annotations[util.EgressRateAnnotation]
×
579
        ovsEgress := pod.Annotations[util.IngressRateAnnotation]
×
580
        err = ovs.SetInterfaceBandwidth(podName, pod.Namespace, ifaceID, ovsIngress, ovsEgress)
×
581
        if err != nil {
×
582
                klog.Error(err)
583
                return err
584
        }
×
585
        err = ovs.ConfigInterfaceMirror(c.config.EnableMirror, pod.Annotations[util.MirrorControlAnnotation], ifaceID)
×
586
        if err != nil {
×
587
                klog.Error(err)
×
588
                return err
×
589
        }
×
590
        // set linux-netem qos
591
        err = ovs.SetNetemQos(podName, pod.Namespace, ifaceID, pod.Annotations[util.NetemQosLatencyAnnotation], pod.Annotations[util.NetemQosLimitAnnotation], pod.Annotations[util.NetemQosLossAnnotation], pod.Annotations[util.NetemQosJitterAnnotation])
592
        if err != nil {
×
593
                klog.Error(err)
×
594
                return err
595
        }
×
UNCOV
596

×
UNCOV
597
        // set multus-nic bandwidth
×
598
        attachNets, err := nadutils.ParsePodNetworkAnnotation(pod)
599
        if err != nil {
×
600
                klog.Error(err)
×
601
                return err
×
602
        }
×
603
        for _, multiNet := range attachNets {
604
                provider := fmt.Sprintf("%s.%s.%s", multiNet.Name, multiNet.Namespace, util.OvnProvider)
×
605
                if pod.Annotations[fmt.Sprintf(util.VMAnnotationTemplate, provider)] != "" {
×
606
                        podName = pod.Annotations[fmt.Sprintf(util.VMAnnotationTemplate, provider)]
×
607
                }
608
                if pod.Annotations[fmt.Sprintf(util.AllocatedAnnotationTemplate, provider)] == "true" {
609
                        ifaceID = ovs.PodNameToPortName(podName, pod.Namespace, provider)
×
610

×
611
                        err = ovs.SetInterfaceBandwidth(podName, pod.Namespace, ifaceID, pod.Annotations[fmt.Sprintf(util.EgressRateAnnotationTemplate, provider)], pod.Annotations[fmt.Sprintf(util.IngressRateAnnotationTemplate, provider)])
×
612
                        if err != nil {
×
613
                                klog.Error(err)
×
614
                                return err
×
615
                        }
×
616
                        err = ovs.ConfigInterfaceMirror(c.config.EnableMirror, pod.Annotations[fmt.Sprintf(util.MirrorControlAnnotationTemplate, provider)], ifaceID)
×
617
                        if err != nil {
×
618
                                klog.Error(err)
×
619
                                return err
×
620
                        }
×
621
                        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)])
622
                        if err != nil {
×
623
                                klog.Error(err)
×
624
                                return err
×
625
                        }
×
UNCOV
626
                }
×
UNCOV
627
        }
×
628
        return nil
×
UNCOV
629
}
×
UNCOV
630

×
631
func (c *Controller) loopEncapIPCheck() {
632
        node, err := c.nodesLister.Get(c.config.NodeName)
633
        if err != nil {
×
634
                klog.Errorf("failed to get node %s %v", c.config.NodeName, err)
×
635
                return
×
636
        }
×
637

638
        if nodeTunnelName := node.GetAnnotations()[util.TunnelInterfaceAnnotation]; nodeTunnelName != "" {
639
                iface, err := findInterface(nodeTunnelName)
×
640
                if err != nil {
×
641
                        klog.Errorf("failed to find iface %s, %v", nodeTunnelName, err)
×
642
                        return
×
643
                }
×
644
                if iface.Flags&net.FlagUp == 0 {
×
645
                        klog.Errorf("iface %v is down", nodeTunnelName)
×
646
                        return
×
647
                }
×
648
                addrs, err := iface.Addrs()
649
                if err != nil {
650
                        klog.Errorf("failed to get iface addr. %v", err)
×
651
                        return
×
652
                }
×
653
                if len(addrs) == 0 {
654
                        klog.Errorf("iface %s has no ip address", nodeTunnelName)
655
                        return
×
656
                }
657
                if iface.Name != c.config.tunnelIface {
658
                        klog.Infof("use %s as tunnel interface", iface.Name)
×
659
                        c.config.tunnelIface = iface.Name
×
660
                }
×
UNCOV
661

×
UNCOV
662
                // if assigned iface in node annotation is down or with no ip, the error msg should be printed periodically
×
663
                if c.config.Iface == nodeTunnelName {
×
664
                        klog.V(3).Infof("node tunnel interface %s not changed", nodeTunnelName)
×
665
                        return
×
666
                }
×
667
                c.config.Iface = nodeTunnelName
668
                klog.Infof("Update node tunnel interface %v", nodeTunnelName)
669

×
670
                encapIP := strings.Split(addrs[0].String(), "/")[0]
×
671
                if err = setEncapIP(encapIP); err != nil {
×
672
                        klog.Errorf("failed to set encap ip %s for iface %s", encapIP, c.config.Iface)
673
                        return
674
                }
×
675
        }
676
}
UNCOV
677

×
678
func (c *Controller) ovnMetricsUpdate() {
×
679
        c.setOvnSubnetGatewayMetric()
×
680

×
681
        resetSysParaMetrics()
×
682
        c.setIPLocalPortRangeMetric()
×
683
        c.setCheckSumErrMetric()
×
684
        c.setDNSSearchMetric()
×
685
        c.setTCPTwRecycleMetric()
×
686
        c.setTCPMtuProbingMetric()
×
687
        c.setConntrackTCPLiberalMetric()
×
688
        c.setBridgeNfCallIptablesMetric()
689
        c.setIPv6RouteMaxsizeMetric()
×
690
        c.setTCPMemMetric()
×
691
}
×
UNCOV
692

×
693
func resetSysParaMetrics() {
×
694
        metricIPLocalPortRange.Reset()
×
695
        metricCheckSumErr.Reset()
696
        metricDNSSearch.Reset()
697
        metricTCPTwRecycle.Reset()
×
698
        metricTCPMtuProbing.Reset()
×
699
        metricConntrackTCPLiberal.Reset()
×
700
        metricBridgeNfCallIptables.Reset()
×
701
        metricTCPMem.Reset()
×
702
        metricIPv6RouteMaxsize.Reset()
×
703
}
×
704

705
func rotateLog() {
×
706
        output, err := exec.Command("logrotate", "/etc/logrotate.d/openvswitch").CombinedOutput()
×
707
        if err != nil {
×
708
                klog.Errorf("failed to rotate openvswitch log %q", output)
×
709
        }
×
710
        output, err = exec.Command("logrotate", "/etc/logrotate.d/ovn").CombinedOutput()
×
711
        if err != nil {
×
712
                klog.Errorf("failed to rotate ovn log %q", output)
713
        }
×
714
        output, err = exec.Command("logrotate", "/etc/logrotate.d/kubeovn").CombinedOutput()
×
715
        if err != nil {
×
716
                klog.Errorf("failed to rotate kube-ovn log %q", output)
×
717
        }
×
UNCOV
718
}
×
UNCOV
719

×
720
func kernelModuleLoaded(module string) (bool, error) {
×
721
        data, err := os.ReadFile("/proc/modules")
×
722
        if err != nil {
×
723
                klog.Errorf("failed to read /proc/modules: %v", err)
×
724
                return false, err
×
725
        }
×
UNCOV
726

×
727
        for _, line := range strings.Split(string(data), "\n") {
728
                if fields := strings.Fields(line); len(fields) != 0 && fields[0] == module {
×
729
                        return true, nil
×
730
                }
×
UNCOV
731
        }
×
UNCOV
732

×
733
        return false, nil
×
UNCOV
734
}
×
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