| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393 |
- package netlink
- import (
- "syscall"
- "fmt"
- "github.com/vishvananda/netlink/nl"
- "golang.org/x/sys/unix"
- )
- // DevlinkDevEswitchAttr represents device's eswitch attributes
- type DevlinkDevEswitchAttr struct {
- Mode string
- InlineMode string
- EncapMode string
- }
- // DevlinkDevAttrs represents device attributes
- type DevlinkDevAttrs struct {
- Eswitch DevlinkDevEswitchAttr
- }
- // DevlinkDevice represents device and its attributes
- type DevlinkDevice struct {
- BusName string
- DeviceName string
- Attrs DevlinkDevAttrs
- }
- // DevlinkPort represents port and its attributes
- type DevlinkPort struct {
- BusName string
- DeviceName string
- PortIndex uint32
- PortType uint16
- NetdeviceName string
- NetdevIfIndex uint32
- RdmaDeviceName string
- PortFlavour uint16
- }
- func parseDevLinkDeviceList(msgs [][]byte) ([]*DevlinkDevice, error) {
- devices := make([]*DevlinkDevice, 0, len(msgs))
- for _, m := range msgs {
- attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:])
- if err != nil {
- return nil, err
- }
- dev := &DevlinkDevice{}
- if err = dev.parseAttributes(attrs); err != nil {
- return nil, err
- }
- devices = append(devices, dev)
- }
- return devices, nil
- }
- func eswitchStringToMode(modeName string) (uint16, error) {
- if modeName == "legacy" {
- return nl.DEVLINK_ESWITCH_MODE_LEGACY, nil
- } else if modeName == "switchdev" {
- return nl.DEVLINK_ESWITCH_MODE_SWITCHDEV, nil
- } else {
- return 0xffff, fmt.Errorf("invalid switchdev mode")
- }
- }
- func parseEswitchMode(mode uint16) string {
- var eswitchMode = map[uint16]string{
- nl.DEVLINK_ESWITCH_MODE_LEGACY: "legacy",
- nl.DEVLINK_ESWITCH_MODE_SWITCHDEV: "switchdev",
- }
- if eswitchMode[mode] == "" {
- return "unknown"
- } else {
- return eswitchMode[mode]
- }
- }
- func parseEswitchInlineMode(inlinemode uint8) string {
- var eswitchInlineMode = map[uint8]string{
- nl.DEVLINK_ESWITCH_INLINE_MODE_NONE: "none",
- nl.DEVLINK_ESWITCH_INLINE_MODE_LINK: "link",
- nl.DEVLINK_ESWITCH_INLINE_MODE_NETWORK: "network",
- nl.DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT: "transport",
- }
- if eswitchInlineMode[inlinemode] == "" {
- return "unknown"
- } else {
- return eswitchInlineMode[inlinemode]
- }
- }
- func parseEswitchEncapMode(encapmode uint8) string {
- var eswitchEncapMode = map[uint8]string{
- nl.DEVLINK_ESWITCH_ENCAP_MODE_NONE: "disable",
- nl.DEVLINK_ESWITCH_ENCAP_MODE_BASIC: "enable",
- }
- if eswitchEncapMode[encapmode] == "" {
- return "unknown"
- } else {
- return eswitchEncapMode[encapmode]
- }
- }
- func (d *DevlinkDevice) parseAttributes(attrs []syscall.NetlinkRouteAttr) error {
- for _, a := range attrs {
- switch a.Attr.Type {
- case nl.DEVLINK_ATTR_BUS_NAME:
- d.BusName = string(a.Value)
- case nl.DEVLINK_ATTR_DEV_NAME:
- d.DeviceName = string(a.Value)
- case nl.DEVLINK_ATTR_ESWITCH_MODE:
- d.Attrs.Eswitch.Mode = parseEswitchMode(native.Uint16(a.Value))
- case nl.DEVLINK_ATTR_ESWITCH_INLINE_MODE:
- d.Attrs.Eswitch.InlineMode = parseEswitchInlineMode(uint8(a.Value[0]))
- case nl.DEVLINK_ATTR_ESWITCH_ENCAP_MODE:
- d.Attrs.Eswitch.EncapMode = parseEswitchEncapMode(uint8(a.Value[0]))
- }
- }
- return nil
- }
- func (dev *DevlinkDevice) parseEswitchAttrs(msgs [][]byte) {
- m := msgs[0]
- attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:])
- if err != nil {
- return
- }
- dev.parseAttributes(attrs)
- }
- func (h *Handle) getEswitchAttrs(family *GenlFamily, dev *DevlinkDevice) {
- msg := &nl.Genlmsg{
- Command: nl.DEVLINK_CMD_ESWITCH_GET,
- Version: nl.GENL_DEVLINK_VERSION,
- }
- req := h.newNetlinkRequest(int(family.ID), unix.NLM_F_REQUEST|unix.NLM_F_ACK)
- req.AddData(msg)
- b := make([]byte, len(dev.BusName))
- copy(b, dev.BusName)
- data := nl.NewRtAttr(nl.DEVLINK_ATTR_BUS_NAME, b)
- req.AddData(data)
- b = make([]byte, len(dev.DeviceName))
- copy(b, dev.DeviceName)
- data = nl.NewRtAttr(nl.DEVLINK_ATTR_DEV_NAME, b)
- req.AddData(data)
- msgs, err := req.Execute(unix.NETLINK_GENERIC, 0)
- if err != nil {
- return
- }
- dev.parseEswitchAttrs(msgs)
- }
- // DevLinkGetDeviceList provides a pointer to devlink devices and nil error,
- // otherwise returns an error code.
- func (h *Handle) DevLinkGetDeviceList() ([]*DevlinkDevice, error) {
- f, err := h.GenlFamilyGet(nl.GENL_DEVLINK_NAME)
- if err != nil {
- return nil, err
- }
- msg := &nl.Genlmsg{
- Command: nl.DEVLINK_CMD_GET,
- Version: nl.GENL_DEVLINK_VERSION,
- }
- req := h.newNetlinkRequest(int(f.ID),
- unix.NLM_F_REQUEST|unix.NLM_F_ACK|unix.NLM_F_DUMP)
- req.AddData(msg)
- msgs, err := req.Execute(unix.NETLINK_GENERIC, 0)
- if err != nil {
- return nil, err
- }
- devices, err := parseDevLinkDeviceList(msgs)
- if err != nil {
- return nil, err
- }
- for _, d := range devices {
- h.getEswitchAttrs(f, d)
- }
- return devices, nil
- }
- // DevLinkGetDeviceList provides a pointer to devlink devices and nil error,
- // otherwise returns an error code.
- func DevLinkGetDeviceList() ([]*DevlinkDevice, error) {
- return pkgHandle.DevLinkGetDeviceList()
- }
- func parseDevlinkDevice(msgs [][]byte) (*DevlinkDevice, error) {
- m := msgs[0]
- attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:])
- if err != nil {
- return nil, err
- }
- dev := &DevlinkDevice{}
- if err = dev.parseAttributes(attrs); err != nil {
- return nil, err
- }
- return dev, nil
- }
- func (h *Handle) createCmdReq(cmd uint8, bus string, device string) (*GenlFamily, *nl.NetlinkRequest, error) {
- f, err := h.GenlFamilyGet(nl.GENL_DEVLINK_NAME)
- if err != nil {
- return nil, nil, err
- }
- msg := &nl.Genlmsg{
- Command: cmd,
- Version: nl.GENL_DEVLINK_VERSION,
- }
- req := h.newNetlinkRequest(int(f.ID),
- unix.NLM_F_REQUEST|unix.NLM_F_ACK)
- req.AddData(msg)
- b := make([]byte, len(bus)+1)
- copy(b, bus)
- data := nl.NewRtAttr(nl.DEVLINK_ATTR_BUS_NAME, b)
- req.AddData(data)
- b = make([]byte, len(device)+1)
- copy(b, device)
- data = nl.NewRtAttr(nl.DEVLINK_ATTR_DEV_NAME, b)
- req.AddData(data)
- return f, req, nil
- }
- // DevlinkGetDeviceByName provides a pointer to devlink device and nil error,
- // otherwise returns an error code.
- func (h *Handle) DevLinkGetDeviceByName(Bus string, Device string) (*DevlinkDevice, error) {
- f, req, err := h.createCmdReq(nl.DEVLINK_CMD_GET, Bus, Device)
- if err != nil {
- return nil, err
- }
- respmsg, err := req.Execute(unix.NETLINK_GENERIC, 0)
- if err != nil {
- return nil, err
- }
- dev, err := parseDevlinkDevice(respmsg)
- if err == nil {
- h.getEswitchAttrs(f, dev)
- }
- return dev, err
- }
- // DevlinkGetDeviceByName provides a pointer to devlink device and nil error,
- // otherwise returns an error code.
- func DevLinkGetDeviceByName(Bus string, Device string) (*DevlinkDevice, error) {
- return pkgHandle.DevLinkGetDeviceByName(Bus, Device)
- }
- // DevLinkSetEswitchMode sets eswitch mode if able to set successfully or
- // returns an error code.
- // Equivalent to: `devlink dev eswitch set $dev mode switchdev`
- // Equivalent to: `devlink dev eswitch set $dev mode legacy`
- func (h *Handle) DevLinkSetEswitchMode(Dev *DevlinkDevice, NewMode string) error {
- mode, err := eswitchStringToMode(NewMode)
- if err != nil {
- return err
- }
- _, req, err := h.createCmdReq(nl.DEVLINK_CMD_ESWITCH_SET, Dev.BusName, Dev.DeviceName)
- if err != nil {
- return err
- }
- req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_ESWITCH_MODE, nl.Uint16Attr(mode)))
- _, err = req.Execute(unix.NETLINK_GENERIC, 0)
- return err
- }
- // DevLinkSetEswitchMode sets eswitch mode if able to set successfully or
- // returns an error code.
- // Equivalent to: `devlink dev eswitch set $dev mode switchdev`
- // Equivalent to: `devlink dev eswitch set $dev mode legacy`
- func DevLinkSetEswitchMode(Dev *DevlinkDevice, NewMode string) error {
- return pkgHandle.DevLinkSetEswitchMode(Dev, NewMode)
- }
- func (port *DevlinkPort) parseAttributes(attrs []syscall.NetlinkRouteAttr) error {
- for _, a := range attrs {
- switch a.Attr.Type {
- case nl.DEVLINK_ATTR_BUS_NAME:
- port.BusName = string(a.Value)
- case nl.DEVLINK_ATTR_DEV_NAME:
- port.DeviceName = string(a.Value)
- case nl.DEVLINK_ATTR_PORT_INDEX:
- port.PortIndex = native.Uint32(a.Value)
- case nl.DEVLINK_ATTR_PORT_TYPE:
- port.PortType = native.Uint16(a.Value)
- case nl.DEVLINK_ATTR_PORT_NETDEV_NAME:
- port.NetdeviceName = string(a.Value)
- case nl.DEVLINK_ATTR_PORT_NETDEV_IFINDEX:
- port.NetdevIfIndex = native.Uint32(a.Value)
- case nl.DEVLINK_ATTR_PORT_IBDEV_NAME:
- port.RdmaDeviceName = string(a.Value)
- case nl.DEVLINK_ATTR_PORT_FLAVOUR:
- port.PortFlavour = native.Uint16(a.Value)
- }
- }
- return nil
- }
- func parseDevLinkAllPortList(msgs [][]byte) ([]*DevlinkPort, error) {
- ports := make([]*DevlinkPort, 0, len(msgs))
- for _, m := range msgs {
- attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:])
- if err != nil {
- return nil, err
- }
- port := &DevlinkPort{}
- if err = port.parseAttributes(attrs); err != nil {
- return nil, err
- }
- ports = append(ports, port)
- }
- return ports, nil
- }
- // DevLinkGetPortList provides a pointer to devlink ports and nil error,
- // otherwise returns an error code.
- func (h *Handle) DevLinkGetAllPortList() ([]*DevlinkPort, error) {
- f, err := h.GenlFamilyGet(nl.GENL_DEVLINK_NAME)
- if err != nil {
- return nil, err
- }
- msg := &nl.Genlmsg{
- Command: nl.DEVLINK_CMD_PORT_GET,
- Version: nl.GENL_DEVLINK_VERSION,
- }
- req := h.newNetlinkRequest(int(f.ID),
- unix.NLM_F_REQUEST|unix.NLM_F_ACK|unix.NLM_F_DUMP)
- req.AddData(msg)
- msgs, err := req.Execute(unix.NETLINK_GENERIC, 0)
- if err != nil {
- return nil, err
- }
- ports, err := parseDevLinkAllPortList(msgs)
- if err != nil {
- return nil, err
- }
- return ports, nil
- }
- // DevLinkGetPortList provides a pointer to devlink ports and nil error,
- // otherwise returns an error code.
- func DevLinkGetAllPortList() ([]*DevlinkPort, error) {
- return pkgHandle.DevLinkGetAllPortList()
- }
- func parseDevlinkPortMsg(msgs [][]byte) (*DevlinkPort, error) {
- m := msgs[0]
- attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:])
- if err != nil {
- return nil, err
- }
- port := &DevlinkPort{}
- if err = port.parseAttributes(attrs); err != nil {
- return nil, err
- }
- return port, nil
- }
- // DevLinkGetPortByIndexprovides a pointer to devlink device and nil error,
- // otherwise returns an error code.
- func (h *Handle) DevLinkGetPortByIndex(Bus string, Device string, PortIndex uint32) (*DevlinkPort, error) {
- _, req, err := h.createCmdReq(nl.DEVLINK_CMD_PORT_GET, Bus, Device)
- if err != nil {
- return nil, err
- }
- req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_INDEX, nl.Uint32Attr(PortIndex)))
- respmsg, err := req.Execute(unix.NETLINK_GENERIC, 0)
- if err != nil {
- return nil, err
- }
- port, err := parseDevlinkPortMsg(respmsg)
- return port, err
- }
- // DevLinkGetPortByIndex provides a pointer to devlink portand nil error,
- // otherwise returns an error code.
- func DevLinkGetPortByIndex(Bus string, Device string, PortIndex uint32) (*DevlinkPort, error) {
- return pkgHandle.DevLinkGetPortByIndex(Bus, Device, PortIndex)
- }
|