update ethtool

This commit is contained in:
Nathan Gieseker 2019-06-18 12:55:00 -07:00
parent e8c953999e
commit addbcd34b4
8 changed files with 357 additions and 39 deletions

2
go.mod
View File

@ -19,7 +19,7 @@ require (
github.com/mattn/go-shellwords v1.0.3 github.com/mattn/go-shellwords v1.0.3
github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a
github.com/safchain/ethtool v0.0.0-20170622225139-7ff1ba29eca2 github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8
github.com/sirupsen/logrus v1.0.6 // indirect github.com/sirupsen/logrus v1.0.6 // indirect
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc // indirect github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc // indirect

2
go.sum
View File

@ -36,6 +36,8 @@ github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a h1:KfNOeFvoAssuZLT7Int
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/safchain/ethtool v0.0.0-20170622225139-7ff1ba29eca2 h1:f10KcdY8NPt2w0/M2o+O9uCiH8sHpS6OVAHcf4BPL7Y= github.com/safchain/ethtool v0.0.0-20170622225139-7ff1ba29eca2 h1:f10KcdY8NPt2w0/M2o+O9uCiH8sHpS6OVAHcf4BPL7Y=
github.com/safchain/ethtool v0.0.0-20170622225139-7ff1ba29eca2/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= github.com/safchain/ethtool v0.0.0-20170622225139-7ff1ba29eca2/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8 h1:2c1EFnZHIPCW8qKWgHMH/fX2PkSabFc5mrVzfUNdg5U=
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
github.com/sirupsen/logrus v1.0.6 h1:hcP1GmhGigz/O7h1WVUM5KklBp1JoNS9FggWKdj/j3s= github.com/sirupsen/logrus v1.0.6 h1:hcP1GmhGigz/O7h1WVUM5KklBp1JoNS9FggWKdj/j3s=
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf h1:3J37+NPjNyGW/dbfXtj3yWuF9OEepIdGOXRaJGbORV8= github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf h1:3J37+NPjNyGW/dbfXtj3yWuF9OEepIdGOXRaJGbORV8=

View File

@ -22,3 +22,6 @@ _testmain.go
*.exe *.exe
*.test *.test
*.prof *.prof
# Skip compiled example binary file
/example/example

4
vendor/github.com/safchain/ethtool/Makefile generated vendored Normal file
View File

@ -0,0 +1,4 @@
all: build
build:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build

View File

@ -33,6 +33,7 @@ func main() {
if err != nil { if err != nil {
panic(err.Error()) panic(err.Error())
} }
defer ethHandle.Close()
// Retrieve tx from eth0 // Retrieve tx from eth0
stats, err := ethHandle.Stats("eth0") stats, err := ethHandle.Stats("eth0")

View File

@ -27,7 +27,9 @@ package ethtool
import ( import (
"bytes" "bytes"
"encoding/hex"
"fmt" "fmt"
"strings"
"syscall" "syscall"
"unsafe" "unsafe"
) )
@ -46,20 +48,34 @@ const (
const ( const (
ETH_GSTRING_LEN = 32 ETH_GSTRING_LEN = 32
ETH_SS_STATS = 1 ETH_SS_STATS = 1
ETH_SS_FEATURES = 4
ETHTOOL_GDRVINFO = 0x00000003 ETHTOOL_GDRVINFO = 0x00000003
ETHTOOL_GSTRINGS = 0x0000001b ETHTOOL_GSTRINGS = 0x0000001b
ETHTOOL_GSTATS = 0x0000001d ETHTOOL_GSTATS = 0x0000001d
// other CMDs from ethtool-copy.h of ethtool-3.5 package // other CMDs from ethtool-copy.h of ethtool-3.5 package
ETHTOOL_GSET = 0x00000001 /* Get settings. */ ETHTOOL_GSET = 0x00000001 /* Get settings. */
ETHTOOL_SSET = 0x00000002 /* Set settings. */ ETHTOOL_SSET = 0x00000002 /* Set settings. */
ETHTOOL_GMSGLVL = 0x00000007 /* Get driver message level */ ETHTOOL_GMSGLVL = 0x00000007 /* Get driver message level */
ETHTOOL_SMSGLVL = 0x00000008 /* Set driver msg level. */ ETHTOOL_SMSGLVL = 0x00000008 /* Set driver msg level. */
/* Get link status for host, i.e. whether the interface *and* the
* physical port (if there is one) are up (ethtool_value). */
ETHTOOL_GLINK = 0x0000000a
ETHTOOL_GMODULEINFO = 0x00000042 /* Get plug-in module information */
ETHTOOL_GMODULEEEPROM = 0x00000043 /* Get plug-in module eeprom */
ETHTOOL_GPERMADDR = 0x00000020
ETHTOOL_GFEATURES = 0x0000003a /* Get device offload settings */
ETHTOOL_SFEATURES = 0x0000003b /* Change device offload settings */
ETHTOOL_GFLAGS = 0x00000025 /* Get flags bitmap(ethtool_value) */
ETHTOOL_GSSET_INFO = 0x00000037 /* Get string set info */
) )
// MAX_GSTRINGS maximum number of stats entries that ethtool can // MAX_GSTRINGS maximum number of stats entries that ethtool can
// retrieve currently. // retrieve currently.
const ( const (
MAX_GSTRINGS = 1000 MAX_GSTRINGS = 1000
MAX_FEATURE_BLOCKS = (MAX_GSTRINGS + 32 - 1) / 32
EEPROM_LEN = 640
PERMADDR_LEN = 32
) )
type ifreq struct { type ifreq struct {
@ -67,6 +83,38 @@ type ifreq struct {
ifr_data uintptr ifr_data uintptr
} }
// following structures comes from uapi/linux/ethtool.h
type ethtoolSsetInfo struct {
cmd uint32
reserved uint32
sset_mask uint32
data uintptr
}
type ethtoolGetFeaturesBlock struct {
available uint32
requested uint32
active uint32
never_changed uint32
}
type ethtoolGfeatures struct {
cmd uint32
size uint32
blocks [MAX_FEATURE_BLOCKS]ethtoolGetFeaturesBlock
}
type ethtoolSetFeaturesBlock struct {
valid uint32
requested uint32
}
type ethtoolSfeatures struct {
cmd uint32
size uint32
blocks [MAX_FEATURE_BLOCKS]ethtoolSetFeaturesBlock
}
type ethtoolDrvInfo struct { type ethtoolDrvInfo struct {
cmd uint32 cmd uint32
driver [32]byte driver [32]byte
@ -95,11 +143,37 @@ type ethtoolStats struct {
data [MAX_GSTRINGS]uint64 data [MAX_GSTRINGS]uint64
} }
type ethtoolEeprom struct {
cmd uint32
magic uint32
offset uint32
len uint32
data [EEPROM_LEN]byte
}
type ethtoolModInfo struct {
cmd uint32
tpe uint32
eeprom_len uint32
reserved [8]uint32
}
type ethtoolLink struct {
cmd uint32
data uint32
}
type ethtoolPermAddr struct {
cmd uint32
size uint32
data [PERMADDR_LEN]byte
}
type Ethtool struct { type Ethtool struct {
fd int fd int
} }
// DriverName returns the driver name of the given interface. // DriverName returns the driver name of the given interface name.
func (e *Ethtool) DriverName(intf string) (string, error) { func (e *Ethtool) DriverName(intf string) (string, error) {
info, err := e.getDriverInfo(intf) info, err := e.getDriverInfo(intf)
if err != nil { if err != nil {
@ -108,7 +182,7 @@ func (e *Ethtool) DriverName(intf string) (string, error) {
return string(bytes.Trim(info.driver[:], "\x00")), nil return string(bytes.Trim(info.driver[:], "\x00")), nil
} }
// BusInfo returns the bus info of the given interface. // BusInfo returns the bus information of the given interface name.
func (e *Ethtool) BusInfo(intf string) (string, error) { func (e *Ethtool) BusInfo(intf string) (string, error) {
info, err := e.getDriverInfo(intf) info, err := e.getDriverInfo(intf)
if err != nil { if err != nil {
@ -117,44 +191,259 @@ func (e *Ethtool) BusInfo(intf string) (string, error) {
return string(bytes.Trim(info.bus_info[:], "\x00")), nil return string(bytes.Trim(info.bus_info[:], "\x00")), nil
} }
func (e *Ethtool) getDriverInfo(intf string) (ethtoolDrvInfo, error) { // ModuleEeprom returns Eeprom information of the given interface name.
drvinfo := ethtoolDrvInfo{ func (e *Ethtool) ModuleEeprom(intf string) ([]byte, error) {
cmd: ETHTOOL_GDRVINFO, eeprom, _, err := e.getModuleEeprom(intf)
if err != nil {
return nil, err
} }
return eeprom.data[:eeprom.len], nil
}
// ModuleEeprom returns Eeprom information of the given interface name.
func (e *Ethtool) ModuleEepromHex(intf string) (string, error) {
eeprom, _, err := e.getModuleEeprom(intf)
if err != nil {
return "", err
}
return hex.EncodeToString(eeprom.data[:eeprom.len]), nil
}
// DriverInfo returns driver information of the given interface name.
func (e *Ethtool) DriverInfo(intf string) (ethtoolDrvInfo, error) {
drvInfo, err := e.getDriverInfo(intf)
if err != nil {
return ethtoolDrvInfo{}, err
}
return drvInfo, nil
}
// PermAddr returns permanent address of the given interface name.
func (e *Ethtool) PermAddr(intf string) (string, error) {
permAddr, err := e.getPermAddr(intf)
if err != nil {
return "", err
}
if permAddr.data[0] == 0 && permAddr.data[1] == 0 &&
permAddr.data[2] == 0 && permAddr.data[3] == 0 &&
permAddr.data[4] == 0 && permAddr.data[5] == 0 {
return "", nil
}
return fmt.Sprintf("%x:%x:%x:%x:%x:%x",
permAddr.data[0:1],
permAddr.data[1:2],
permAddr.data[2:3],
permAddr.data[3:4],
permAddr.data[4:5],
permAddr.data[5:6],
), nil
}
func (e *Ethtool) ioctl(intf string, data uintptr) error {
var name [IFNAMSIZ]byte var name [IFNAMSIZ]byte
copy(name[:], []byte(intf)) copy(name[:], []byte(intf))
ifr := ifreq{ ifr := ifreq{
ifr_name: name, ifr_name: name,
ifr_data: uintptr(unsafe.Pointer(&drvinfo)), ifr_data: data,
} }
_, _, ep := syscall.Syscall(syscall.SYS_IOCTL, uintptr(e.fd), SIOCETHTOOL, uintptr(unsafe.Pointer(&ifr))) _, _, ep := syscall.Syscall(syscall.SYS_IOCTL, uintptr(e.fd), SIOCETHTOOL, uintptr(unsafe.Pointer(&ifr)))
if ep != 0 { if ep != 0 {
return ethtoolDrvInfo{}, syscall.Errno(ep) return syscall.Errno(ep)
}
return nil
}
func (e *Ethtool) getDriverInfo(intf string) (ethtoolDrvInfo, error) {
drvinfo := ethtoolDrvInfo{
cmd: ETHTOOL_GDRVINFO,
}
if err := e.ioctl(intf, uintptr(unsafe.Pointer(&drvinfo))); err != nil {
return ethtoolDrvInfo{}, err
} }
return drvinfo, nil return drvinfo, nil
} }
func (e *Ethtool) getPermAddr(intf string) (ethtoolPermAddr, error) {
permAddr := ethtoolPermAddr{
cmd: ETHTOOL_GPERMADDR,
size: PERMADDR_LEN,
}
if err := e.ioctl(intf, uintptr(unsafe.Pointer(&permAddr))); err != nil {
return ethtoolPermAddr{}, err
}
return permAddr, nil
}
func (e *Ethtool) getModuleEeprom(intf string) (ethtoolEeprom, ethtoolModInfo, error) {
modInfo := ethtoolModInfo{
cmd: ETHTOOL_GMODULEINFO,
}
if err := e.ioctl(intf, uintptr(unsafe.Pointer(&modInfo))); err != nil {
return ethtoolEeprom{}, ethtoolModInfo{}, err
}
eeprom := ethtoolEeprom{
cmd: ETHTOOL_GMODULEEEPROM,
len: modInfo.eeprom_len,
offset: 0,
}
if modInfo.eeprom_len > EEPROM_LEN {
return ethtoolEeprom{}, ethtoolModInfo{}, fmt.Errorf("eeprom size: %d is larger than buffer size: %d", modInfo.eeprom_len, EEPROM_LEN)
}
if err := e.ioctl(intf, uintptr(unsafe.Pointer(&eeprom))); err != nil {
return ethtoolEeprom{}, ethtoolModInfo{}, err
}
return eeprom, modInfo, nil
}
func isFeatureBitSet(blocks [MAX_FEATURE_BLOCKS]ethtoolGetFeaturesBlock, index uint) bool {
return (blocks)[index/32].active&(1<<(index%32)) != 0
}
func setFeatureBit(blocks *[MAX_FEATURE_BLOCKS]ethtoolSetFeaturesBlock, index uint, value bool) {
blockIndex, bitIndex := index/32, index%32
blocks[blockIndex].valid |= 1 << bitIndex
if value {
blocks[blockIndex].requested |= 1 << bitIndex
} else {
blocks[blockIndex].requested &= ^(1 << bitIndex)
}
}
// FeatureNames shows supported features by their name.
func (e *Ethtool) FeatureNames(intf string) (map[string]uint, error) {
ssetInfo := ethtoolSsetInfo{
cmd: ETHTOOL_GSSET_INFO,
sset_mask: 1 << ETH_SS_FEATURES,
}
if err := e.ioctl(intf, uintptr(unsafe.Pointer(&ssetInfo))); err != nil {
return nil, err
}
length := uint32(ssetInfo.data)
if length == 0 {
return map[string]uint{}, nil
} else if length > MAX_GSTRINGS {
return nil, fmt.Errorf("ethtool currently doesn't support more than %d entries, received %d", MAX_GSTRINGS, length)
}
gstrings := ethtoolGStrings{
cmd: ETHTOOL_GSTRINGS,
string_set: ETH_SS_FEATURES,
len: length,
data: [MAX_GSTRINGS * ETH_GSTRING_LEN]byte{},
}
if err := e.ioctl(intf, uintptr(unsafe.Pointer(&gstrings))); err != nil {
return nil, err
}
var result = make(map[string]uint)
for i := 0; i != int(length); i++ {
b := gstrings.data[i*ETH_GSTRING_LEN : i*ETH_GSTRING_LEN+ETH_GSTRING_LEN]
key := string(bytes.Trim(b, "\x00"))
if key != "" {
result[key] = uint(i)
}
}
return result, nil
}
// Features retrieves features of the given interface name.
func (e *Ethtool) Features(intf string) (map[string]bool, error) {
names, err := e.FeatureNames(intf)
if err != nil {
return nil, err
}
length := uint32(len(names))
if length == 0 {
return map[string]bool{}, nil
}
features := ethtoolGfeatures{
cmd: ETHTOOL_GFEATURES,
size: (length + 32 - 1) / 32,
}
if err := e.ioctl(intf, uintptr(unsafe.Pointer(&features))); err != nil {
return nil, err
}
var result = make(map[string]bool, length)
for key, index := range names {
result[key] = isFeatureBitSet(features.blocks, index)
}
return result, nil
}
// Change requests a change in the given device's features.
func (e *Ethtool) Change(intf string, config map[string]bool) error {
names, err := e.FeatureNames(intf)
if err != nil {
return err
}
length := uint32(len(names))
features := ethtoolSfeatures{
cmd: ETHTOOL_SFEATURES,
size: (length + 32 - 1) / 32,
}
for key, value := range config {
if index, ok := names[key]; ok {
setFeatureBit(&features.blocks, index, value)
} else {
return fmt.Errorf("unsupported feature %q", key)
}
}
return e.ioctl(intf, uintptr(unsafe.Pointer(&features)))
}
// Get state of a link.
func (e *Ethtool) LinkState(intf string) (uint32, error) {
x := ethtoolLink{
cmd: ETHTOOL_GLINK,
}
if err := e.ioctl(intf, uintptr(unsafe.Pointer(&x))); err != nil {
return 0, err
}
return x.data, nil
}
// Stats retrieves stats of the given interface name. // Stats retrieves stats of the given interface name.
func (e *Ethtool) Stats(intf string) (map[string]uint64, error) { func (e *Ethtool) Stats(intf string) (map[string]uint64, error) {
drvinfo := ethtoolDrvInfo{ drvinfo := ethtoolDrvInfo{
cmd: ETHTOOL_GDRVINFO, cmd: ETHTOOL_GDRVINFO,
} }
var name [IFNAMSIZ]byte if err := e.ioctl(intf, uintptr(unsafe.Pointer(&drvinfo))); err != nil {
copy(name[:], []byte(intf)) return nil, err
ifr := ifreq{
ifr_name: name,
ifr_data: uintptr(unsafe.Pointer(&drvinfo)),
}
_, _, ep := syscall.Syscall(syscall.SYS_IOCTL, uintptr(e.fd), SIOCETHTOOL, uintptr(unsafe.Pointer(&ifr)))
if ep != 0 {
return nil, syscall.Errno(ep)
} }
if drvinfo.n_stats*ETH_GSTRING_LEN > MAX_GSTRINGS*ETH_GSTRING_LEN { if drvinfo.n_stats*ETH_GSTRING_LEN > MAX_GSTRINGS*ETH_GSTRING_LEN {
@ -167,11 +456,9 @@ func (e *Ethtool) Stats(intf string) (map[string]uint64, error) {
len: drvinfo.n_stats, len: drvinfo.n_stats,
data: [MAX_GSTRINGS * ETH_GSTRING_LEN]byte{}, data: [MAX_GSTRINGS * ETH_GSTRING_LEN]byte{},
} }
ifr.ifr_data = uintptr(unsafe.Pointer(&gstrings))
_, _, ep = syscall.Syscall(syscall.SYS_IOCTL, uintptr(e.fd), SIOCETHTOOL, uintptr(unsafe.Pointer(&ifr))) if err := e.ioctl(intf, uintptr(unsafe.Pointer(&gstrings))); err != nil {
if ep != 0 { return nil, err
return nil, syscall.Errno(ep)
} }
stats := ethtoolStats{ stats := ethtoolStats{
@ -180,31 +467,32 @@ func (e *Ethtool) Stats(intf string) (map[string]uint64, error) {
data: [MAX_GSTRINGS]uint64{}, data: [MAX_GSTRINGS]uint64{},
} }
ifr.ifr_data = uintptr(unsafe.Pointer(&stats)) if err := e.ioctl(intf, uintptr(unsafe.Pointer(&stats))); err != nil {
return nil, err
_, _, ep = syscall.Syscall(syscall.SYS_IOCTL, uintptr(e.fd), SIOCETHTOOL, uintptr(unsafe.Pointer(&ifr)))
if ep != 0 {
return nil, syscall.Errno(ep)
} }
var result = make(map[string]uint64) var result = make(map[string]uint64)
for i := 0; i != int(drvinfo.n_stats); i++ { for i := 0; i != int(drvinfo.n_stats); i++ {
b := gstrings.data[i*ETH_GSTRING_LEN : i*ETH_GSTRING_LEN+ETH_GSTRING_LEN] b := gstrings.data[i*ETH_GSTRING_LEN : i*ETH_GSTRING_LEN+ETH_GSTRING_LEN]
key := string(bytes.Trim(b, "\x00")) key := string(b[:strings.Index(string(b), "\x00")])
result[key] = stats.data[i] if len(key) != 0 {
result[key] = stats.data[i]
}
} }
return result, nil return result, nil
} }
// Close closes the ethool handler
func (e *Ethtool) Close() { func (e *Ethtool) Close() {
syscall.Close(e.fd) syscall.Close(e.fd)
} }
// NewEthtool returns a new ethtool handler
func NewEthtool() (*Ethtool, error) { func NewEthtool() (*Ethtool, error) {
fd, _, err := syscall.RawSyscall(syscall.SYS_SOCKET, syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_IP) fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_IP)
if err != 0 { if err != nil {
return nil, syscall.Errno(err) return nil, err
} }
return &Ethtool{ return &Ethtool{
@ -212,6 +500,7 @@ func NewEthtool() (*Ethtool, error) {
}, nil }, nil
} }
// BusInfo returns bus information of the given interface name.
func BusInfo(intf string) (string, error) { func BusInfo(intf string) (string, error) {
e, err := NewEthtool() e, err := NewEthtool()
if err != nil { if err != nil {
@ -221,6 +510,7 @@ func BusInfo(intf string) (string, error) {
return e.BusInfo(intf) return e.BusInfo(intf)
} }
// DriverName returns the driver name of the given interface name.
func DriverName(intf string) (string, error) { func DriverName(intf string) (string, error) {
e, err := NewEthtool() e, err := NewEthtool()
if err != nil { if err != nil {
@ -230,6 +520,7 @@ func DriverName(intf string) (string, error) {
return e.DriverName(intf) return e.DriverName(intf)
} }
// Stats retrieves stats of the given interface name.
func Stats(intf string) (map[string]uint64, error) { func Stats(intf string) (map[string]uint64, error) {
e, err := NewEthtool() e, err := NewEthtool()
if err != nil { if err != nil {
@ -238,3 +529,13 @@ func Stats(intf string) (map[string]uint64, error) {
defer e.Close() defer e.Close()
return e.Stats(intf) return e.Stats(intf)
} }
// PermAddr returns permanent address of the given interface name.
func PermAddr(intf string) (string, error) {
e, err := NewEthtool()
if err != nil {
return "", err
}
defer e.Close()
return e.PermAddr(intf)
}

View File

@ -26,6 +26,7 @@
package ethtool package ethtool
import ( import (
"math"
"reflect" "reflect"
"syscall" "syscall"
"unsafe" "unsafe"
@ -128,6 +129,9 @@ func (e *Ethtool) CmdGet(ecmd *EthtoolCmd, intf string) (uint32, error) {
var speedval uint32 = (uint32(ecmd.Speed_hi) << 16) | var speedval uint32 = (uint32(ecmd.Speed_hi) << 16) |
(uint32(ecmd.Speed) & 0xffff) (uint32(ecmd.Speed) & 0xffff)
if speedval == math.MaxUint16 {
speedval = math.MaxUint32
}
return speedval, nil return speedval, nil
} }
@ -153,6 +157,9 @@ func (e *Ethtool) CmdSet(ecmd *EthtoolCmd, intf string) (uint32, error) {
var speedval uint32 = (uint32(ecmd.Speed_hi) << 16) | var speedval uint32 = (uint32(ecmd.Speed_hi) << 16) |
(uint32(ecmd.Speed) & 0xffff) (uint32(ecmd.Speed) & 0xffff)
if speedval == math.MaxUint16 {
speedval = math.MaxUint32
}
return speedval, nil return speedval, nil
} }

2
vendor/modules.txt vendored
View File

@ -84,7 +84,7 @@ github.com/onsi/gomega/matchers/support/goraph/bipartitegraph
github.com/onsi/gomega/matchers/support/goraph/edge github.com/onsi/gomega/matchers/support/goraph/edge
github.com/onsi/gomega/matchers/support/goraph/node github.com/onsi/gomega/matchers/support/goraph/node
github.com/onsi/gomega/matchers/support/goraph/util github.com/onsi/gomega/matchers/support/goraph/util
# github.com/safchain/ethtool v0.0.0-20170622225139-7ff1ba29eca2 # github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8
github.com/safchain/ethtool github.com/safchain/ethtool
# github.com/sirupsen/logrus v1.0.6 # github.com/sirupsen/logrus v1.0.6
github.com/sirupsen/logrus github.com/sirupsen/logrus