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

k8snetworkplumbingwg / sriov-network-operator / 7913628099

15 Feb 2024 09:18AM UTC coverage: 30.287% (+0.1%) from 30.177%
7913628099

Pull #635

github

web-flow
Merge f9cf91565 into 1163ef9d1
Pull Request #635: Optmize refreshing SriovNetworkNodeState

9 of 16 new or added lines in 2 files covered. (56.25%)

3 existing lines in 1 file now uncovered.

3562 of 11761 relevant lines covered (30.29%)

0.33 hits per line

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

43.73
/api/v1/helper.go
1
package v1
2

3
import (
4
        "context"
5
        "encoding/json"
6
        "fmt"
7
        "os"
8
        "regexp"
9
        "sort"
10
        "strconv"
11
        "strings"
12

13
        netattdefv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1"
14
        corev1 "k8s.io/api/core/v1"
15
        "k8s.io/apimachinery/pkg/api/errors"
16
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
17
        uns "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
18
        "k8s.io/apimachinery/pkg/types"
19
        "k8s.io/client-go/kubernetes"
20
        "sigs.k8s.io/controller-runtime/pkg/client"
21
        logf "sigs.k8s.io/controller-runtime/pkg/log"
22

23
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts"
24
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/render"
25
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars"
26
)
27

28
const (
29
        LASTNETWORKNAMESPACE    = "operator.sriovnetwork.openshift.io/last-network-namespace"
30
        NETATTDEFFINALIZERNAME  = "netattdef.finalizers.sriovnetwork.openshift.io"
31
        POOLCONFIGFINALIZERNAME = "poolconfig.finalizers.sriovnetwork.openshift.io"
32
        ESwithModeLegacy        = "legacy"
33
        ESwithModeSwitchDev     = "switchdev"
34

35
        SriovCniStateEnable  = "enable"
36
        SriovCniStateDisable = "disable"
37
        SriovCniStateAuto    = "auto"
38
        SriovCniStateOff     = "off"
39
        SriovCniStateOn      = "on"
40
        SriovCniIpam         = "\"ipam\""
41
        SriovCniIpamEmpty    = SriovCniIpam + ":{}"
42
)
43

44
const invalidVfIndex = -1
45

46
var ManifestsPath = "./bindata/manifests/cni-config"
47
var log = logf.Log.WithName("sriovnetwork")
48

49
// NicIDMap contains supported mapping of IDs with each in the format of:
50
// Vendor ID, Physical Function Device ID, Virtual Function Device ID
51
var NicIDMap = []string{}
52

53
var InitialState SriovNetworkNodeState
54

55
// NetFilterType Represents the NetFilter tags to be used
56
type NetFilterType int
57

58
const (
59
        // OpenstackNetworkID network UUID
60
        OpenstackNetworkID NetFilterType = iota
61

62
        SupportedNicIDConfigmap = "supported-nic-ids"
63
)
64

65
type ConfigurationModeType string
66

67
const (
68
        DaemonConfigurationMode  ConfigurationModeType = "daemon"
69
        SystemdConfigurationMode ConfigurationModeType = "systemd"
70
)
71

72
func (e NetFilterType) String() string {
×
73
        switch e {
×
74
        case OpenstackNetworkID:
×
75
                return "openstack/NetworkID"
×
76
        default:
×
77
                return fmt.Sprintf("%d", int(e))
×
78
        }
79
}
80

81
func InitNicIDMapFromConfigMap(client kubernetes.Interface, namespace string) error {
1✔
82
        cm, err := client.CoreV1().ConfigMaps(namespace).Get(
1✔
83
                context.Background(),
1✔
84
                SupportedNicIDConfigmap,
1✔
85
                metav1.GetOptions{},
1✔
86
        )
1✔
87
        // if the configmap does not exist, return false
1✔
88
        if err != nil {
1✔
89
                return err
×
90
        }
×
91
        for _, v := range cm.Data {
2✔
92
                NicIDMap = append(NicIDMap, v)
1✔
93
        }
1✔
94

95
        return nil
1✔
96
}
97

98
func InitNicIDMapFromList(idList []string) {
1✔
99
        NicIDMap = append(NicIDMap, idList...)
1✔
100
}
1✔
101

102
func IsSupportedVendor(vendorID string) bool {
1✔
103
        for _, n := range NicIDMap {
2✔
104
                ids := strings.Split(n, " ")
1✔
105
                if vendorID == ids[0] {
2✔
106
                        return true
1✔
107
                }
1✔
108
        }
109
        return false
1✔
110
}
111

