go.ligato.io/vpp-agent/v3@v3.5.0/plugins/linux/ifplugin/linuxcalls/ethtool_linuxcalls.go (about) 1 // Copyright (c) 2018 Cisco and/or its affiliates. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at: 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 //go:build !windows && !darwin 16 17 package linuxcalls 18 19 import ( 20 "fmt" 21 "syscall" 22 "unsafe" 23 ) 24 25 const ( 26 siocEthtool = 0x8946 // linux/sockios.h 27 28 ethtoolGRxCsum = 0x00000014 // linux/ethtool.h 29 ethtoolSRxCsum = 0x00000015 // linux/ethtool.h 30 31 ethtoolGTxCsum = 0x00000016 // linux/ethtool.h 32 ethtoolSTxCsum = 0x00000017 // linux/ethtool.h 33 34 maxIfNameSize = 16 // linux/if.h 35 ) 36 37 // linux/if.h 'struct ifreq' 38 type ifreq struct { 39 Name [maxIfNameSize]byte 40 Data uintptr 41 } 42 43 // linux/ethtool.h 'struct ethtool_value' 44 type ethtoolValue struct { 45 Cmd uint32 46 Data uint32 47 } 48 49 // GetChecksumOffloading returns the state of Rx/Tx checksum offloading 50 // for the given interface. 51 func (h *NetLinkHandler) GetChecksumOffloading(ifName string) (rxOn, txOn bool, err error) { 52 rxVal, err := ethtool(ifName, ethtoolGRxCsum, 0) 53 if err != nil { 54 return 55 } 56 txVal, err := ethtool(ifName, ethtoolGTxCsum, 0) 57 if err != nil { 58 return 59 } 60 return rxVal != 0, txVal != 0, nil 61 } 62 63 // SetChecksumOffloading enables/disables Rx/Tx checksum offloading 64 // for the given interface. 65 func (h *NetLinkHandler) SetChecksumOffloading(ifName string, rxOn, txOn bool) error { 66 var rxVal, txVal uint32 67 if rxOn { 68 rxVal = 1 69 } 70 if txOn { 71 txVal = 1 72 } 73 _, err := ethtool(ifName, ethtoolSRxCsum, rxVal) 74 if err != nil { 75 return err 76 } 77 _, err = ethtool(ifName, ethtoolSTxCsum, txVal) 78 return err 79 } 80 81 // ethtool executes Linux ethtool syscall. 82 func ethtool(iface string, cmd, val uint32) (retval uint32, err error) { 83 if len(iface)+1 > maxIfNameSize { 84 return 0, fmt.Errorf("interface name is too long") 85 } 86 socket, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, 0) 87 if err != nil { 88 return 0, err 89 } 90 defer syscall.Close(socket) 91 92 // prepare ethtool request 93 value := ethtoolValue{cmd, val} 94 request := ifreq{Data: uintptr(unsafe.Pointer(&value))} 95 copy(request.Name[:], iface) 96 97 // ioctl system call 98 _, _, errno := syscall.RawSyscall(syscall.SYS_IOCTL, uintptr(socket), uintptr(siocEthtool), 99 uintptr(unsafe.Pointer(&request))) 100 if errno != 0 { 101 return 0, errno 102 } 103 return value.Data, nil 104 }