Skip to content

Commit c311f60

Browse files
committed
vdpa: Introduce VDPASetAttr, support setting mac
The Linux kernel supports setting mac addresses to existing vdpa devices since 6.12. The feature was introduced by commit 2f87e9cf. This commit brings support for that feature to the netlink library by introducing the VDPASetAttr function. Note that even though setting the mac address is the only supported operation currently, the implementation has been left open for MTU, MaxVQP and Feature setting. In other words, it relies on whether the kernel supports it or not, and just feeds the kernel's error back to the caller. That way, no further changes will be needed in the future, if support for those operations is implemented. Well, apart from tests, as they currently assume those are not supported. Signed-off-by: Beñat Gartzia Arruabarrena <[email protected]>
1 parent 6e61cd4 commit c311f60

File tree

3 files changed

+119
-0
lines changed

3 files changed

+119
-0
lines changed

nl/vdpa_linux.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const (
1414
VDPA_CMD_DEV_GET /* can dump */
1515
VDPA_CMD_DEV_CONFIG_GET /* can dump */
1616
VDPA_CMD_DEV_VSTATS_GET
17+
VDPA_CMD_DEV_ATTR_SET
1718
)
1819

1920
const (

vdpa_linux.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,10 @@ func VDPAGetMGMTDevByBusAndName(bus, name string) (*VDPAMGMTDev, error) {
168168
return pkgHandle.VDPAGetMGMTDevByBusAndName(bus, name)
169169
}
170170

171+
func VDPASetAttr(name string, params VDPANewDevParams) error {
172+
return pkgHandle.VDPASetAttr(name, params)
173+
}
174+
171175
type vdpaNetlinkMessage []syscall.NetlinkRouteAttr
172176

173177
func (id *vdpaDevID) parseIDAttribute(attr syscall.NetlinkRouteAttr) {
@@ -489,3 +493,30 @@ func (h *Handle) VDPAGetMGMTDevByBusAndName(bus, name string) (*VDPAMGMTDev, err
489493
}
490494
return devs[0], nil
491495
}
496+
497+
// VDPASetAttr sets other values to attributes of a VDPA device
498+
// Equivalent to: `vdpa dev set name <name> ...`
499+
func (h *Handle) VDPASetAttr(name string, params VDPANewDevParams) error {
500+
attrs := []*nl.RtAttr{}
501+
502+
if len(params.MACAddr) != 0 {
503+
attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_NET_CFG_MACADDR, params.MACAddr))
504+
}
505+
if params.MaxVQP > 0 {
506+
attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_NET_CFG_MAX_VQP, nl.Uint16Attr(params.MaxVQP)))
507+
}
508+
if params.MTU > 0 {
509+
attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_NET_CFG_MTU, nl.Uint16Attr(params.MTU)))
510+
}
511+
if params.Features > 0 {
512+
attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_FEATURES, nl.Uint64Attr(params.Features)))
513+
}
514+
515+
if len(attrs) == 0 {
516+
return fmt.Errorf("parameters were not provided")
517+
}
518+
attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_NAME, nl.ZeroTerminated(name)))
519+
520+
_, err := h.vdpaRequest(nl.VDPA_CMD_DEV_ATTR_SET, unix.NLM_F_REQUEST, attrs)
521+
return err
522+
}

vdpa_linux_test.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package netlink
22

33
import (
44
"errors"
5+
"net"
56
"syscall"
67
"testing"
78

@@ -222,6 +223,88 @@ func TestVDPAGetDevConfigByName_Unknowm(t *testing.T) {
222223
}
223224
}
224225