112
func IsSupportedDevice(deviceID string) bool {
1✔
113
        for _, n := range NicIDMap {
2✔
114
                ids := strings.Split(n, " ")
1✔
115
                if deviceID == ids[1] {
1✔
116
                        return true
×
117
                }
×
118
        }
119
        return false
1✔
120
}
121

122
func IsSupportedModel(vendorID, deviceID string) bool {
1✔
123
        for _, n := range NicIDMap {
2✔
124
                ids := strings.Split(n, " ")
1✔
125
                if vendorID == ids[0] && deviceID == ids[1] {
2✔
126
                        return true
1✔
127
                }
1✔
128
        }
129
        log.Info("IsSupportedModel(): found unsupported model", "vendorId:", vendorID, "deviceId:", deviceID)
1✔
130
        return false
1✔
131
}
132

133
func IsVfSupportedModel(vendorID, deviceID string) bool {
1✔
134
        for _, n := range NicIDMap {
2✔
135
                ids := strings.Split(n, " ")
1✔
136
                if vendorID == ids[0] && deviceID == ids[2] {
2✔
137
                        return true
1✔
138
                }
1✔
139
        }
140
        log.Info("IsVfSupportedModel(): found unsupported VF model", "vendorId:", vendorID, "deviceId:", deviceID)
×
141
        return false
×
142
}
143

144
func IsEnabledUnsupportedVendor(vendorID string, unsupportedNicIDMap map[string]string) bool {
×
145
        for _, n := range unsupportedNicIDMap {
×
146
                if IsValidPciString(n) {
×
147
                        ids := strings.Split(n, " ")
×
148
                        if vendorID == ids[0] {
×
149
                                return true
×
150
                        }
×
151
                }
152
        }
153
        return false
×
154
}
155

156
func IsValidPciString(nicIDString string) bool {
×
157
        ids := strings.Split(nicIDString, " ")
×
158

×
159
        if len(ids) != 3 {
×
160
                log.Info("IsValidPciString(): ", nicIDString)
×
161
                return false
×
162
        }
×
163

164
        if len(ids[0]) != 4 {
×
165
                log.Info("IsValidPciString():", "Invalid vendor PciId ", ids[0])
×
166
                return false
×
167
        }
×
168
        if _, err := strconv.ParseInt(ids[0], 16, 32); err != nil {
×
169
                log.Info("IsValidPciString():", "Invalid vendor PciId ", ids[0])
×
170
        }
×
171

172
        if len(ids[1]) != 4 {
×
173
                log.Info("IsValidPciString():", "Invalid PciId of PF ", ids[1])
×
174
                return false
×
175
        }
×
176
        if _, err := strconv.ParseInt(ids[1], 16, 32); err != nil {
×
177
                log.Info("IsValidPciString():", "Invalid PciId of PF ", ids[1])
×
178
        }
×
179

180
        if len(ids[2]) != 4 {
×
181
                log.Info("IsValidPciString():", "Invalid PciId of VF ", ids[2])
×
182
                return false
×
183
        }
×
184
        if _, err := strconv.ParseInt(ids[2], 16, 32); err != nil {
×
185
                log.Info("IsValidPciString():", "Invalid PciId of VF ", ids[2])
×
186
        }
×
187

188
        return true
×
189
}
190

191
func GetSupportedVfIds() []string {
1✔
192
        var vfIds []string
1✔
193
        for _, n := range NicIDMap {
2✔
194
                ids := strings.Split(n, " ")
1✔
195
                vfID := "0x" + ids[2]
1✔
196
                if !StringInArray(vfID, vfIds) {
2✔
197
                        vfIds = append(vfIds, vfID)
1✔
198
                }
1✔
199
        }
200
        // return a sorted slice so that udev rule is stable
201
        sort.Slice(vfIds, func(i, j int) bool {
2✔
202
                ip, _ := strconv.ParseInt(vfIds[i], 0, 32)
1✔
203
                jp, _ := strconv.ParseInt(vfIds[j], 0, 32)
1✔
204
                return ip < jp
1✔
205
        })
1✔
206
        return vfIds
1✔
207
}
208

209
func GetVfDeviceID(deviceID string) string {
×
210
        for _, n := range NicIDMap {
×
211
                ids := strings.Split(n, " ")
×
212
                if deviceID == ids[1] {
×
213
                        return ids[2]
×
214
                }
×
215
        }
216
        return ""
×
217
}
218

219
func IsSwitchdevModeSpec(spec SriovNetworkNodeStateSpec) bool {
1✔
220
        for _, iface := range spec.Interfaces {
1✔
221
                if iface.EswitchMode == ESwithModeSwitchDev {
×
222
                        return true
×
223
                }
×
224
        }
225
        return false
1✔
226
}
227

