Skip to content

Commit

Permalink
move set DF implementation to separate files & avoid the need for OOB…
Browse files Browse the repository at this point in the history
…CapablePacketConn (#3334)

* move set DF implementation to separate files & avoid the need for OOBCapablePacketConn

* merge err_size_* into conn_df_* & fix format
  • Loading branch information
tobyxdd committed Mar 7, 2022
1 parent fa070e5 commit ad1cb27
Show file tree
Hide file tree
Showing 10 changed files with 106 additions and 85 deletions.
13 changes: 13 additions & 0 deletions conn.go
Expand Up @@ -29,6 +29,19 @@ type OOBCapablePacketConn interface {
var _ OOBCapablePacketConn = &net.UDPConn{}

func wrapConn(pc net.PacketConn) (connection, error) {
conn, ok := pc.(interface {
SyscallConn() (syscall.RawConn, error)
})
if ok {
rawConn, err := conn.SyscallConn()
if err != nil {
return nil, err
}
err = setDF(rawConn)
if err != nil {
return nil, err
}
}
c, ok := pc.(OOBCapablePacketConn)
if !ok {
utils.DefaultLogger.Infof("PacketConn is not a net.UDPConn. Disabling optimizations possible on UDP connections.")
Expand Down
7 changes: 7 additions & 0 deletions err_size.go → conn_df.go
Expand Up @@ -3,6 +3,13 @@

package quic

import "syscall"

func setDF(rawConn syscall.RawConn) error {
// no-op on unsupported platforms
return nil
}

func isMsgSizeErr(err error) bool {
// to be implemented for more specific platforms
return false
Expand Down
40 changes: 40 additions & 0 deletions conn_df_linux.go
@@ -0,0 +1,40 @@
//go:build linux
// +build linux

package quic

import (
"errors"
"syscall"

"github.com/lucas-clemente/quic-go/internal/utils"
"golang.org/x/sys/unix"
)

func setDF(rawConn syscall.RawConn) error {
// Enabling IP_MTU_DISCOVER will force the kernel to return "sendto: message too long"
// and the datagram will not be fragmented
var errDFIPv4, errDFIPv6 error
if err := rawConn.Control(func(fd uintptr) {
errDFIPv4 = unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_MTU_DISCOVER, unix.IP_PMTUDISC_DO)
errDFIPv6 = unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_MTU_DISCOVER, unix.IPV6_PMTUDISC_DO)
}); err != nil {
return err
}
switch {
case errDFIPv4 == nil && errDFIPv6 == nil:
utils.DefaultLogger.Debugf("Setting DF for IPv4 and IPv6.")
case errDFIPv4 == nil && errDFIPv6 != nil:
utils.DefaultLogger.Debugf("Setting DF for IPv4.")
case errDFIPv4 != nil && errDFIPv6 == nil:
utils.DefaultLogger.Debugf("Setting DF for IPv6.")
case errDFIPv4 != nil && errDFIPv6 != nil:
return errors.New("setting DF failed for both IPv4 and IPv6")
}
return nil
}

func isMsgSizeErr(err error) bool {
// https://man7.org/linux/man-pages/man7/udp.7.html
return errors.Is(err, unix.EMSGSIZE)
}
46 changes: 46 additions & 0 deletions conn_df_windows.go
@@ -0,0 +1,46 @@
//go:build windows
// +build windows

package quic

import (
"errors"
"syscall"

"github.com/lucas-clemente/quic-go/internal/utils"
"golang.org/x/sys/windows"
)

const (
// same for both IPv4 and IPv6 on Windows
// https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/Networking/WinSock/constant.IP_DONTFRAG.html
// https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/Networking/WinSock/constant.IPV6_DONTFRAG.html
IP_DONTFRAGMENT = 14
IPV6_DONTFRAG = 14
)

func setDF(rawConn syscall.RawConn) error {
var errDFIPv4, errDFIPv6 error
if err := rawConn.Control(func(fd uintptr) {
errDFIPv4 = windows.SetsockoptInt(windows.Handle(fd), windows.IPPROTO_IP, IP_DONTFRAGMENT, 1)
errDFIPv6 = windows.SetsockoptInt(windows.Handle(fd), windows.IPPROTO_IPV6, IPV6_DONTFRAG, 1)
}); err != nil {
return err
}
switch {
case errDFIPv4 == nil && errDFIPv6 == nil:
utils.DefaultLogger.Debugf("Setting DF for IPv4 and IPv6.")
case errDFIPv4 == nil && errDFIPv6 != nil:
utils.DefaultLogger.Debugf("Setting DF for IPv4.")
case errDFIPv4 != nil && errDFIPv6 == nil:
utils.DefaultLogger.Debugf("Setting DF for IPv6.")
case errDFIPv4 != nil && errDFIPv6 != nil:
return errors.New("setting DF failed for both IPv4 and IPv6")
}
return nil
}

func isMsgSizeErr(err error) bool {
// https://docs.microsoft.com/en-us/windows/win32/winsock/windows-sockets-error-codes-2
return errors.Is(err, windows.WSAEMSGSIZE)
}
2 changes: 0 additions & 2 deletions conn_oob.go
Expand Up @@ -87,8 +87,6 @@ func newConn(c OOBCapablePacketConn) (*oobConn, error) {
errPIIPv4 = unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, ipv4RECVPKTINFO, 1)
errPIIPv6 = unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, ipv6RECVPKTINFO, 1)
}

setOOBSockOpts(fd)
}); err != nil {
return nil, err
}
Expand Down
8 changes: 0 additions & 8 deletions conn_oob_opts.go

