ethtool_cmd.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /*
  2. *
  3. * Licensed to the Apache Software Foundation (ASF) under one
  4. * or more contributor license agreements. See the NOTICE file
  5. * distributed with this work for additional information
  6. * regarding copyright ownership. The ASF licenses this file
  7. * to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance
  9. * with the License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing,
  14. * software distributed under the License is distributed on an
  15. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  16. * KIND, either express or implied. See the License for the
  17. * specific language governing permissions and limitations
  18. * under the License.
  19. *
  20. */
  21. // Package ethtool aims to provide a library giving a simple access to the
  22. // Linux SIOCETHTOOL ioctl operations. It can be used to retrieve informations
  23. // from a network device like statistics, driver related informations or
  24. // even the peer of a VETH interface.
  25. package ethtool
  26. import (
  27. "math"
  28. "reflect"
  29. "unsafe"
  30. "golang.org/x/sys/unix"
  31. )
  32. type EthtoolCmd struct { /* ethtool.c: struct ethtool_cmd */
  33. Cmd uint32
  34. Supported uint32
  35. Advertising uint32
  36. Speed uint16
  37. Duplex uint8
  38. Port uint8
  39. Phy_address uint8
  40. Transceiver uint8
  41. Autoneg uint8
  42. Mdio_support uint8
  43. Maxtxpkt uint32
  44. Maxrxpkt uint32
  45. Speed_hi uint16
  46. Eth_tp_mdix uint8
  47. Reserved2 uint8
  48. Lp_advertising uint32
  49. Reserved [2]uint32
  50. }
  51. // CmdGet returns the interface settings in the receiver struct
  52. // and returns speed
  53. func (ecmd *EthtoolCmd) CmdGet(intf string) (uint32, error) {
  54. e, err := NewEthtool()
  55. if err != nil {
  56. return 0, err
  57. }
  58. defer e.Close()
  59. return e.CmdGet(ecmd, intf)
  60. }
  61. // CmdSet sets and returns the settings in the receiver struct
  62. // and returns speed
  63. func (ecmd *EthtoolCmd) CmdSet(intf string) (uint32, error) {
  64. e, err := NewEthtool()
  65. if err != nil {
  66. return 0, err
  67. }
  68. defer e.Close()
  69. return e.CmdSet(ecmd, intf)
  70. }
  71. func (f *EthtoolCmd) reflect(retv *map[string]uint64) {
  72. val := reflect.ValueOf(f).Elem()
  73. for i := 0; i < val.NumField(); i++ {
  74. valueField := val.Field(i)
  75. typeField := val.Type().Field(i)
  76. t := valueField.Interface()
  77. //tt := reflect.TypeOf(t)
  78. //fmt.Printf(" t %T %v tt %T %v\n", t, t, tt, tt)
  79. switch t.(type) {
  80. case uint32:
  81. //fmt.Printf(" t is uint32\n")
  82. (*retv)[typeField.Name] = uint64(t.(uint32))
  83. case uint16:
  84. (*retv)[typeField.Name] = uint64(t.(uint16))
  85. case uint8:
  86. (*retv)[typeField.Name] = uint64(t.(uint8))
  87. case int32:
  88. (*retv)[typeField.Name] = uint64(t.(int32))
  89. case int16:
  90. (*retv)[typeField.Name] = uint64(t.(int16))
  91. case int8:
  92. (*retv)[typeField.Name] = uint64(t.(int8))
  93. default:
  94. (*retv)[typeField.Name+"_unknown_type"] = 0
  95. }
  96. //tag := typeField.Tag
  97. //fmt.Printf("Field Name: %s,\t Field Value: %v,\t Tag Value: %s\n",
  98. // typeField.Name, valueField.Interface(), tag.Get("tag_name"))
  99. }
  100. }
  101. // CmdGet returns the interface settings in the receiver struct
  102. // and returns speed
  103. func (e *Ethtool) CmdGet(ecmd *EthtoolCmd, intf string) (uint32, error) {
  104. ecmd.Cmd = ETHTOOL_GSET
  105. var name [IFNAMSIZ]byte
  106. copy(name[:], []byte(intf))
  107. ifr := ifreq{
  108. ifr_name: name,
  109. ifr_data: uintptr(unsafe.Pointer(ecmd)),
  110. }
  111. _, _, ep := unix.Syscall(unix.SYS_IOCTL, uintptr(e.fd),
  112. SIOCETHTOOL, uintptr(unsafe.Pointer(&ifr)))
  113. if ep != 0 {
  114. return 0, ep
  115. }
  116. var speedval uint32 = (uint32(ecmd.Speed_hi) << 16) |
  117. (uint32(ecmd.Speed) & 0xffff)
  118. if speedval == math.MaxUint16 {
  119. speedval = math.MaxUint32
  120. }
  121. return speedval, nil
  122. }
  123. // CmdSet sets and returns the settings in the receiver struct
  124. // and returns speed
  125. func (e *Ethtool) CmdSet(ecmd *EthtoolCmd, intf string) (uint32, error) {
  126. ecmd.Cmd = ETHTOOL_SSET
  127. var name [IFNAMSIZ]byte
  128. copy(name[:], []byte(intf))
  129. ifr := ifreq{
  130. ifr_name: name,
  131. ifr_data: uintptr(unsafe.Pointer(ecmd)),
  132. }
  133. _, _, ep := unix.Syscall(unix.SYS_IOCTL, uintptr(e.fd),
  134. SIOCETHTOOL, uintptr(unsafe.Pointer(&ifr)))
  135. if ep != 0 {
  136. return 0, unix.Errno(ep)
  137. }
  138. var speedval uint32 = (uint32(ecmd.Speed_hi) << 16) |
  139. (uint32(ecmd.Speed) & 0xffff)
  140. if speedval == math.MaxUint16 {
  141. speedval = math.MaxUint32
  142. }
  143. return speedval, nil
  144. }
  145. // CmdGetMapped returns the interface settings in a map
  146. func (e *Ethtool) CmdGetMapped(intf string) (map[string]uint64, error) {
  147. ecmd := EthtoolCmd{
  148. Cmd: ETHTOOL_GSET,
  149. }
  150. var name [IFNAMSIZ]byte
  151. copy(name[:], []byte(intf))
  152. ifr := ifreq{
  153. ifr_name: name,
  154. ifr_data: uintptr(unsafe.Pointer(&ecmd)),
  155. }
  156. _, _, ep := unix.Syscall(unix.SYS_IOCTL, uintptr(e.fd),
  157. SIOCETHTOOL, uintptr(unsafe.Pointer(&ifr)))
  158. if ep != 0 {
  159. return nil, ep
  160. }
  161. var result = make(map[string]uint64)
  162. // ref https://gist.github.com/drewolson/4771479
  163. // Golang Reflection Example
  164. ecmd.reflect(&result)
  165. var speedval uint32 = (uint32(ecmd.Speed_hi) << 16) |
  166. (uint32(ecmd.Speed) & 0xffff)
  167. result["speed"] = uint64(speedval)
  168. return result, nil
  169. }
  170. func CmdGetMapped(intf string) (map[string]uint64, error) {
  171. e, err := NewEthtool()
  172. if err != nil {
  173. return nil, err
  174. }
  175. defer e.Close()
  176. return e.CmdGetMapped(intf)
  177. }