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

k8snetworkplumbingwg / sriov-network-operator / 14307506029

07 Apr 2025 11:01AM UTC coverage: 61.542% (+13.0%) from 48.541%
14307506029

push

github

web-flow
Merge pull request #870 from SchSeba/remove_client

Remove auto generated client

37 of 76 new or added lines in 9 files covered. (48.68%)

523 existing lines in 19 files now uncovered.

8491 of 13797 relevant lines covered (61.54%)

0.68 hits per line

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

83.5
/pkg/plugins/virtual/virtual_plugin.go
1
package virtual
2

3
import (
4
        "reflect"
5

6
        "sigs.k8s.io/controller-runtime/pkg/log"
7

8
        sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1"
9
        consts "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts"
10
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/helper"
11
        plugin "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/plugins"
12
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars"
13
)
14

15
var PluginName = "virtual"
16

17
// VirtualPlugin Plugin type to use on a virtual platform
18
type VirtualPlugin struct {
19
        PluginName     string
20
        SpecVersion    string
21
        DesireState    *sriovnetworkv1.SriovNetworkNodeState
22
        LastState      *sriovnetworkv1.SriovNetworkNodeState
23
        LoadVfioDriver uint
24
        helpers        helper.HostHelpersInterface
25
}
26

27
const (
28
        unloaded = iota
29
        loading
30
        loaded
31
)
32

33
// Initialize our plugin and set up initial values
34
func NewVirtualPlugin(helper helper.HostHelpersInterface) (plugin.VendorPlugin, error) {
1✔
35
        return &VirtualPlugin{
1✔
36
                PluginName:     PluginName,
1✔
37
                LoadVfioDriver: unloaded,
1✔
38
                helpers:        helper,
1✔
39
        }, nil
1✔
40
}
1✔
41

42
// Name returns the name of the plugin
43
func (p *VirtualPlugin) Name() string {
1✔
44
        return p.PluginName
1✔
45
}
1✔
46

47
// OnNodeStateChange Invoked when SriovNetworkNodeState CR is created or updated, return if need dain and/or reboot node
48
func (p *VirtualPlugin) OnNodeStateChange(new *sriovnetworkv1.SriovNetworkNodeState) (needDrain bool, needReboot bool, err error) {
1✔
49
        log.Log.Info("virtual plugin OnNodeStateChange()")
1✔
50
        needDrain = false
1✔
51
        needReboot = false
1✔
52
        err = nil
1✔
53
        p.DesireState = new
1✔
54

1✔
55
        if p.LoadVfioDriver != loaded {
2✔
56
                if needVfioDriver(new) {
2✔
57
                        p.LoadVfioDriver = loading
1✔
58
                }
1✔
59
        }
60

61
        return
1✔
62
}
63

64
// OnNodeStatusChange verify whether SriovNetworkNodeState CR status present changes on configured VFs.
65
func (p *VirtualPlugin) CheckStatusChanges(*sriovnetworkv1.SriovNetworkNodeState) (bool, error) {
1✔
66
        return false, nil
1✔
67
}
1✔
68

69
// Apply config change
70
func (p *VirtualPlugin) Apply() error {
1✔
71
        log.Log.Info("virtual plugin Apply()", "desired-state", p.DesireState.Spec)
1✔
72

1✔
73
        if p.LoadVfioDriver == loading {
2✔
74
                // In virtual deployments of Kubernetes where the underlying virtualization platform does not support a virtualized iommu
1✔
75
                // the VFIO PCI driver needs to be loaded with a special flag.
1✔
76
                // This is the case for OpenStack deployments where the underlying virtualization platform is KVM.
1✔
77
                // NOTE: if VFIO was already loaded for some reason, we will not try to load it again with the new options.
1✔
78
                kernelArgs := "enable_unsafe_noiommu_mode=1"
1✔
79
                if err := p.helpers.LoadKernelModule("vfio", kernelArgs); err != nil {
2✔
80
                        log.Log.Error(err, "virtual plugin Apply(): fail to load vfio kmod")
1✔
81
                        return err
1✔
82
                }
1✔
83

84
                if err := p.helpers.LoadKernelModule("vfio_pci"); err != nil {
2✔
85
                        log.Log.Error(err, "virtual plugin Apply(): fail to load vfio_pci kmod")
1✔
86
                        return err
1✔
87
                }
1✔
88
                p.LoadVfioDriver = loaded
1✔
89
        }
90

91
        if p.LastState != nil {
2✔
92
                log.Log.Info("virtual plugin Apply()", "last-state", p.LastState.Spec)
1✔
93
                if reflect.DeepEqual(p.LastState.Spec.Interfaces, p.DesireState.Spec.Interfaces) {
2✔
94
                        log.Log.Info("virtual plugin Apply(): nothing to apply")
1✔
95
                        return nil
1✔
96
                }
1✔
97
        }
98
        exit, err := p.helpers.Chroot(consts.Host)
1✔
99
        if err != nil {
1✔
100
                return err
×
101
        }
×
102
        defer exit()
1✔
103
        if err := syncNodeStateVirtual(p.DesireState, p.helpers); err != nil {
1✔
104
                return err
×
105
        }
×
106
        p.LastState = &sriovnetworkv1.SriovNetworkNodeState{}
1✔
107
        *p.LastState = *p.DesireState
1✔
108

1✔
109
        return nil
1✔
110
}
111

