/
dev.go
117 lines (101 loc) · 2.5 KB
/
dev.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package eal
/*
#include "../../csrc/core/common.h"
#include <rte_bus_vdev.h>
#include <rte_dev.h>
*/
import "C"
import (
"fmt"
"unsafe"
"github.com/usnistgov/ndn-dpdk/core/pciaddr"
"go.uber.org/zap"
)
// JoinDevArgs converts device argument key-value pairs to a string.
// nil values are skipped.
// As a special case, if the map has a "" key, its value would override all other arguments.
func JoinDevArgs(m map[string]any) string {
if s, ok := m[""]; ok {
return fmt.Sprint(s)
}
var b []byte
delim := ""
for k, v := range m {
if v == nil {
continue
}
b = fmt.Appendf(b, "%s%s=%v", delim, k, v)
delim = ","
}
return string(b)
}
// ProbePCI requests to probe a PCI device.
func ProbePCI(addr pciaddr.PCIAddress, args map[string]any) error {
arg := JoinDevArgs(args)
devargs := addr.String()
if arg != "" {
devargs += "," + arg
}
devargsC := C.CString(devargs)
defer C.free(unsafe.Pointer(devargsC))
logEntry := logger.With(
zap.String("addr", addr.String()),
zap.String("args", arg),
)
if res := C.rte_dev_probe(devargsC); res != 0 {
e := MakeErrno(res)
logEntry.Error("rte_dev_probe error", zap.Error(e))
return e
}
logEntry.Info("PCI device probed")
return nil
}
// VDev represents a DPDK virtual device.
type VDev struct {
name string
socket NumaSocket
}
// Name returns the device name.
func (vdev VDev) Name() string {
return vdev.name
}
// NumaSocket returns the NUMA socket of this device, if known.
func (vdev VDev) NumaSocket() NumaSocket {
return vdev.socket
}
// Close destroys the virtual device.
func (vdev *VDev) Close() error {
nameC := C.CString(vdev.name)
defer C.free(unsafe.Pointer(nameC))
logEntry := logger.With(zap.String("name", vdev.name))
if res := C.rte_vdev_uninit(nameC); res != 0 {
e := MakeErrno(res)
logEntry.Error("rte_vdev_uninit error", zap.Error(e))
return e
}
logEntry.Info("vdev uninitialized")
return nil
}
// NewVDev creates a virtual device.
func NewVDev(name string, args map[string]any, socket NumaSocket) (vdev *VDev, e error) {
nameC := C.CString(name)
defer C.free(unsafe.Pointer(nameC))
arg := JoinDevArgs(args)
argC := C.CString(arg)
defer C.free(unsafe.Pointer(argC))
logEntry := logger.With(
zap.String("name", name),
zap.String("args", arg),
socket.ZapField("socket"),
)
if res := C.rte_vdev_init(nameC, argC); res != 0 {
e := MakeErrno(res)
logEntry.Error("rte_vdev_init error", zap.Error(e))
return nil, e
}
logEntry.Info("vdev initialized")
return &VDev{
name: name,
socket: socket,
}, nil
}