rdma_link_linux.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. package netlink
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "fmt"
  6. "net"
  7. "github.com/vishvananda/netlink/nl"
  8. "golang.org/x/sys/unix"
  9. )
  10. // LinkAttrs represents data shared by most link types
  11. type RdmaLinkAttrs struct {
  12. Index uint32
  13. Name string
  14. FirmwareVersion string
  15. NodeGuid string
  16. SysImageGuid string
  17. }
  18. // Link represents a rdma device from netlink.
  19. type RdmaLink struct {
  20. Attrs RdmaLinkAttrs
  21. }
  22. func getProtoField(clientType int, op int) int {
  23. return ((clientType << nl.RDMA_NL_GET_CLIENT_SHIFT) | op)
  24. }
  25. func uint64ToGuidString(guid uint64) string {
  26. //Convert to byte array
  27. sysGuidBytes := new(bytes.Buffer)
  28. binary.Write(sysGuidBytes, binary.LittleEndian, guid)
  29. //Convert to HardwareAddr
  30. sysGuidNet := net.HardwareAddr(sysGuidBytes.Bytes())
  31. //Get the String
  32. return sysGuidNet.String()
  33. }
  34. func executeOneGetRdmaLink(data []byte) (*RdmaLink, error) {
  35. link := RdmaLink{}
  36. reader := bytes.NewReader(data)
  37. for reader.Len() >= 4 {
  38. _, attrType, len, value := parseNfAttrTLV(reader)
  39. switch attrType {
  40. case nl.RDMA_NLDEV_ATTR_DEV_INDEX:
  41. var Index uint32
  42. r := bytes.NewReader(value)
  43. binary.Read(r, nl.NativeEndian(), &Index)
  44. link.Attrs.Index = Index
  45. case nl.RDMA_NLDEV_ATTR_DEV_NAME:
  46. link.Attrs.Name = string(value[0 : len-1])
  47. case nl.RDMA_NLDEV_ATTR_FW_VERSION:
  48. link.Attrs.FirmwareVersion = string(value[0 : len-1])
  49. case nl.RDMA_NLDEV_ATTR_NODE_GUID:
  50. var guid uint64
  51. r := bytes.NewReader(value)
  52. binary.Read(r, nl.NativeEndian(), &guid)
  53. link.Attrs.NodeGuid = uint64ToGuidString(guid)
  54. case nl.RDMA_NLDEV_ATTR_SYS_IMAGE_GUID:
  55. var sysGuid uint64
  56. r := bytes.NewReader(value)
  57. binary.Read(r, nl.NativeEndian(), &sysGuid)
  58. link.Attrs.SysImageGuid = uint64ToGuidString(sysGuid)
  59. }
  60. if (len % 4) != 0 {
  61. // Skip pad bytes
  62. reader.Seek(int64(4-(len%4)), seekCurrent)
  63. }
  64. }
  65. return &link, nil
  66. }
  67. func execRdmaGetLink(req *nl.NetlinkRequest, name string) (*RdmaLink, error) {
  68. msgs, err := req.Execute(unix.NETLINK_RDMA, 0)
  69. if err != nil {
  70. return nil, err
  71. }
  72. for _, m := range msgs {
  73. link, err := executeOneGetRdmaLink(m)
  74. if err != nil {
  75. return nil, err
  76. }
  77. if link.Attrs.Name == name {
  78. return link, nil
  79. }
  80. }
  81. return nil, fmt.Errorf("Rdma device %v not found", name)
  82. }
  83. func execRdmaSetLink(req *nl.NetlinkRequest) error {
  84. _, err := req.Execute(unix.NETLINK_RDMA, 0)
  85. return err
  86. }
  87. // RdmaLinkByName finds a link by name and returns a pointer to the object if
  88. // found and nil error, otherwise returns error code.
  89. func RdmaLinkByName(name string) (*RdmaLink, error) {
  90. return pkgHandle.RdmaLinkByName(name)
  91. }
  92. // RdmaLinkByName finds a link by name and returns a pointer to the object if
  93. // found and nil error, otherwise returns error code.
  94. func (h *Handle) RdmaLinkByName(name string) (*RdmaLink, error) {
  95. proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_GET)
  96. req := h.newNetlinkRequest(proto, unix.NLM_F_ACK|unix.NLM_F_DUMP)
  97. return execRdmaGetLink(req, name)
  98. }
  99. // RdmaLinkSetName sets the name of the rdma link device. Return nil on success
  100. // or error otherwise.
  101. // Equivalent to: `rdma dev set $old_devname name $name`
  102. func RdmaLinkSetName(link *RdmaLink, name string) error {
  103. return pkgHandle.RdmaLinkSetName(link, name)
  104. }
  105. // RdmaLinkSetName sets the name of the rdma link device. Return nil on success
  106. // or error otherwise.
  107. // Equivalent to: `rdma dev set $old_devname name $name`
  108. func (h *Handle) RdmaLinkSetName(link *RdmaLink, name string) error {
  109. proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_SET)
  110. req := h.newNetlinkRequest(proto, unix.NLM_F_ACK)
  111. b := make([]byte, 4)
  112. native.PutUint32(b, uint32(link.Attrs.Index))
  113. data := nl.NewRtAttr(nl.RDMA_NLDEV_ATTR_DEV_INDEX, b)
  114. req.AddData(data)
  115. b = make([]byte, len(name)+1)
  116. copy(b, name)
  117. data = nl.NewRtAttr(nl.RDMA_NLDEV_ATTR_DEV_NAME, b)
  118. req.AddData(data)
  119. return execRdmaSetLink(req)
  120. }