1 package netlink
2
3 import (
4 "errors"
5 "syscall"
6 "testing"
7
8 "github.com/vishvananda/netlink/nl"
9 )
10
11
12
13
14 const (
15 vdpaSimMGMTDev = "vdpasim_net"
16 vdpaTestDeviceName = "__nl_test_dev"
17 )
18
19 var (
20 vdapTestReqModules = []string{"vdpa", "vdpa_sim", "vdpa_sim_net"}
21 )
22
23 func setupVDPATest(t *testing.T, reqCommands ...int) func() {
24 t.Helper()
25 skipUnlessRoot(t)
26 skipUnlessKModuleLoaded(t, vdapTestReqModules...)
27 gFam, err := GenlFamilyGet(nl.VDPA_GENL_NAME)
28 if err != nil {
29 t.Skip("can't check for supported VDPA commands")
30 }
31 for _, c := range reqCommands {
32 found := false
33 for _, supportedOpt := range gFam.Ops {
34 if supportedOpt.ID == uint32(c) {
35 found = true
36 }
37 }
38 if !found {
39 t.Skip("host doesn't support required VDPA command for the test")
40 }
41 }
42 return func() {
43 _ = VDPADelDev(vdpaTestDeviceName)
44 }
45 }
46
47 func TestVDPAGetMGMTDevList(t *testing.T) {
48 defer setupVDPATest(t, nl.VDPA_CMD_MGMTDEV_GET)()
49 mgmtDevs, err := VDPAGetMGMTDevList()
50 if err != nil {
51 t.Fatalf("Failed to list VDPA mgmt devs: %v", err)
52 }
53 simMGMTFound := false
54 for _, d := range mgmtDevs {
55 if d.DevName != vdpaSimMGMTDev || d.BusName != "" {
56 continue
57 }
58 simMGMTFound = true
59 checkVDPAMGMTDev(t, d)
60 }
61 if !simMGMTFound {
62 t.Fatal("VDPA vdpasim_net MGMT device not found")
63 }
64 }
65
66 func TestVDPAGetMGMTDevByBusAndName(t *testing.T) {
67 defer setupVDPATest(t, nl.VDPA_CMD_MGMTDEV_GET)()
68 mgmtDev, err := VDPAGetMGMTDevByBusAndName("", vdpaSimMGMTDev)
69 if err != nil {
70 t.Fatalf("Failed to get VDPA sim mgmt dev: %v", err)
71 }
72 checkVDPAMGMTDev(t, mgmtDev)
73 if mgmtDev.DevName != vdpaSimMGMTDev || mgmtDev.BusName != "" {
74 t.Fatalf("Invalid device received for Get call, expected: %s, actual: %s", vdpaSimMGMTDev, mgmtDev.DevName)
75 }
76 }
77
78 func TestVDPAGetMGMTDevByBusAndName_Unknown_Device(t *testing.T) {
79 defer setupVDPATest(t, nl.VDPA_CMD_MGMTDEV_GET)()
80 _, err := VDPAGetMGMTDevByBusAndName("pci", "__should_not_exist")
81 if !errors.Is(err, syscall.ENODEV) {
82 t.Fatal("VDPAGetMGMTDevByBusAndName returns unexpected error for unknown device")
83 }
84 }
85
86 func TestVDPANewDev(t *testing.T) {
87 defer setupVDPATest(t, nl.VDPA_CMD_DEV_GET, nl.VDPA_CMD_DEV_NEW)()
88 if err := createVDPATestDev(); err != nil {
89 t.Fatalf("failed to create VDPA device: %v", err)
90 }
91 _, err := VDPAGetDevByName(vdpaTestDeviceName)
92 if err != nil {
93 t.Fatalf("failed to get created VDPA devvice: %v", err)
94 }
95 }
96
97 func TestVDPANewDev_Already_Exist(t *testing.T) {
98 defer setupVDPATest(t, nl.VDPA_CMD_DEV_GET, nl.VDPA_CMD_DEV_NEW)()
99 if err := createVDPATestDev(); err != nil {
100 t.Fatalf("failed to create VDPA device: %v", err)
101 }
102 err := createVDPATestDev()
103 if !errors.Is(err, syscall.EEXIST) {
104 t.Fatal("VDPANewDev returns unexpected error for device which is already exist")
105 }
106 }
107
108 func TestVDPANewDev_Unknown_MGMT_DEV(t *testing.T) {
109 defer setupVDPATest(t, nl.VDPA_CMD_DEV_GET, nl.VDPA_CMD_DEV_NEW)()
110 err := VDPANewDev(vdpaTestDeviceName, "", "__should_not_exist", VDPANewDevParams{})
111 if !errors.Is(err, syscall.ENODEV) {
112 t.Fatal("VDPANewDev returns unexpected error for unknown mgmt device")
113 }
114 }
115
116 func TestVDPADelDev(t *testing.T) {
117 defer setupVDPATest(t, nl.VDPA_CMD_DEV_DEL, nl.VDPA_CMD_DEV_NEW)()
118 defer setupVDPATest(t)()
119 if err := createVDPATestDev(); err != nil {
120 t.Fatalf("failed to create VDPA device: %v", err)
121 }
122 if err := VDPADelDev(vdpaTestDeviceName); err != nil {
123 t.Fatalf("VDPADelDev failed: %v", err)
124 }
125 }
126
127 func TestVDPADelDev_Unknown_Device(t *testing.T) {
128 defer setupVDPATest(t, nl.VDPA_CMD_DEV_DEL)()
129 err := VDPADelDev("__should_not_exist")
130 if !errors.Is(err, syscall.ENODEV) {
131 t.Fatal("VDPADelDev returns unexpected error for unknown device")
132 }
133 }
134
135 func TestVDPAGetDevList(t *testing.T) {
136 defer setupVDPATest(t, nl.VDPA_CMD_DEV_GET, nl.VDPA_CMD_DEV_NEW)()
137 if err := createVDPATestDev(); err != nil {
138 t.Fatalf("failed to create VDPA device: %v", err)
139 }
140 devs, err := VDPAGetDevList()
141 if err != nil {
142 t.Fatalf("VDPAGetDevList failed: %v", err)
143 }
144 testDevFound := false
145 for _, d := range devs {
146 if d.Name != vdpaTestDeviceName {
147 continue
148 }
149 testDevFound = true
150 checkVDPADev(t, d)
151 }
152 if !testDevFound {
153 t.Fatal("VDPA test device not found")
154 }
155 }
156
157 func TestVDPAGetDevByName(t *testing.T) {
158 defer setupVDPATest(t, nl.VDPA_CMD_DEV_GET, nl.VDPA_CMD_DEV_NEW)()
159 if err := createVDPATestDev(); err != nil {
160 t.Fatalf("failed to create VDPA device: %v", err)
161 }
162 dev, err := VDPAGetDevByName(vdpaTestDeviceName)
163 if err != nil {
164 t.Fatalf("VDPAGetDevByName failed: %v", err)
165 }
166 checkVDPADev(t, dev)
167 if dev.Name != vdpaTestDeviceName {
168 t.Fatalf("Invalid device received for Get call, expected: %s, actual: %s", vdpaTestDeviceName, dev.Name)
169 }
170 }
171
172 func TestVDPAGetDevByName_Unknown(t *testing.T) {
173 defer setupVDPATest(t, nl.VDPA_CMD_DEV_GET)()
174 _, err := VDPAGetDevByName("__should_not_exist")
175 if !errors.Is(err, syscall.ENODEV) {
176 t.Fatal("VDPAGetDevByName returns unexpected error for unknown device")
177 }
178 }
179
180 func TestVDPAGetDevConfigList(t *testing.T) {
181 defer setupVDPATest(t, nl.VDPA_CMD_DEV_GET, nl.VDPA_CMD_DEV_CONFIG_GET)()
182 if err := createVDPATestDev(); err != nil {
183 t.Fatalf("failed to create VDPA device: %v", err)
184 }
185 devConfs, err := VDPAGetDevConfigList()
186 if err != nil {
187 t.Fatalf("VDPAGetDevConfigList failed: %v", err)
188 }
189 testDevConfFound := false
190 for _, d := range devConfs {
191 if d.Name != vdpaTestDeviceName {
192 continue
193 }
194 testDevConfFound = true
195 checkVDPADevConf(t, d)
196 }
197 if !testDevConfFound {
198 t.Fatal("VDPA test device config not found")
199 }
200 }
201
202 func TestVDPAGetDevConfigByName(t *testing.T) {
203 defer setupVDPATest(t, nl.VDPA_CMD_DEV_GET, nl.VDPA_CMD_DEV_CONFIG_GET)()
204 if err := createVDPATestDev(); err != nil {
205 t.Fatalf("failed to create VDPA device: %v", err)
206 }
207 dev, err := VDPAGetDevConfigByName(vdpaTestDeviceName)
208 if err != nil {
209 t.Fatalf("VDPAGetDevConfigByName failed: %v", err)
210 }
211 checkVDPADevConf(t, dev)
212 if dev.Name != vdpaTestDeviceName {
213 t.Fatalf("Invalid device received for Get call, expected: %s, actual: %s", vdpaTestDeviceName, dev.Name)
214 }
215 }
216
217 func TestVDPAGetDevConfigByName_Unknowm(t *testing.T) {
218 defer setupVDPATest(t, nl.VDPA_CMD_DEV_GET, nl.VDPA_CMD_DEV_CONFIG_GET)()
219 _, err := VDPAGetDevConfigByName("__should_not_exist")
220 if !errors.Is(err, syscall.ENODEV) {
221 t.Fatal("VDPAGetDevConfigByName returns unexpected error for unknown device")
222 }
223 }
224
225 func TestSetGetBits(t *testing.T) {
226 features := SetBits(0, VIRTIO_NET_F_CSUM, VIRTIO_NET_F_MQ)
227 if !IsBitSet(features, VIRTIO_NET_F_CSUM) || !IsBitSet(features, VIRTIO_NET_F_MQ) {
228 t.Fatal("BitSet test failed")
229 }
230 if IsBitSet(features, VIRTIO_NET_F_STATUS) {
231 t.Fatal("unexpected bit is set")
232 }
233 }
234
235 func createVDPATestDev() error {
236 return VDPANewDev(vdpaTestDeviceName, "", vdpaSimMGMTDev, VDPANewDevParams{})
237 }
238
239 func checkVDPAMGMTDev(t *testing.T, d *VDPAMGMTDev) {
240 if d == nil {
241 t.Fatal("VDPA MGMT dev is nil")
242 }
243 if d.DevName == "" {
244 t.Fatal("VDPA MGMT dev name is not set")
245 }
246 }
247
248 func checkVDPADev(t *testing.T, d *VDPADev) {
249 if d == nil {
250 t.Fatal("VDPA dev is nil")
251 }
252 if d.Name == "" {
253 t.Fatal("VDPA dev name is not set")
254 }
255 if d.ID == 0 {
256 t.Fatal("VDPA dev ID is not set")
257 }
258 }
259
260 func checkVDPADevConf(t *testing.T, d *VDPADevConfig) {
261 if d == nil {
262 t.Fatal("VDPA dev config is nil")
263 }
264 if d.Name == "" {
265 t.Fatal("VDPA dev name is not set")
266 }
267 if d.ID == 0 {
268 t.Fatal("VDPA dev ID is not set")
269 }
270 }
271
View as plain text