226+
func TestVDPASetMAC(t *testing.T) {
227+
defer setupVDPATest(t, nl.VDPA_CMD_DEV_GET, nl.VDPA_CMD_DEV_CONFIG_GET, nl.VDPA_CMD_DEV_ATTR_SET)()
228+
firstMac, _ := net.ParseMAC("02:11:22:33:44:68")
229+
lastMacStr := "72:84:65:12:09:77"
230+
lastMac, _ := net.ParseMAC(lastMacStr)
231+
if err := createVDPATestDevWithParams(VDPANewDevParams{MACAddr: firstMac}); err != nil {
232+
t.Fatalf("failed to create VDPA device: %v", err)
233+
}
234+
if err := VDPASetAttr(vdpaTestDeviceName, VDPANewDevParams{MACAddr: lastMac}); err != nil {
235+
t.Fatalf("failed to set mac to VDPA device: %v", err)
236+
}
237+
dev, err := VDPAGetDevConfigByName(vdpaTestDeviceName)
238+
if err != nil {
239+
t.Fatalf("VDPAGetDevConfigByName failed: %v", err)
240+
}
241+
checkVDPADevConf(t, dev)
242+
if dev.Name != vdpaTestDeviceName {
243+
t.Fatalf("Invalid device received for Get call, expected: %s, actual: %s", vdpaTestDeviceName, dev.Name)
244+
}
245+
newMacStr := dev.Net.Cfg.MACAddr.String()
246+
if newMacStr != lastMacStr {
247+
t.Fatalf("mac address was not properly set. Expected: %s, actual: %s", lastMac, newMacStr)
248+
}
249+
}
250+
251+
func TestVDPASetMACWrongName(t *testing.T) {
252+
defer setupVDPATest(t, nl.VDPA_CMD_DEV_GET, nl.VDPA_CMD_DEV_CONFIG_GET, nl.VDPA_CMD_DEV_ATTR_SET)()
253+
mac, _ := net.ParseMAC("72:84:65:12:09:77")
254+
if err := createVDPATestDev(); err != nil {
255+
t.Fatalf("failed to create VDPA device: %v", err)
256+
}
257+
err := VDPASetAttr("__unknown_device__", VDPANewDevParams{MACAddr: mac})
258+
if !errors.Is(err, syscall.ENODEV) {
259+
t.Fatalf("VDPASetAttr returned unexpected error setting mac to non existing device: %v", err)
260+
}
261+
}
262+
263+
func TestVDPASetEmptyParams(t *testing.T) {
264+
defer setupVDPATest(t, nl.VDPA_CMD_DEV_GET, nl.VDPA_CMD_DEV_CONFIG_GET, nl.VDPA_CMD_DEV_ATTR_SET)()
265+
if err := createVDPATestDev(); err != nil {
266+
t.Fatalf("failed to create VDPA device: %v", err)
267+
}
268+
err := VDPASetAttr(vdpaTestDeviceName, VDPANewDevParams{})
269+
if err == nil {
270+
t.Fatalf("VDPASetAttr did not return an error when params were empty: %v", err)
271+
}
272+
}
273+
274+
func TestVDPASetMTU(t *testing.T) {
275+
defer setupVDPATest(t, nl.VDPA_CMD_DEV_GET, nl.VDPA_CMD_DEV_CONFIG_GET, nl.VDPA_CMD_DEV_ATTR_SET)()
276+
if err := createVDPATestDev(); err != nil {
277+
t.Fatalf("failed to create VDPA device: %v", err)
278+
}
279+
err := VDPASetAttr(vdpaTestDeviceName, VDPANewDevParams{MTU: 3000})
280+
if !errors.Is(err, syscall.ENOTSUP) {
281+
t.Fatalf("VDPASetAttr returned an unexpected error setting mtu to vdpa device: %v", err)
282+
}
283+
}
284+
285+
func TestVDPASetMaxVQP(t *testing.T) {
286+
defer setupVDPATest(t, nl.VDPA_CMD_DEV_GET, nl.VDPA_CMD_DEV_CONFIG_GET, nl.VDPA_CMD_DEV_ATTR_SET)()
287+
if err := createVDPATestDev(); err != nil {
288+
t.Fatalf("failed to create VDPA device: %v", err)
289+
}
290+
err := VDPASetAttr(vdpaTestDeviceName, VDPANewDevParams{MaxVQP: 3000})
291+
if !errors.Is(err, syscall.ENOTSUP) {
292+
t.Fatalf("VDPASetAttr returned an unexpected error setting maxvqp to vdpa device: %v", err)
293+
}
294+
}
295+
296+
func TestVDPASetFeatures(t *testing.T) {
297+
defer setupVDPATest(t, nl.VDPA_CMD_DEV_GET, nl.VDPA_CMD_DEV_CONFIG_GET, nl.VDPA_CMD_DEV_ATTR_SET)()
298+
if err := createVDPATestDev(); err != nil {
299+
t.Fatalf("failed to create VDPA device: %v", err)
300+
}
301+
// Default vdpa_sim_net features without VIRTIO_NET_F_CTRL_MAC_ADDR
302+
err := VDPASetAttr(vdpaTestDeviceName, VDPANewDevParams{Features: 13019316265})
303+
if !errors.Is(err, syscall.ENOTSUP) {
304+
t.Fatalf("VDPASetAttr returned an unexpected error setting features to vdpa device: %v", err)
305+
}
306+
}
307+
225308
func TestSetGetBits(t *testing.T) {
226309
features := SetBits(0, VIRTIO_NET_F_CSUM, VIRTIO_NET_F_MQ)
227310
if !IsBitSet(features, VIRTIO_NET_F_CSUM) || !IsBitSet(features, VIRTIO_NET_F_MQ) {
@@ -236,6 +319,10 @@ func createVDPATestDev() error {
236319
return VDPANewDev(vdpaTestDeviceName, "", vdpaSimMGMTDev, VDPANewDevParams{})
237320
}
238321

322+
func createVDPATestDevWithParams(params VDPANewDevParams) error {
323+
return VDPANewDev(vdpaTestDeviceName, "", vdpaSimMGMTDev, params)
324+
}
325+
239326
func checkVDPAMGMTDev(t *testing.T, d *VDPAMGMTDev) {
240327
if d == nil {
241328
t.Fatal("VDPA MGMT dev is nil")

0 commit comments

Comments
 (0)