mirror of
https://github.com/qdm12/gluetun.git
synced 2026-05-06 20:10:11 +02:00
4a78989d9d
- main reason being it's a burden to always define sentinel errors at global scope, wrap them with `%w` instead of using a string directly - only use sentinel errors when it has to be checked using `errors.Is` - replace all usage of these sentinel errors in `fmt.Errorf` with direct strings that were in the sentinel error - exclude the sentinel error definition requirement from .golangci.yml - update unit tests to use ContainersError instead of ErrorIs so it stays as a "not a change detector test" without requiring a sentinel error
53 lines
1.7 KiB
Go
53 lines
1.7 KiB
Go
package icmp
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"net/netip"
|
|
"time"
|
|
|
|
"github.com/qdm12/gluetun/internal/pmtud/constants"
|
|
)
|
|
|
|
// PathMTUDiscover discovers the path MTU to the given IP address
|
|
// using ICMP.
|
|
// It first tries to get the next hop MTU using ICMP messages.
|
|
// If that fails, it falls back to sending echo requests with
|
|
// different packet sizes to find the maximum MTU.
|
|
// The function returns [ErrMTUNotFound] if the MTU could not be determined.
|
|
func PathMTUDiscover(ctx context.Context, ip netip.Addr,
|
|
physicalLinkMTU uint32, timeout time.Duration, logger Logger,
|
|
) (mtu uint32, err error) {
|
|
if ip.Is4() {
|
|
logger.Debugf("finding IPv4 next hop MTU to %s", ip)
|
|
mtu, err = findIPv4NextHopMTU(ctx, ip, physicalLinkMTU, timeout, logger)
|
|
switch {
|
|
case err == nil:
|
|
return mtu, nil
|
|
case errors.Is(err, errTimeout) || errors.Is(err, errCommunicationAdministrativelyProhibited): // blackhole
|
|
default:
|
|
return 0, fmt.Errorf("finding IPv4 next hop MTU to %s: %w", ip, err)
|
|
}
|
|
} else {
|
|
logger.Debugf("requesting IPv6 ICMP packet-too-big reply from %s", ip)
|
|
mtu, err = getIPv6PacketTooBig(ctx, ip, physicalLinkMTU, timeout, logger)
|
|
switch {
|
|
case err == nil:
|
|
return mtu, nil
|
|
case errors.Is(err, errTimeout): // blackhole
|
|
default:
|
|
return 0, fmt.Errorf("getting IPv6 packet-too-big message: %w", err)
|
|
}
|
|
}
|
|
|
|
// Fall back method: send echo requests with different packet
|
|
// sizes and check which ones succeed to find the maximum MTU.
|
|
logger.Debugf("falling back to sending different sized echo packets to %s", ip)
|
|
minMTU := constants.MinIPv4MTU
|
|
if ip.Is6() {
|
|
minMTU = constants.MinIPv6MTU
|
|
}
|
|
return pmtudMultiSizes(ctx, ip, minMTU, physicalLinkMTU, timeout, logger)
|
|
}
|