Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disable tx and rx offloading on VXLAN interfaces #1282

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions backend/vxlan/device.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ func (dev *vxlanDevice) Configure(ipn ip.IP4Net) error {
return fmt.Errorf("failed to set interface %s to UP state: %s", dev.link.Attrs().Name, err)
}

// TODO: Workaround to fix #1282
if err := ip.SetChecksumOffloading(dev.link.Attrs().Name, false, false); err != nil {
return fmt.Errorf("failed to disable interface %s tx and rx offloading: %s", dev.link.Attrs().Name, err)
}

return nil
}

Expand Down
67 changes: 67 additions & 0 deletions pkg/ip/iface.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,77 @@ import (
"fmt"
"net"
"syscall"
"unsafe"

"github.com/vishvananda/netlink"
)

const (
siocEthtool = 0x8946 // linux/sockios.h

// #define ETHTOOL_SRXCSUM 0x00000015 /* Set RX hw csum enable (ethtool_value) */
ethtoolSRxCsum = 0x00000015 // linux/ethtool.h
// #define ETHTOOL_STXCSUM 0x00000017 /* Set TX hw csum enable (ethtool_value) */
ethtoolSTxCsum = 0x00000017 // linux/ethtool.h

maxIfNameSize = 16 // linux/if.h
)

// linux/if.h 'struct ifreq'
type ifreq struct {
Name [maxIfNameSize]byte
Data uintptr
}

// linux/ethtool.h 'struct ethtool_value'
type ethtoolValue struct {
Cmd uint32
Data uint32
}

// ethtool executes Linux ethtool syscall.
func ethtool(iface string, cmd, val uint32) (retval uint32, err error) {
if len(iface)+1 > maxIfNameSize {
return 0, fmt.Errorf("interface name is too long")
}
socket, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, 0)
if err != nil {
return 0, err
}
defer syscall.Close(socket)

// prepare ethtool request
value := ethtoolValue{cmd, val}
request := ifreq{Data: uintptr(unsafe.Pointer(&value))}
copy(request.Name[:], iface)

// ioctl system call
_, _, errno := syscall.RawSyscall(syscall.SYS_IOCTL, uintptr(socket), uintptr(siocEthtool),
uintptr(unsafe.Pointer(&request)))
if errno != 0 {
return 0, errno
}
return value.Data, nil
}

// SetChecksumOffloading enables/disables Rx/Tx checksum offloading
// for the given interface.
func SetChecksumOffloading(ifName string, rxOn, txOn bool) error {
var rxVal, txVal uint32
if rxOn {
rxVal = 1
}
if txOn {
txVal = 1
}
_, err := ethtool(ifName, ethtoolSRxCsum, rxVal)
if err != nil {
return err
}
_, err = ethtool(ifName, ethtoolSTxCsum, txVal)
return err
}

func getIfaceAddrs(iface *net.Interface) ([]netlink.Addr, error) {
link := &netlink.Device{
netlink.LinkAttrs{
Expand Down