228
func FindInterface(interfaces Interfaces, name string) (iface Interface, err error) {
×
229
        for _, i := range interfaces {
×
230
                if i.Name == name {
×
231
                        return i, nil
×
232
                }
×
233
        }
234
        return Interface{}, fmt.Errorf("unable to find interface: %v", name)
×
235
}
236

237
func NeedToUpdateSriov(ifaceSpec *Interface, ifaceStatus *InterfaceExt) bool {
1✔
238
        if ifaceSpec.Mtu > 0 {
2✔
239
                mtu := ifaceSpec.Mtu
1✔
240
                if mtu != ifaceStatus.Mtu {
1✔
241
                        log.V(2).Info("NeedToUpdateSriov(): MTU needs update", "desired", mtu, "current", ifaceStatus.Mtu)
×
242
                        return true
×
243
                }
×
244
        }
245

246
        if ifaceSpec.NumVfs != ifaceStatus.NumVfs {
1✔
247
                log.V(2).Info("NeedToUpdateSriov(): NumVfs needs update", "desired", ifaceSpec.NumVfs, "current", ifaceStatus.NumVfs)
×
248
                return true
×
249
        }
×
250
        if ifaceSpec.NumVfs > 0 {
2✔
251
                for _, vfStatus := range ifaceStatus.VFs {
2✔
252
                        ingroup := false
1✔
253
                        for _, groupSpec := range ifaceSpec.VfGroups {
2✔
254
                                if IndexInRange(vfStatus.VfID, groupSpec.VfRange) {
2✔
255
                                        ingroup = true
1✔
256
                                        if groupSpec.DeviceType != consts.DeviceTypeNetDevice {
1✔
257
                                                if groupSpec.DeviceType != vfStatus.Driver {
×
258
                                                        log.V(2).Info("NeedToUpdateSriov(): Driver needs update",
×
259
                                                                "desired", groupSpec.DeviceType, "current", vfStatus.Driver)
×
260
                                                        return true
×
261
                                                }
×
262
                                        } else {
1✔
263
                                                if StringInArray(vfStatus.Driver, vars.DpdkDrivers) {
1✔
264
                                                        log.V(2).Info("NeedToUpdateSriov(): Driver needs update",
×
265
                                                                "desired", groupSpec.DeviceType, "current", vfStatus.Driver)
×
266
                                                        return true
×
267
                                                }
×
268
                                                if vfStatus.Mtu != 0 && groupSpec.Mtu != 0 && vfStatus.Mtu != groupSpec.Mtu {
2✔
269
                                                        log.V(2).Info("NeedToUpdateSriov(): VF MTU needs update",
1✔
270
                                                                "vf", vfStatus.VfID, "desired", groupSpec.Mtu, "current", vfStatus.Mtu)
1✔
271
                                                        return true
1✔
272
                                                }
1✔
273

274
                                                // this is needed to be sure the admin mac address is configured as expected
275
                                                if ifaceSpec.ExternallyManaged {
1✔
276
                                                        log.V(2).Info("NeedToUpdateSriov(): need to update the device as it's externally manage",
×
277
                                                                "device", ifaceStatus.PciAddress)
×
278
                                                        return true
×
279
                                                }
×
280
                                        }
281
                                        break
1✔
282
                                }
283
                        }
284
                        if !ingroup && StringInArray(vfStatus.Driver, vars.DpdkDrivers) {
1✔
285
                                // VF which has DPDK driver loaded but not in any group, needs to be reset to default driver.
×
286
                                return true
×
287
                        }
×
288
                }
289
        }
290
        return false
1✔
291
}
292

293
type ByPriority []SriovNetworkNodePolicy
294

295
func (a ByPriority) Len() int {
×
296
        return len(a)
×
297
}
×
298

299
func (a ByPriority) Less(i, j int) bool {
×
300
        if a[i].Spec.Priority != a[j].Spec.Priority {
×
301
                return a[i].Spec.Priority > a[j].Spec.Priority
×
302
        }
×
303
        return a[i].GetName() < a[j].GetName()
×
304
}
305

306
func (a ByPriority) Swap(i, j int) {
×
307
        a[i], a[j] = a[j], a[i]
×
308
}
×
309

310
// Match check if node is selected by NodeSelector
311
func (p *SriovNetworkNodePolicy) Selected(node *corev1.Node) bool {
1✔
312
        for k, v := range p.Spec.NodeSelector {
1✔
313
                if nv, ok := node.Labels[k]; ok && nv == v {
×
314
                        continue
×
315
                }
316
                return false
×
317
        }
318
        return true
1✔
319
}
320

