mirror of https://github.com/vishvananda/netlink
Add support to get devlink resources
- Update nl package with new netlink attribute types and consts - Define structs to model devlink device resources - Add DevlinkGetDeviceResources method to return device resources - Add basic test Signed-off-by: adrianc <adrianc@nvidia.com>
This commit is contained in:
parent
2bbba08be2
commit
36b61ad22c
192
devlink_linux.go
192
devlink_linux.go
|
@ -84,6 +84,169 @@ type DevlinkDeviceInfo struct {
|
|||
FwUndi string
|
||||
}
|
||||
|
||||
// DevlinkResource represents a device resource
|
||||
type DevlinkResource struct {
|
||||
Name string
|
||||
ID uint64
|
||||
Size uint64
|
||||
SizeNew uint64
|
||||
SizeMin uint64
|
||||
SizeMax uint64
|
||||
SizeGranularity uint64
|
||||
PendingChange bool
|
||||
Unit uint8
|
||||
SizeValid bool
|
||||
OCCValid bool
|
||||
OCCSize uint64
|
||||
Parent *DevlinkResource
|
||||
Children []DevlinkResource
|
||||
}
|
||||
|
||||
// parseAttributes parses provided Netlink Attributes and populates DevlinkResource, returns error if occured
|
||||
func (dlr *DevlinkResource) parseAttributes(attrs map[uint16]syscall.NetlinkRouteAttr) error {
|
||||
var attr syscall.NetlinkRouteAttr
|
||||
var ok bool
|
||||
|
||||
// mandatory attributes
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_ID]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing resource id")
|
||||
}
|
||||
dlr.ID = native.Uint64(attr.Value)
|
||||
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_NAME]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing resource name")
|
||||
}
|
||||
dlr.Name = nl.BytesToString(attr.Value)
|
||||
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_SIZE]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing resource size")
|
||||
}
|
||||
dlr.Size = native.Uint64(attr.Value)
|
||||
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_SIZE_GRAN]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing resource size granularity")
|
||||
}
|
||||
dlr.SizeGranularity = native.Uint64(attr.Value)
|
||||
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_UNIT]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing resource unit")
|
||||
}
|
||||
dlr.Unit = uint8(attr.Value[0])
|
||||
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_SIZE_MIN]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing resource size min")
|
||||
}
|
||||
dlr.SizeMin = native.Uint64(attr.Value)
|
||||
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_SIZE_MAX]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing resource size max")
|
||||
}
|
||||
dlr.SizeMax = native.Uint64(attr.Value)
|
||||
|
||||
// optional attributes
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_OCC]
|
||||
if ok {
|
||||
dlr.OCCSize = native.Uint64(attr.Value)
|
||||
dlr.OCCValid = true
|
||||
}
|
||||
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_SIZE_VALID]
|
||||
if ok {
|
||||
dlr.SizeValid = uint8(attr.Value[0]) != 0
|
||||
}
|
||||
|
||||
dlr.SizeNew = dlr.Size
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_SIZE_NEW]
|
||||
if ok {
|
||||
dlr.SizeNew = native.Uint64(attr.Value)
|
||||
}
|
||||
|
||||
dlr.PendingChange = dlr.Size != dlr.SizeNew
|
||||
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_LIST]
|
||||
if ok {
|
||||
// handle nested resoruces recursively
|
||||
subResources, err := nl.ParseRouteAttr(attr.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, subresource := range subResources {
|
||||
resource := DevlinkResource{Parent: dlr}
|
||||
attrs, err := nl.ParseRouteAttrAsMap(subresource.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = resource.parseAttributes(attrs)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse child resource, parent:%s. %w", dlr.Name, err)
|
||||
}
|
||||
dlr.Children = append(dlr.Children, resource)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DevlinkResources represents all devlink resources of a devlink device
|
||||
type DevlinkResources struct {
|
||||
Bus string
|
||||
Device string
|
||||
Resources []DevlinkResource
|
||||
}
|
||||
|
||||
// parseAttributes parses provided Netlink Attributes and populates DevlinkResources, returns error if occured
|
||||
func (dlrs *DevlinkResources) parseAttributes(attrs map[uint16]syscall.NetlinkRouteAttr) error {
|
||||
var attr syscall.NetlinkRouteAttr
|
||||
var ok bool
|
||||
|
||||
// Bus
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_BUS_NAME]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing bus name")
|
||||
}
|
||||
dlrs.Bus = nl.BytesToString(attr.Value)
|
||||
|
||||
// Device
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_DEV_NAME]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing device name")
|
||||
}
|
||||
dlrs.Device = nl.BytesToString(attr.Value)
|
||||
|
||||
// Resource List
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_LIST]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing resource list")
|
||||
}
|
||||
|
||||
resourceAttrs, err := nl.ParseRouteAttr(attr.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, resourceAttr := range resourceAttrs {
|
||||
resource := DevlinkResource{}
|
||||
attrs, err := nl.ParseRouteAttrAsMap(resourceAttr.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = resource.parseAttributes(attrs)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse root resoruces, %w", err)
|
||||
}
|
||||
dlrs.Resources = append(dlrs.Resources, resource)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseDevLinkDeviceList(msgs [][]byte) ([]*DevlinkDevice, error) {
|
||||
devices := make([]*DevlinkDevice, 0, len(msgs))
|
||||
for _, m := range msgs {
|
||||
|
@ -443,6 +606,35 @@ func (h *Handle) DevLinkGetPortByIndex(Bus string, Device string, PortIndex uint
|
|||
return port, err
|
||||
}
|
||||
|
||||
// DevlinkGetDeviceResources returns devlink device resources
|
||||
func DevlinkGetDeviceResources(bus string, device string) (*DevlinkResources, error) {
|
||||
return pkgHandle.DevlinkGetDeviceResources(bus, device)
|
||||
}
|
||||
|
||||
// DevlinkGetDeviceResources returns devlink device resources
|
||||
func (h *Handle) DevlinkGetDeviceResources(bus string, device string) (*DevlinkResources, error) {
|
||||
_, req, err := h.createCmdReq(nl.DEVLINK_CMD_RESOURCE_DUMP, bus, device)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
respmsg, err := req.Execute(unix.NETLINK_GENERIC, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var resources DevlinkResources
|
||||
for _, m := range respmsg {
|
||||
attrs, err := nl.ParseRouteAttrAsMap(m[nl.SizeofGenlmsg:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resources.parseAttributes(attrs)
|
||||
}
|
||||
|
||||
return &resources, nil
|
||||
}
|
||||
|
||||
// DevLinkGetPortByIndex provides a pointer to devlink portand nil error,
|
||||
// otherwise returns an error code.
|
||||
func DevLinkGetPortByIndex(Bus string, Device string, PortIndex uint32) (*DevlinkPort, error) {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package netlink
|
||||
|
@ -262,3 +263,26 @@ func areInfoStructsEqual(first *DevlinkDeviceInfo, second *DevlinkDeviceInfo) bo
|
|||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func TestDevlinkGetDeviceResources(t *testing.T) {
|
||||
minKernelRequired(t, 5, 11)
|
||||
tearDown := setUpNetlinkTestWithKModule(t, "devlink")
|
||||
defer tearDown()
|
||||
|
||||
if bus == "" || device == "" {
|
||||
//TODO: setup netdevsim device instead of getting device from flags
|
||||
t.Log("devlink bus and device are empty, skipping test")
|
||||
t.SkipNow()
|
||||
}
|
||||
|
||||
res, err := DevlinkGetDeviceResources(bus, device)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get device(%s/%s) resources. %s", bus, device, err)
|
||||
}
|
||||
|
||||
if res.Bus != bus || res.Device != device {
|
||||
t.Fatalf("missmatching bus/device")
|
||||
}
|
||||
|
||||
t.Logf("Resources: %+v", res)
|
||||
}
|
||||
|
|
|
@ -9,39 +9,54 @@ const (
|
|||
)
|
||||
|
||||
const (
|
||||
DEVLINK_CMD_GET = 1
|
||||
DEVLINK_CMD_PORT_GET = 5
|
||||
DEVLINK_CMD_PORT_SET = 6
|
||||
DEVLINK_CMD_PORT_NEW = 7
|
||||
DEVLINK_CMD_PORT_DEL = 8
|
||||
DEVLINK_CMD_ESWITCH_GET = 29
|
||||
DEVLINK_CMD_ESWITCH_SET = 30
|
||||
DEVLINK_CMD_INFO_GET = 51
|
||||
DEVLINK_CMD_GET = 1
|
||||
DEVLINK_CMD_PORT_GET = 5
|
||||
DEVLINK_CMD_PORT_SET = 6
|
||||
DEVLINK_CMD_PORT_NEW = 7
|
||||
DEVLINK_CMD_PORT_DEL = 8
|
||||
DEVLINK_CMD_ESWITCH_GET = 29
|
||||
DEVLINK_CMD_ESWITCH_SET = 30
|
||||
DEVLINK_CMD_RESOURCE_DUMP = 36
|
||||
DEVLINK_CMD_INFO_GET = 51
|
||||
)
|
||||
|
||||
const (
|
||||
DEVLINK_ATTR_BUS_NAME = 1
|
||||
DEVLINK_ATTR_DEV_NAME = 2
|
||||
DEVLINK_ATTR_PORT_INDEX = 3
|
||||
DEVLINK_ATTR_PORT_TYPE = 4
|
||||
DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 6
|
||||
DEVLINK_ATTR_PORT_NETDEV_NAME = 7
|
||||
DEVLINK_ATTR_PORT_IBDEV_NAME = 8
|
||||
DEVLINK_ATTR_ESWITCH_MODE = 25
|
||||
DEVLINK_ATTR_ESWITCH_INLINE_MODE = 26
|
||||
DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 62
|
||||
DEVLINK_ATTR_PORT_FLAVOUR = 77
|
||||
DEVLINK_ATTR_INFO_DRIVER_NAME = 98
|
||||
DEVLINK_ATTR_INFO_SERIAL_NUMBER = 99
|
||||
DEVLINK_ATTR_INFO_VERSION_FIXED = 100
|
||||
DEVLINK_ATTR_INFO_VERSION_RUNNING = 101
|
||||
DEVLINK_ATTR_INFO_VERSION_STORED = 102
|
||||
DEVLINK_ATTR_INFO_VERSION_NAME = 103
|
||||
DEVLINK_ATTR_INFO_VERSION_VALUE = 104
|
||||
DEVLINK_ATTR_PORT_PCI_PF_NUMBER = 127
|
||||
DEVLINK_ATTR_PORT_FUNCTION = 145
|
||||
DEVLINK_ATTR_PORT_CONTROLLER_NUMBER = 150
|
||||
DEVLINK_ATTR_PORT_PCI_SF_NUMBER = 164
|
||||
DEVLINK_ATTR_BUS_NAME = 1
|
||||
DEVLINK_ATTR_DEV_NAME = 2
|
||||
DEVLINK_ATTR_PORT_INDEX = 3
|
||||
DEVLINK_ATTR_PORT_TYPE = 4
|
||||
DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 6
|
||||
DEVLINK_ATTR_PORT_NETDEV_NAME = 7
|
||||
DEVLINK_ATTR_PORT_IBDEV_NAME = 8
|
||||
DEVLINK_ATTR_ESWITCH_MODE = 25
|
||||
DEVLINK_ATTR_ESWITCH_INLINE_MODE = 26
|
||||
DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 62
|
||||
DEVLINK_ATTR_RESOURCE_LIST = 63 /* nested */
|
||||
DEVLINK_ATTR_RESOURCE = 64 /* nested */
|
||||
DEVLINK_ATTR_RESOURCE_NAME = 65 /* string */
|
||||
DEVLINK_ATTR_RESOURCE_ID = 66 /* u64 */
|
||||
DEVLINK_ATTR_RESOURCE_SIZE = 67 /* u64 */
|
||||
DEVLINK_ATTR_RESOURCE_SIZE_NEW = 68 /* u64 */
|
||||
DEVLINK_ATTR_RESOURCE_SIZE_VALID = 69 /* u8 */
|
||||
DEVLINK_ATTR_RESOURCE_SIZE_MIN = 70 /* u64 */
|
||||
DEVLINK_ATTR_RESOURCE_SIZE_MAX = 71 /* u64 */
|
||||
DEVLINK_ATTR_RESOURCE_SIZE_GRAN = 72 /* u64 */
|
||||
DEVLINK_ATTR_RESOURCE_UNIT = 73 /* u8 */
|
||||
DEVLINK_ATTR_RESOURCE_OCC = 74 /* u64 */
|
||||
DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID = 75 /* u64 */
|
||||
DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS = 76 /* u64 */
|
||||
DEVLINK_ATTR_PORT_FLAVOUR = 77
|
||||
DEVLINK_ATTR_INFO_DRIVER_NAME = 98
|
||||
DEVLINK_ATTR_INFO_SERIAL_NUMBER = 99
|
||||
DEVLINK_ATTR_INFO_VERSION_FIXED = 100
|
||||
DEVLINK_ATTR_INFO_VERSION_RUNNING = 101
|
||||
DEVLINK_ATTR_INFO_VERSION_STORED = 102
|
||||
DEVLINK_ATTR_INFO_VERSION_NAME = 103
|
||||
DEVLINK_ATTR_INFO_VERSION_VALUE = 104
|
||||
DEVLINK_ATTR_PORT_PCI_PF_NUMBER = 127
|
||||
DEVLINK_ATTR_PORT_FUNCTION = 145
|
||||
DEVLINK_ATTR_PORT_CONTROLLER_NUMBER = 150
|
||||
DEVLINK_ATTR_PORT_PCI_SF_NUMBER = 164
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -94,3 +109,7 @@ const (
|
|||
DEVLINK_PORT_FN_OPSTATE_DETACHED = 0
|
||||
DEVLINK_PORT_FN_OPSTATE_ATTACHED = 1
|
||||
)
|
||||
|
||||
const (
|
||||
DEVLINK_RESOURCE_UNIT_ENTRY uint8 = 0
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue