package net import "fmt" import "syscall" import "unsafe" const ( SIOCETHTOOL = 0x8946 // linux/sockios.h ETHTOOL_GTXCSUM = 0x00000016 // linux/ethtool.h ETHTOOL_STXCSUM = 0x00000017 // linux/ethtool.h IFNAMSIZ = 16 // linux/if.h ) // linux/if.h 'struct ifreq' type IFReqData struct { Name [IFNAMSIZ]byte Data uintptr } // linux/ethtool.h 'struct ethtool_value' type EthtoolValue struct { Cmd uint32 Data uint32 } func ioctlEthtool(fd int, argp uintptr) error { _, _, errno := syscall.RawSyscall(syscall.SYS_IOCTL, uintptr(fd), uintptr(SIOCETHTOOL), argp) if errno != 0 { return errno } return nil } // Disable TX checksum offload on specified interface func EthtoolTXOff(name string) error { if len(name)+1 > IFNAMSIZ { return fmt.Errorf("name too long") } socket, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, 0) if err != nil { return err } defer syscall.Close(socket) // Request current value value := EthtoolValue{Cmd: ETHTOOL_GTXCSUM} request := IFReqData{Data: uintptr(unsafe.Pointer(&value))} copy(request.Name[:], name) if err := ioctlEthtool(socket, uintptr(unsafe.Pointer(&request))); err != nil { return err } if value.Data == 0 { // if already off, don't try to change return nil } value = EthtoolValue{ETHTOOL_STXCSUM, 0} return ioctlEthtool(socket, uintptr(unsafe.Pointer(&request))) }