321
func StringInArray(val string, array []string) bool {
1✔
322
        for i := range array {
2✔
323
                if array[i] == val {
2✔
324
                        return true
1✔
325
                }
1✔
326
        }
327
        return false
1✔
328
}
329

330
func RemoveString(s string, slice []string) (result []string, found bool) {
1✔
331
        if len(slice) != 0 {
2✔
332
                for _, item := range slice {
2✔
333
                        if item == s {
2✔
334
                                found = true
1✔
335
                                continue
1✔
336
                        }
337
                        result = append(result, item)
×
338
                }
339
        }
340
        return
1✔
341
}
342

343
func UniqueAppend(inSlice []string, strings ...string) []string {
×
344
        for _, s := range strings {
×
345
                if !StringInArray(s, inSlice) {
×
346
                        inSlice = append(inSlice, s)
×
347
                }
×
348
        }
349
        return inSlice
×
350
}
351

352
// Apply policy to SriovNetworkNodeState CR
353
func (p *SriovNetworkNodePolicy) Apply(state *SriovNetworkNodeState, equalPriority bool) error {
×
354
        s := p.Spec.NicSelector
×
355
        if s.Vendor == "" && s.DeviceID == "" && len(s.RootDevices) == 0 && len(s.PfNames) == 0 &&
×
356
                len(s.NetFilter) == 0 {
×
357
                // Empty NicSelector match none
×
358
                return nil
×
359
        }
×
360
        for _, iface := range state.Status.Interfaces {
×
361
                if s.Selected(&iface) {
×
362
                        log.Info("Update interface", "name:", iface.Name)
×
363
                        result := Interface{
×
364
                                PciAddress:        iface.PciAddress,
×
365
                                Mtu:               p.Spec.Mtu,
×
366
                                Name:              iface.Name,
×
367
                                LinkType:          p.Spec.LinkType,
×
368
                                EswitchMode:       p.Spec.EswitchMode,
×
369
                                NumVfs:            p.Spec.NumVfs,
×
370
                                ExternallyManaged: p.Spec.ExternallyManaged,
×
371
                        }
×
372
                        if p.Spec.NumVfs > 0 {
×
373
                                group, err := p.generateVfGroup(&iface)
×
374
                                if err != nil {
×
375
                                        return err
×
376
                                }
×
377
                                result.VfGroups = []VfGroup{*group}
×
378
                                found := false
×
379
                                for i := range state.Spec.Interfaces {
×
380
                                        if state.Spec.Interfaces[i].PciAddress == result.PciAddress {
×
381
                                                found = true
×
382
                                                state.Spec.Interfaces[i].mergeConfigs(&result, equalPriority)
×
383
                                                state.Spec.Interfaces[i] = result
×
384
                                                break
×
385
                                        }
386
                                }
387
                                if !found {
×
388
                                        state.Spec.Interfaces = append(state.Spec.Interfaces, result)
×
389
                                }
×
390
                        }
391
                }
392
        }
393
        return nil
×
394
}
395

396
// mergeConfigs merges configs from multiple polices where the last one has the
397
// highest priority. This merge is dependent on: 1. SR-IOV partition is
398
// configured with the #-notation in pfName, 2. The VF groups are
399
// non-overlapping or SR-IOV policies have the same priority.
400
func (iface Interface) mergeConfigs(input *Interface, equalPriority bool) {
×
401
        m := false
×
402
        // merge VF groups (input.VfGroups already contains the highest priority):
×
403
        // - skip group with same ResourceName,
×
404
        // - skip overlapping groups (use only highest priority)
×
405
        for _, gr := range iface.VfGroups {
×
406
                if gr.ResourceName == input.VfGroups[0].ResourceName || gr.isVFRangeOverlapping(input.VfGroups[0]) {
×
407
                        continue
×
408
                }
409
                m = true
×
410
                input.VfGroups = append(input.VfGroups, gr)
×
411
        }
412

413
        if !equalPriority && !m {
×
414
                return
×
415
        }
×
416

417
        // mtu configuration we take the highest value
418
        if input.Mtu < iface.Mtu {
×
419
                input.Mtu = iface.Mtu
×
420
        }
×
421
        if input.NumVfs < iface.NumVfs {
×
422
                input.NumVfs = iface.NumVfs
×
423
        }
×
424
}
425

