summaryrefslogtreecommitdiff
path: root/vendor/github.com/vishvananda/netlink/devlink_linux.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/vishvananda/netlink/devlink_linux.go')
-rw-r--r--vendor/github.com/vishvananda/netlink/devlink_linux.go272
1 files changed, 272 insertions, 0 deletions
diff --git a/vendor/github.com/vishvananda/netlink/devlink_linux.go b/vendor/github.com/vishvananda/netlink/devlink_linux.go
new file mode 100644
index 000000000..29b3f8ec1
--- /dev/null
+++ b/vendor/github.com/vishvananda/netlink/devlink_linux.go
@@ -0,0 +1,272 @@
+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
+}
+
+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)
+}