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

k8snetworkplumbingwg / sriov-network-operator / 19227470377

10 Nov 2025 09:48AM UTC coverage: 62.151% (-0.2%) from 62.366%
19227470377

Pull #902

github

web-flow
Merge f9637c189 into 3d1a472a6
Pull Request #902: Create platform and orchestrator packages

319 of 659 new or added lines in 25 files covered. (48.41%)

41 existing lines in 9 files now uncovered.

8772 of 14114 relevant lines covered (62.15%)

0.69 hits per line

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

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

3
import (
4
        "k8s.io/apimachinery/pkg/api/equality"
5
        "sigs.k8s.io/controller-runtime/pkg/log"
6

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

14
var PluginName = "virtual"
15

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

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

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

41
// Name returns the name of the plugin
UNCOV
42
func (p *VirtualPlugin) Name() string {
×
UNCOV
43
        return p.PluginName
×
UNCOV
44
}
×
45

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

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

60
        return
1✔
61
}
62

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

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

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

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

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

1✔
108
        return nil
1✔
109
}
110

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

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

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