426
func (gr VfGroup) isVFRangeOverlapping(group VfGroup) bool {
×
427
        rngSt, rngEnd, err := parseRange(gr.VfRange)
×
428
        if err != nil {
×
429
                return false
×
430
        }
×
431
        rngSt2, rngEnd2, err := parseRange(group.VfRange)
×
432
        if err != nil {
×
433
                return false
×
434
        }
×
435
        // compare minimal range has overlap
436
        if rngSt < rngSt2 {
×
437
                return IndexInRange(rngSt2, gr.VfRange) || IndexInRange(rngEnd2, gr.VfRange)
×
438
        }
×
439
        return IndexInRange(rngSt, group.VfRange) || IndexInRange(rngEnd, group.VfRange)
×
440
}
441

442
func (p *SriovNetworkNodePolicy) generateVfGroup(iface *InterfaceExt) (*VfGroup, error) {
×
443
        var err error
×
444
        pfName := ""
×
445
        var rngStart, rngEnd int
×
446
        found := false
×
447
        for _, selector := range p.Spec.NicSelector.PfNames {
×
448
                pfName, rngStart, rngEnd, err = ParsePFName(selector)
×
449
                if err != nil {
×
450
                        log.Error(err, "Unable to parse PF Name.")
×
451
                        return nil, err
×
452
                }
×
453
                if pfName == iface.Name {
×
454
                        found = true
×
455
                        if rngStart == invalidVfIndex && rngEnd == invalidVfIndex {
×
456
                                rngStart, rngEnd = 0, p.Spec.NumVfs-1
×
457
                        }
×
458
                        break
×
459
                }
460
        }
461
        if !found {
×
462
                // assign the default vf index range if the pfName is not specified by the nicSelector
×
463
                rngStart, rngEnd = 0, p.Spec.NumVfs-1
×
464
        }
×
465
        rng := strconv.Itoa(rngStart) + "-" + strconv.Itoa(rngEnd)
×
466
        return &VfGroup{
×
467
                ResourceName: p.Spec.ResourceName,
×
468
                DeviceType:   p.Spec.DeviceType,
×
469
                VfRange:      rng,
×
470
                PolicyName:   p.GetName(),
×
471
                Mtu:          p.Spec.Mtu,
×
472
                IsRdma:       p.Spec.IsRdma,
×
473
                VdpaType:     p.Spec.VdpaType,
×
474
        }, nil
×
475
}
476

477
func IndexInRange(i int, r string) bool {
1✔
478
        rngSt, rngEnd, err := parseRange(r)
1✔
479
        if err != nil {
1✔
480
                return false
×
481
        }
×
482
        if i <= rngEnd && i >= rngSt {
2✔
483
                return true
1✔
484
        }
1✔
485
        return false
×
486
}
487

488
func parseRange(r string) (rngSt, rngEnd int, err error) {
1✔
489
        rng := strings.Split(r, "-")
1✔
490
        rngSt, err = strconv.Atoi(rng[0])
1✔
491
        if err != nil {
1✔
492
                return
×
493
        }
×
494
        rngEnd, err = strconv.Atoi(rng[1])
1✔
495
        if err != nil {
1✔
496
                return
×
497
        }
×
498
        return
1✔
499
}
500

501
// Parse PF name with VF range
502
func ParsePFName(name string) (ifName string, rngSt, rngEnd int, err error) {
1✔
503
        rngSt, rngEnd = invalidVfIndex, invalidVfIndex
1✔
504
        if strings.Contains(name, "#") {
2✔
505
                fields := strings.Split(name, "#")
1✔
506
                ifName = fields[0]
1✔
507
                rngSt, rngEnd, err = parseRange(fields[1])
1✔
508
        } else {
1✔
509
                ifName = name
×
510
        }
×
511
        return
1✔
512
}
513

514
func (selector *SriovNetworkNicSelector) Selected(iface *InterfaceExt) bool {
×
515
        if selector.Vendor != "" && selector.Vendor != iface.Vendor {
×
516
                return false
×
517
        }
×
518
        if selector.DeviceID != "" && selector.DeviceID != iface.DeviceID {
×
519
                return false
×
520
        }
×
521
        if len(selector.RootDevices) > 0 && !StringInArray(iface.PciAddress, selector.RootDevices) {
×
522
                return false
×
523
        }
×
524
        if len(selector.PfNames) > 0 {
×
525
                var pfNames []string
×
526
                for _, p := range selector.PfNames {
×
527
                        if strings.Contains(p, "#") {
×
528
                                fields := strings.Split(p, "#")
×
529
                                pfNames = append(pfNames, fields[0])
×
530
                        } else {
×
531
                                pfNames = append(pfNames, p)
×
532
                        }
×
533
                }
534
                if !StringInArray(iface.Name, pfNames) {
×
535
                        return false
×
536
                }
×
537
        }
538
        if selector.NetFilter != "" && !NetFilterMatch(selector.NetFilter, iface.NetFilter) {
×
539
                return false
×
540
        }
×
541

542
        return true
×
543
}
544

