diff --git a/devlink_linux.go b/devlink_linux.go index 0db166ff..9e05426c 100644 --- a/devlink_linux.go +++ b/devlink_linux.go @@ -34,6 +34,13 @@ type DevlinkPortFn struct { OpState uint8 } +// DevlinkPortFnSetAttrs represents attributes to set +type DevlinkPortFnSetAttrs struct { + FnAttrs DevlinkPortFn + HwAddrValid bool + StateValid bool +} + // DevlinkPort represents port and its attributes type DevlinkPort struct { BusName string @@ -472,3 +479,34 @@ func (h *Handle) DevLinkPortDel(Bus string, Device string, PortIndex uint32) err func DevLinkPortDel(Bus string, Device string, PortIndex uint32) error { return pkgHandle.DevLinkPortDel(Bus, Device, PortIndex) } + +// DevlinkPortFnSet sets one or more port function attributes specified by the attribute mask. +// It returns 0 on success or error code. +func (h *Handle) DevlinkPortFnSet(Bus string, Device string, PortIndex uint32, FnAttrs DevlinkPortFnSetAttrs) error { + _, req, err := h.createCmdReq(nl.DEVLINK_CMD_PORT_SET, Bus, Device) + if err != nil { + return err + } + + req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_INDEX, nl.Uint32Attr(PortIndex))) + + fnAttr := nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_FUNCTION|unix.NLA_F_NESTED, nil) + + if FnAttrs.HwAddrValid == true { + fnAttr.AddRtAttr(nl.DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR, []byte(FnAttrs.FnAttrs.HwAddr)) + } + + if FnAttrs.StateValid == true { + fnAttr.AddRtAttr(nl.DEVLINK_PORT_FN_ATTR_STATE, nl.Uint8Attr(FnAttrs.FnAttrs.State)) + } + req.AddData(fnAttr) + + _, err = req.Execute(unix.NETLINK_GENERIC, 0) + return err +} + +// DevlinkPortFnSet sets one or more port function attributes specified by the attribute mask. +// It returns 0 on success or error code. +func DevlinkPortFnSet(Bus string, Device string, PortIndex uint32, FnAttrs DevlinkPortFnSetAttrs) error { + return pkgHandle.DevlinkPortFnSet(Bus, Device, PortIndex, FnAttrs) +} diff --git a/devlink_test.go b/devlink_test.go index 3364636a..b1f7e5e1 100644 --- a/devlink_test.go +++ b/devlink_test.go @@ -3,8 +3,9 @@ package netlink import ( - "testing" "flag" + "net" + "testing" ) func TestDevLinkGetDeviceList(t *testing.T) { @@ -77,7 +78,62 @@ func TestDevLinkAddDelSfPort(t *testing.T) { } t.Log(*port) if port.Fn != nil { - t.Log("function attributes = " , *port.Fn) + t.Log("function attributes = ", *port.Fn) + } + err2 = DevLinkPortDel(dev.BusName, dev.DeviceName, port.PortIndex) + if err2 != nil { + t.Fatal(err2) + } +} + +func TestDevLinkSfPortFnSet(t *testing.T) { + var addAttrs DevLinkPortAddAttrs + var stateAttr DevlinkPortFnSetAttrs + + minKernelRequired(t, 5, 12) + if bus == "" || device == "" { + t.Log("devlink bus and device are empty, skipping test") + return + } + + dev, err := DevLinkGetDeviceByName(bus, device) + if err != nil { + t.Fatal(err) + return + } + addAttrs.SfNumberValid = true + addAttrs.SfNumber = uint32(sfnum) + addAttrs.PfNumber = 0 + port, err2 := DevLinkPortAdd(dev.BusName, dev.DeviceName, 7, addAttrs) + if err2 != nil { + t.Fatal(err2) + return + } + t.Log(*port) + if port.Fn != nil { + t.Log("function attributes = ", *port.Fn) + } + macAttr := DevlinkPortFnSetAttrs{ + FnAttrs: DevlinkPortFn{ + HwAddr: net.HardwareAddr{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}, + }, + HwAddrValid: true, + } + err2 = DevlinkPortFnSet(dev.BusName, dev.DeviceName, port.PortIndex, macAttr) + if err2 != nil { + t.Log("function mac set err = ", err2) + } + stateAttr.FnAttrs.State = 1 + stateAttr.StateValid = true + err2 = DevlinkPortFnSet(dev.BusName, dev.DeviceName, port.PortIndex, stateAttr) + if err2 != nil { + t.Log("function state set err = ", err2) + } + + port, err3 := DevLinkGetPortByIndex(dev.BusName, dev.DeviceName, port.PortIndex) + if err3 == nil { + t.Log(*port) + t.Log(*port.Fn) } err2 = DevLinkPortDel(dev.BusName, dev.DeviceName, port.PortIndex) if err2 != nil { @@ -90,7 +146,7 @@ var device string var sfnum uint func init() { - flag.StringVar(&bus, "bus", "", "devlink device bus name") - flag.StringVar(&device, "device", "", "devlink device devicename") - flag.UintVar(&sfnum, "sfnum", 0, "devlink port sfnumber") + flag.StringVar(&bus, "bus", "", "devlink device bus name") + flag.StringVar(&device, "device", "", "devlink device devicename") + flag.UintVar(&sfnum, "sfnum", 0, "devlink port sfnumber") }