This file was deleted.

15 changes: 0 additions & 15 deletions conn_oob_opts_linux.go

This file was deleted.

30 changes: 0 additions & 30 deletions conn_windows.go
Expand Up @@ -9,40 +9,10 @@ import (
"net"
"syscall"

"github.com/lucas-clemente/quic-go/internal/utils"
"golang.org/x/sys/windows"
)

const (
// same for both IPv4 and IPv6 on Windows
// https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/Networking/WinSock/constant.IP_DONTFRAG.html
// https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/Networking/WinSock/constant.IPV6_DONTFRAG.html
IP_DONTFRAGMENT = 14
IPV6_DONTFRAG = 14
)

func newConn(c OOBCapablePacketConn) (connection, error) {
rawConn, err := c.SyscallConn()
if err != nil {
return nil, fmt.Errorf("couldn't get syscall.RawConn: %w", err)
}
var errDFIPv4, errDFIPv6 error
if err := rawConn.Control(func(fd uintptr) {
errDFIPv4 = windows.SetsockoptInt(windows.Handle(fd), windows.IPPROTO_IP, IP_DONTFRAGMENT, 1)
errDFIPv6 = windows.SetsockoptInt(windows.Handle(fd), windows.IPPROTO_IPV6, IPV6_DONTFRAG, 1)
}); err != nil {
return nil, err
}
switch {
case errDFIPv4 == nil && errDFIPv6 == nil:
utils.DefaultLogger.Debugf("Setting DF for IPv4 and IPv6.")
case errDFIPv4 == nil && errDFIPv6 != nil:
utils.DefaultLogger.Debugf("Setting DF for IPv4.")
case errDFIPv4 != nil && errDFIPv6 == nil:
utils.DefaultLogger.Debugf("Setting DF for IPv6.")
case errDFIPv4 != nil && errDFIPv6 != nil:
return nil, errors.New("setting Df failed for both IPv4 and IPv6")
}
return &basicConn{PacketConn: c}, nil
}

Expand Down
15 changes: 0 additions & 15 deletions err_size_linux.go

This file was deleted.

15 changes: 0 additions & 15 deletions err_size_windows.go

This file was deleted.

0 comments on commit ad1cb27

Please sign in to comment.