545
func (s *SriovNetworkNodeState) GetInterfaceStateByPciAddress(addr string) *InterfaceExt {
×
546
        for _, iface := range s.Status.Interfaces {
×
547
                if addr == iface.PciAddress {
×
548
                        return &iface
×
549
                }
×
550
        }
551
        return nil
×
552
}
553

554
func (s *SriovNetworkNodeState) GetDriverByPciAddress(addr string) string {
×
555
        for _, iface := range s.Status.Interfaces {
×
556
                if addr == iface.PciAddress {
×
557
                        return iface.Driver
×
558
                }
×
559
        }
560
        return ""
×
561
}
562

563
// RenderNetAttDef renders a net-att-def for ib-sriov CNI
564
func (cr *SriovIBNetwork) RenderNetAttDef() (*uns.Unstructured, error) {
1✔
565
        logger := log.WithName("RenderNetAttDef")
1✔
566
        logger.Info("Start to render IB SRIOV CNI NetworkAttachmentDefinition")
1✔
567

1✔
568
        // render RawCNIConfig manifests
1✔
569
        data := render.MakeRenderData()
1✔
570
        data.Data["CniType"] = "ib-sriov"
1✔
571
        data.Data["SriovNetworkName"] = cr.Name
1✔
572
        if cr.Spec.NetworkNamespace == "" {
2✔
573
                data.Data["SriovNetworkNamespace"] = cr.Namespace
1✔
574
        } else {
2✔
575
                data.Data["SriovNetworkNamespace"] = cr.Spec.NetworkNamespace
1✔
576
        }
1✔
577
        data.Data["SriovCniResourceName"] = os.Getenv("RESOURCE_PREFIX") + "/" + cr.Spec.ResourceName
1✔
578

1✔
579
        data.Data["StateConfigured"] = true
1✔
580
        switch cr.Spec.LinkState {
1✔
581
        case SriovCniStateEnable:
1✔
582
                data.Data["SriovCniState"] = SriovCniStateEnable
1✔
583
        case SriovCniStateDisable:
×
584
                data.Data["SriovCniState"] = SriovCniStateDisable
×
585
        case SriovCniStateAuto:
×
586
                data.Data["SriovCniState"] = SriovCniStateAuto
×
587
        default:
1✔
588
                data.Data["StateConfigured"] = false
1✔
589
        }
590

591
        if cr.Spec.Capabilities == "" {
2✔
592
                data.Data["CapabilitiesConfigured"] = false
1✔
593
        } else {
1✔
594
                data.Data["CapabilitiesConfigured"] = true
×
595
                data.Data["SriovCniCapabilities"] = cr.Spec.Capabilities
×
596
        }
×
597

598
        if cr.Spec.IPAM != "" {
2✔
599
                data.Data["SriovCniIpam"] = SriovCniIpam + ":" + strings.Join(strings.Fields(cr.Spec.IPAM), "")
1✔
600
        } else {
2✔
601
                data.Data["SriovCniIpam"] = SriovCniIpamEmpty
1✔
602
        }
1✔
603

604
        // metaplugins for the infiniband cni
605
        data.Data["MetaPluginsConfigured"] = false
1✔
606
        if cr.Spec.MetaPluginsConfig != "" {
1✔
607
                data.Data["MetaPluginsConfigured"] = true
×
608
                data.Data["MetaPlugins"] = cr.Spec.MetaPluginsConfig
×
609
        }
×
610

611
        // logLevel and logFile are currently not supports by the ip-sriov-cni -> hardcode them to false.
612
        data.Data["LogLevelConfigured"] = false
1✔
613
        data.Data["LogFileConfigured"] = false
1✔
614

1✔
615
        objs, err := render.RenderDir(ManifestsPath, &data)
1✔
616
        if err != nil {
1✔
617
                return nil, err
×
618
        }
×
619
        for _, obj := range objs {
2✔
620
                raw, _ := json.Marshal(obj)
1✔
621
                logger.Info("render NetworkAttachmentDefinition output", "raw", string(raw))
1✔
622
        }
1✔
623
        return objs[0], nil
1✔
624
}
625

