1 package netlink
2
3 import (
4 "fmt"
5 "net"
6 "syscall"
7
8 "golang.org/x/sys/unix"
9
10 "github.com/vishvananda/netlink/nl"
11 )
12
13 type vdpaDevID struct {
14 Name string
15 ID uint32
16 }
17
18
19 type VDPADev struct {
20 vdpaDevID
21 VendorID uint32
22 MaxVQS uint32
23 MaxVQSize uint16
24 MinVQSize uint16
25 }
26
27
28 type VDPADevConfig struct {
29 vdpaDevID
30 Features uint64
31 NegotiatedFeatures uint64
32 Net VDPADevConfigNet
33 }
34
35
36 type VDPADevVStats struct {
37 vdpaDevID
38 QueueIndex uint32
39 Vendor []VDPADevVStatsVendor
40 NegotiatedFeatures uint64
41 }
42
43
44 type VDPADevVStatsVendor struct {
45 Name string
46 Value uint64
47 }
48
49
50 type VDPADevConfigNet struct {
51 Status VDPADevConfigNetStatus
52 Cfg VDPADevConfigNetCfg
53 }
54
55
56 type VDPADevConfigNetStatus struct {
57 LinkUp bool
58 Announce bool
59 }
60
61
62 type VDPADevConfigNetCfg struct {
63 MACAddr net.HardwareAddr
64 MaxVQP uint16
65 MTU uint16
66 }
67
68
69 type VDPAMGMTDev struct {
70 BusName string
71 DevName string
72 SupportedClasses uint64
73 SupportedFeatures uint64
74 MaxVQS uint32
75 }
76
77
78
79
80
81
82 type VDPANewDevParams struct {
83 MACAddr net.HardwareAddr
84 MaxVQP uint16
85 MTU uint16
86 Features uint64
87 }
88
89
90
91
92 func SetBits(input uint64, pos ...int) uint64 {
93 for _, p := range pos {
94 input |= 1 << uint64(p)
95 }
96 return input
97 }
98
99
100
101
102 func IsBitSet(input uint64, pos int) bool {
103 val := input & (1 << uint64(pos))
104 return val > 0
105 }
106
107
108
109 func VDPANewDev(name, mgmtBus, mgmtName string, params VDPANewDevParams) error {
110 return pkgHandle.VDPANewDev(name, mgmtBus, mgmtName, params)
111 }
112
113
114
115 func VDPADelDev(name string) error {
116 return pkgHandle.VDPADelDev(name)
117 }
118
119
120
121 func VDPAGetDevList() ([]*VDPADev, error) {
122 return pkgHandle.VDPAGetDevList()
123 }
124
125
126
127 func VDPAGetDevByName(name string) (*VDPADev, error) {
128 return pkgHandle.VDPAGetDevByName(name)
129 }
130
131
132
133 func VDPAGetDevConfigList() ([]*VDPADevConfig, error) {
134 return pkgHandle.VDPAGetDevConfigList()
135 }
136
137
138
139 func VDPAGetDevConfigByName(name string) (*VDPADevConfig, error) {
140 return pkgHandle.VDPAGetDevConfigByName(name)
141 }
142
143
144
145 func VDPAGetDevVStats(name string, queueIndex uint32) (*VDPADevVStats, error) {
146 return pkgHandle.VDPAGetDevVStats(name, queueIndex)
147 }
148
149
150
151 func VDPAGetMGMTDevList() ([]*VDPAMGMTDev, error) {
152 return pkgHandle.VDPAGetMGMTDevList()
153 }
154
155
156
157 func VDPAGetMGMTDevByBusAndName(bus, name string) (*VDPAMGMTDev, error) {
158 return pkgHandle.VDPAGetMGMTDevByBusAndName(bus, name)
159 }
160
161 type vdpaNetlinkMessage []syscall.NetlinkRouteAttr
162
163 func (id *vdpaDevID) parseIDAttribute(attr syscall.NetlinkRouteAttr) {
164 switch attr.Attr.Type {
165 case nl.VDPA_ATTR_DEV_NAME:
166 id.Name = nl.BytesToString(attr.Value)
167 case nl.VDPA_ATTR_DEV_ID:
168 id.ID = native.Uint32(attr.Value)
169 }
170 }
171
172 func (netStatus *VDPADevConfigNetStatus) parseStatusAttribute(value []byte) {
173 a := native.Uint16(value)
174 netStatus.Announce = (a & VIRTIO_NET_S_ANNOUNCE) > 0
175 netStatus.LinkUp = (a & VIRTIO_NET_S_LINK_UP) > 0
176 }
177
178 func (d *VDPADev) parseAttributes(attrs vdpaNetlinkMessage) {
179 for _, a := range attrs {
180 d.parseIDAttribute(a)
181 switch a.Attr.Type {
182 case nl.VDPA_ATTR_DEV_VENDOR_ID:
183 d.VendorID = native.Uint32(a.Value)
184 case nl.VDPA_ATTR_DEV_MAX_VQS:
185 d.MaxVQS = native.Uint32(a.Value)
186 case nl.VDPA_ATTR_DEV_MAX_VQ_SIZE:
187 d.MaxVQSize = native.Uint16(a.Value)
188 case nl.VDPA_ATTR_DEV_MIN_VQ_SIZE:
189 d.MinVQSize = native.Uint16(a.Value)
190 }
191 }
192 }
193
194 func (c *VDPADevConfig) parseAttributes(attrs vdpaNetlinkMessage) {
195 for _, a := range attrs {
196 c.parseIDAttribute(a)
197 switch a.Attr.Type {
198 case nl.VDPA_ATTR_DEV_NET_CFG_MACADDR:
199 c.Net.Cfg.MACAddr = a.Value
200 case nl.VDPA_ATTR_DEV_NET_STATUS:
201 c.Net.Status.parseStatusAttribute(a.Value)
202 case nl.VDPA_ATTR_DEV_NET_CFG_MAX_VQP:
203 c.Net.Cfg.MaxVQP = native.Uint16(a.Value)
204 case nl.VDPA_ATTR_DEV_NET_CFG_MTU:
205 c.Net.Cfg.MTU = native.Uint16(a.Value)
206 case nl.VDPA_ATTR_DEV_FEATURES:
207 c.Features = native.Uint64(a.Value)
208 case nl.VDPA_ATTR_DEV_NEGOTIATED_FEATURES:
209 c.NegotiatedFeatures = native.Uint64(a.Value)
210 }
211 }
212 }
213
214 func (s *VDPADevVStats) parseAttributes(attrs vdpaNetlinkMessage) {
215 for _, a := range attrs {
216 s.parseIDAttribute(a)
217 switch a.Attr.Type {
218 case nl.VDPA_ATTR_DEV_QUEUE_INDEX:
219 s.QueueIndex = native.Uint32(a.Value)
220 case nl.VDPA_ATTR_DEV_VENDOR_ATTR_NAME:
221 s.Vendor = append(s.Vendor, VDPADevVStatsVendor{Name: nl.BytesToString(a.Value)})
222 case nl.VDPA_ATTR_DEV_VENDOR_ATTR_VALUE:
223 if len(s.Vendor) == 0 {
224 break
225 }
226 s.Vendor[len(s.Vendor)-1].Value = native.Uint64(a.Value)
227 case nl.VDPA_ATTR_DEV_NEGOTIATED_FEATURES:
228 s.NegotiatedFeatures = native.Uint64(a.Value)
229 }
230 }
231 }
232
233 func (d *VDPAMGMTDev) parseAttributes(attrs vdpaNetlinkMessage) {
234 for _, a := range attrs {
235 switch a.Attr.Type {
236 case nl.VDPA_ATTR_MGMTDEV_BUS_NAME:
237 d.BusName = nl.BytesToString(a.Value)
238 case nl.VDPA_ATTR_MGMTDEV_DEV_NAME:
239 d.DevName = nl.BytesToString(a.Value)
240 case nl.VDPA_ATTR_MGMTDEV_SUPPORTED_CLASSES:
241 d.SupportedClasses = native.Uint64(a.Value)
242 case nl.VDPA_ATTR_DEV_SUPPORTED_FEATURES:
243 d.SupportedFeatures = native.Uint64(a.Value)
244 case nl.VDPA_ATTR_DEV_MGMTDEV_MAX_VQS:
245 d.MaxVQS = native.Uint32(a.Value)
246 }
247 }
248 }
249
250 func (h *Handle) vdpaRequest(command uint8, extraFlags int, attrs []*nl.RtAttr) ([]vdpaNetlinkMessage, error) {
251 f, err := h.GenlFamilyGet(nl.VDPA_GENL_NAME)
252 if err != nil {
253 return nil, err
254 }
255 req := h.newNetlinkRequest(int(f.ID), unix.NLM_F_ACK|extraFlags)
256 req.AddData(&nl.Genlmsg{
257 Command: command,
258 Version: nl.VDPA_GENL_VERSION,
259 })
260 for _, a := range attrs {
261 req.AddData(a)
262 }
263
264 resp, err := req.Execute(unix.NETLINK_GENERIC, 0)
265 if err != nil {
266 return nil, err
267 }
268 messages := make([]vdpaNetlinkMessage, 0, len(resp))
269 for _, m := range resp {
270 attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:])
271 if err != nil {
272 return nil, err
273 }
274 messages = append(messages, attrs)
275 }
276 return messages, nil
277 }
278
279
280 func (h *Handle) vdpaDevGet(dev *string) ([]*VDPADev, error) {
281 var extraFlags int
282 var attrs []*nl.RtAttr
283 if dev != nil {
284 attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_NAME, nl.ZeroTerminated(*dev)))
285 } else {
286 extraFlags = extraFlags | unix.NLM_F_DUMP
287 }
288 messages, err := h.vdpaRequest(nl.VDPA_CMD_DEV_GET, extraFlags, attrs)
289 if err != nil {
290 return nil, err
291 }
292 devs := make([]*VDPADev, 0, len(messages))
293 for _, m := range messages {
294 d := &VDPADev{}
295 d.parseAttributes(m)
296 devs = append(devs, d)
297 }
298 return devs, nil
299 }
300
301
302 func (h *Handle) vdpaDevConfigGet(dev *string) ([]*VDPADevConfig, error) {
303 var extraFlags int
304 var attrs []*nl.RtAttr
305 if dev != nil {
306 attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_NAME, nl.ZeroTerminated(*dev)))
307 } else {
308 extraFlags = extraFlags | unix.NLM_F_DUMP
309 }
310 messages, err := h.vdpaRequest(nl.VDPA_CMD_DEV_CONFIG_GET, extraFlags, attrs)
311 if err != nil {
312 return nil, err
313 }
314 cfgs := make([]*VDPADevConfig, 0, len(messages))
315 for _, m := range messages {
316 cfg := &VDPADevConfig{}
317 cfg.parseAttributes(m)
318 cfgs = append(cfgs, cfg)
319 }
320 return cfgs, nil
321 }
322
323
324 func (h *Handle) vdpaMGMTDevGet(bus, dev *string) ([]*VDPAMGMTDev, error) {
325 var extraFlags int
326 var attrs []*nl.RtAttr
327 if dev != nil {
328 attrs = append(attrs,
329 nl.NewRtAttr(nl.VDPA_ATTR_MGMTDEV_DEV_NAME, nl.ZeroTerminated(*dev)),
330 )
331 if bus != nil {
332 attrs = append(attrs,
333 nl.NewRtAttr(nl.VDPA_ATTR_MGMTDEV_BUS_NAME, nl.ZeroTerminated(*bus)),
334 )
335 }
336 } else {
337 extraFlags = extraFlags | unix.NLM_F_DUMP
338 }
339 messages, err := h.vdpaRequest(nl.VDPA_CMD_MGMTDEV_GET, extraFlags, attrs)
340 if err != nil {
341 return nil, err
342 }
343 cfgs := make([]*VDPAMGMTDev, 0, len(messages))
344 for _, m := range messages {
345 cfg := &VDPAMGMTDev{}
346 cfg.parseAttributes(m)
347 cfgs = append(cfgs, cfg)
348 }
349 return cfgs, nil
350 }
351
352
353
354 func (h *Handle) VDPANewDev(name, mgmtBus, mgmtName string, params VDPANewDevParams) error {
355 attrs := []*nl.RtAttr{
356 nl.NewRtAttr(nl.VDPA_ATTR_DEV_NAME, nl.ZeroTerminated(name)),
357 nl.NewRtAttr(nl.VDPA_ATTR_MGMTDEV_DEV_NAME, nl.ZeroTerminated(mgmtName)),
358 }
359 if mgmtBus != "" {
360 attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_MGMTDEV_BUS_NAME, nl.ZeroTerminated(mgmtBus)))
361 }
362 if len(params.MACAddr) != 0 {
363 attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_NET_CFG_MACADDR, params.MACAddr))
364 }
365 if params.MaxVQP > 0 {
366 attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_NET_CFG_MAX_VQP, nl.Uint16Attr(params.MaxVQP)))
367 }
368 if params.MTU > 0 {
369 attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_NET_CFG_MTU, nl.Uint16Attr(params.MTU)))
370 }
371 if params.Features > 0 {
372 attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_FEATURES, nl.Uint64Attr(params.Features)))
373 }
374 _, err := h.vdpaRequest(nl.VDPA_CMD_DEV_NEW, 0, attrs)
375 return err
376 }
377
378
379
380 func (h *Handle) VDPADelDev(name string) error {
381 _, err := h.vdpaRequest(nl.VDPA_CMD_DEV_DEL, 0, []*nl.RtAttr{
382 nl.NewRtAttr(nl.VDPA_ATTR_DEV_NAME, nl.ZeroTerminated(name))})
383 return err
384 }
385
386
387
388 func (h *Handle) VDPAGetDevList() ([]*VDPADev, error) {
389 return h.vdpaDevGet(nil)
390 }
391
392
393
394 func (h *Handle) VDPAGetDevByName(name string) (*VDPADev, error) {
395 devs, err := h.vdpaDevGet(&name)
396 if err != nil {
397 return nil, err
398 }
399 if len(devs) == 0 {
400 return nil, fmt.Errorf("device not found")
401 }
402 return devs[0], nil
403 }
404
405
406
407 func (h *Handle) VDPAGetDevConfigList() ([]*VDPADevConfig, error) {
408 return h.vdpaDevConfigGet(nil)
409 }
410
411
412
413 func (h *Handle) VDPAGetDevConfigByName(name string) (*VDPADevConfig, error) {
414 cfgs, err := h.vdpaDevConfigGet(&name)
415 if err != nil {
416 return nil, err
417 }
418 if len(cfgs) == 0 {
419 return nil, fmt.Errorf("configuration not found")
420 }
421 return cfgs[0], nil
422 }
423
424
425
426 func (h *Handle) VDPAGetDevVStats(name string, queueIndex uint32) (*VDPADevVStats, error) {
427 messages, err := h.vdpaRequest(nl.VDPA_CMD_DEV_VSTATS_GET, 0, []*nl.RtAttr{
428 nl.NewRtAttr(nl.VDPA_ATTR_DEV_NAME, nl.ZeroTerminated(name)),
429 nl.NewRtAttr(nl.VDPA_ATTR_DEV_QUEUE_INDEX, nl.Uint32Attr(queueIndex)),
430 })
431 if err != nil {
432 return nil, err
433 }
434 if len(messages) == 0 {
435 return nil, fmt.Errorf("stats not found")
436 }
437 stats := &VDPADevVStats{}
438 stats.parseAttributes(messages[0])
439 return stats, nil
440 }
441
442
443
444 func (h *Handle) VDPAGetMGMTDevList() ([]*VDPAMGMTDev, error) {
445 return h.vdpaMGMTDevGet(nil, nil)
446 }
447
448
449
450 func (h *Handle) VDPAGetMGMTDevByBusAndName(bus, name string) (*VDPAMGMTDev, error) {
451 var busPtr *string
452 if bus != "" {
453 busPtr = &bus
454 }
455 devs, err := h.vdpaMGMTDevGet(busPtr, &name)
456 if err != nil {
457 return nil, err
458 }
459 if len(devs) == 0 {
460 return nil, fmt.Errorf("mgmtdev not found")
461 }
462 return devs[0], nil
463 }
464
View as plain text