112
func needVfioDriver(state *sriovnetworkv1.SriovNetworkNodeState) bool {
1✔
113
        for _, iface := range state.Spec.Interfaces {
2✔
114
                for i := range iface.VfGroups {
2✔
115
                        if iface.VfGroups[i].DeviceType == consts.DeviceTypeVfioPci {
2✔
116
                                return true
1✔
117
                        }
1✔
118
                }
119
        }
120
        return false
1✔
121
}
122

123
// syncNodeStateVirtual attempt to update the node state to match the desired state in virtual platforms
124
func syncNodeStateVirtual(newState *sriovnetworkv1.SriovNetworkNodeState, helpers helper.HostHelpersInterface) error {
1✔
125
        var err error
1✔
126
        for _, ifaceStatus := range newState.Status.Interfaces {
2✔
127
                for _, iface := range newState.Spec.Interfaces {
2✔
128
                        if iface.PciAddress == ifaceStatus.PciAddress {
2✔
129
                                if !needUpdateVirtual(&iface, &ifaceStatus) {
1✔
130
                                        log.Log.V(2).Info("syncNodeStateVirtual(): no need update interface", "address", iface.PciAddress)
×
UNCOV
131
                                        break
×
132
                                }
133
                                if err = helpers.ConfigSriovDeviceVirtual(&iface); err != nil {
1✔
UNCOV
134
                                        log.Log.Error(err, "syncNodeStateVirtual(): fail to config sriov interface", "address", iface.PciAddress)
×
UNCOV
135
                                        return err
×
UNCOV
136
                                }
×
137
                                break
1✔
138
                        }
139
                }
140
        }
141
        return nil
1✔
142
}
143

144
func needUpdateVirtual(iface *sriovnetworkv1.Interface, ifaceStatus *sriovnetworkv1.InterfaceExt) bool {
1✔
145
        // The device MTU is set by the platform
1✔
146
        // The NumVfs is always 1
1✔
147
        if iface.NumVfs > 0 {
2✔
148
                for _, vf := range ifaceStatus.VFs {
2✔
149
                        for _, group := range iface.VfGroups {
2✔
150
                                if sriovnetworkv1.IndexInRange(vf.VfID, group.VfRange) {
2✔
151
                                        if group.DeviceType != consts.DeviceTypeNetDevice {
2✔
152
                                                if group.DeviceType != vf.Driver {
2✔
153
                                                        log.Log.V(2).Info("needUpdateVirtual(): Driver needs update",
1✔
154
                                                                "desired", group.DeviceType, "current", vf.Driver)
1✔
155
                                                        return true
1✔
156
                                                }
1✔
157
                                        } else {
×
158
                                                if sriovnetworkv1.StringInArray(vf.Driver, vars.DpdkDrivers) {
×
159
                                                        log.Log.V(2).Info("needUpdateVirtual(): Driver needs update",
×
160
                                                                "desired", group.DeviceType, "current", vf.Driver)
×
161
                                                        return true
×
162
                                                }
×
163
                                        }
164
                                        break
×
165
                                }
166
                        }
167
                }
168
        }
169
        return false
×
170
}
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