626
// DeleteNetAttDef deletes the generated net-att-def CR
627
func (cr *SriovIBNetwork) DeleteNetAttDef(c client.Client) error {
1✔
628
        // Fetch the NetworkAttachmentDefinition instance
1✔
629
        instance := &netattdefv1.NetworkAttachmentDefinition{}
1✔
630
        namespace := cr.GetNamespace()
1✔
631
        if cr.Spec.NetworkNamespace != "" {
2✔
632
                namespace = cr.Spec.NetworkNamespace
1✔
633
        }
1✔
634
        err := c.Get(context.TODO(), types.NamespacedName{Namespace: namespace, Name: cr.GetName()}, instance)
1✔
635
        if err != nil {
2✔
636
                if errors.IsNotFound(err) {
2✔
637
                        return nil
1✔
638
                }
1✔
639
                return err
×
640
        }
641
        err = c.Delete(context.TODO(), instance)
1✔
642
        if err != nil {
1✔
643
                return err
×
644
        }
×
645
        return nil
1✔
646
}
647

648
// RenderNetAttDef renders a net-att-def for sriov CNI
649
func (cr *SriovNetwork) RenderNetAttDef() (*uns.Unstructured, error) {
1✔
650
        logger := log.WithName("RenderNetAttDef")
1✔
651
        logger.Info("Start to render SRIOV CNI NetworkAttachmentDefinition")
1✔
652

1✔
653
        // render RawCNIConfig manifests
1✔
654
        data := render.MakeRenderData()
1✔
655
        data.Data["CniType"] = "sriov"
1✔
656
        data.Data["SriovNetworkName"] = cr.Name
1✔
657
        if cr.Spec.NetworkNamespace == "" {
2✔
658
                data.Data["SriovNetworkNamespace"] = cr.Namespace
1✔
659
        } else {
2✔
660
                data.Data["SriovNetworkNamespace"] = cr.Spec.NetworkNamespace
1✔
661
        }
1✔
662
        data.Data["SriovCniResourceName"] = os.Getenv("RESOURCE_PREFIX") + "/" + cr.Spec.ResourceName
1✔
663
        data.Data["SriovCniVlan"] = cr.Spec.Vlan
1✔
664

1✔
665
        if cr.Spec.VlanQoS <= 7 && cr.Spec.VlanQoS >= 0 {
2✔
666
                data.Data["VlanQoSConfigured"] = true
1✔
667
                data.Data["SriovCniVlanQoS"] = cr.Spec.VlanQoS
1✔
668
        } else {
1✔
669
                data.Data["VlanQoSConfigured"] = false
×
670
        }
×
671

672
        data.Data["VlanProtoConfigured"] = false
1✔
673
        if cr.Spec.VlanProto != "" {
2✔
674
                data.Data["VlanProtoConfigured"] = true
1✔
675
                data.Data["SriovCniVlanProto"] = cr.Spec.VlanProto
1✔
676
        }
1✔
677

678
        if cr.Spec.Capabilities == "" {
2✔
679
                data.Data["CapabilitiesConfigured"] = false
1✔
680
        } else {
1✔
681
                data.Data["CapabilitiesConfigured"] = true
×
682
                data.Data["SriovCniCapabilities"] = cr.Spec.Capabilities
×
683
        }
×
684

685
        data.Data["SpoofChkConfigured"] = true
1✔
686
        switch cr.Spec.SpoofChk {
1✔
687
        case SriovCniStateOff:
×
688
                data.Data["SriovCniSpoofChk"] = SriovCniStateOff
×
689
        case SriovCniStateOn:
1✔
690
                data.Data["SriovCniSpoofChk"] = SriovCniStateOn
1✔
691
        default:
1✔
692
                data.Data["SpoofChkConfigured"] = false
1✔
693
        }
694

695
        data.Data["TrustConfigured"] = true
1✔
696
        switch cr.Spec.Trust {
1✔
697
        case SriovCniStateOn:
1✔
698
                data.Data["SriovCniTrust"] = SriovCniStateOn
1✔
699
        case SriovCniStateOff:
×
700
                data.Data["SriovCniTrust"] = SriovCniStateOff
×
701
        default:
1✔
702
                data.Data["TrustConfigured"] = false
1✔
703
        }
704

705
        data.Data["StateConfigured"] = true
1✔
706
        switch cr.Spec.LinkState {
1✔
707
        case SriovCniStateEnable:
×
708
                data.Data["SriovCniState"] = SriovCniStateEnable
×
709
        case SriovCniStateDisable:
×
710
                data.Data["SriovCniState"] = SriovCniStateDisable
×
711
        case SriovCniStateAuto:
×
712
                data.Data["SriovCniState"] = SriovCniStateAuto
×
713
        default:
1✔
714
                data.Data["StateConfigured"] = false
1✔
715
        }
716

717
        data.Data["MinTxRateConfigured"] = false
1✔
718
        if cr.Spec.MinTxRate != nil {
1✔
719
                if *cr.Spec.MinTxRate >= 0 {
×
720
                        data.Data["MinTxRateConfigured"] = true
×
721
                        data.Data["SriovCniMinTxRate"] = *cr.Spec.MinTxRate
×
722
                }
×
723
        }
724

725
        data.Data["MaxTxRateConfigured"] = false
1✔
726
        if cr.Spec.MaxTxRate != nil {
1✔
727
                if *cr.Spec.MaxTxRate >= 0 {
×
728
                        data.Data["MaxTxRateConfigured"] = true
×
729
                        data.Data["SriovCniMaxTxRate"] = *cr.Spec.MaxTxRate
×
730
                }
×
731
        }
732

733
        if cr.Spec.IPAM != "" {
2✔
734
                data.Data["SriovCniIpam"] = SriovCniIpam + ":" + strings.Join(strings.Fields(cr.Spec.IPAM), "")
1✔
735
        } else {
1✔
736
                data.Data["SriovCniIpam"] = SriovCniIpamEmpty
×
737
        }
×
738

739
        data.Data["MetaPluginsConfigured"] = false
1✔
740
        if cr.Spec.MetaPluginsConfig != "" {
1✔
741
                data.Data["MetaPluginsConfigured"] = true
×
742
                data.Data["MetaPlugins"] = cr.Spec.MetaPluginsConfig
×
743
        }
×
744

745
        data.Data["LogLevelConfigured"] = (cr.Spec.LogLevel != "")
1✔
746
        data.Data["LogLevel"] = cr.Spec.LogLevel
1✔
747
        data.Data["LogFileConfigured"] = (cr.Spec.LogFile != "")
1✔
748
        data.Data["LogFile"] = cr.Spec.LogFile
1✔
749

1✔
750
        objs, err := render.RenderDir(ManifestsPath, &data)
1✔
751
        if err != nil {
1✔
752
                return nil, err
×
753
        }
×
754
        for _, obj := range objs {
2✔
755
                raw, _ := json.Marshal(obj)
1✔
756
                logger.Info("render NetworkAttachmentDefinition output", "raw", string(raw))
1✔
757
        }
1✔
758
        return objs[0], nil
1✔
759
}
760

761
// DeleteNetAttDef deletes the generated net-att-def CR
762
func (cr *SriovNetwork) DeleteNetAttDef(c client.Client) error {
1✔
763
        // Fetch the NetworkAttachmentDefinition instance
1✔
764
        instance := &netattdefv1.NetworkAttachmentDefinition{}
1✔
765
        namespace := cr.GetNamespace()
1✔
766
        if cr.Spec.NetworkNamespace != "" {
2✔
767
                namespace = cr.Spec.NetworkNamespace
1✔
768
        }
1✔
769
        err := c.Get(context.TODO(), types.NamespacedName{Namespace: namespace, Name: cr.GetName()}, instance)
1✔
770
        if err != nil {
1✔
UNCOV
771
                if errors.IsNotFound(err) {
×
UNCOV
772
                        return nil
×
UNCOV
773
                }
×
774
                return err
×
775
        }
776
        err = c.Delete(context.TODO(), instance)
1✔
777
        if err != nil {
1✔
778
                return err
×
779
        }
×
780
        return nil
1✔
781
}
782

783
// NetFilterMatch -- parse netFilter and check for a match
784
func NetFilterMatch(netFilter string, netValue string) (isMatch bool) {
×
785
        logger := log.WithName("NetFilterMatch")
×
786

×
787
        var re = regexp.MustCompile(`(?m)^\s*([^\s]+)\s*:\s*([^\s]+)`)
×
788

×
789
        netFilterResult := re.FindAllStringSubmatch(netFilter, -1)
×
790

×
791
        if netFilterResult == nil {
×
792
                logger.Info("Invalid NetFilter spec...", "netFilter", netFilter)
×
793
                return false
×
794
        }
×
795

796
        netValueResult := re.FindAllStringSubmatch(netValue, -1)
×
797

×
798
        if netValueResult == nil {
×
799
                logger.Info("Invalid netValue...", "netValue", netValue)
×
800
                return false
×
801
        }
×
802

803
        return netFilterResult[0][1] == netValueResult[0][1] && netFilterResult[0][2] == netValueResult[0][2]
×
804
}
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

© 2025 Coveralls, Inc