github.com/database64128/shadowsocks-go@v1.10.2-0.20240315062903-143a773533f1/service/udp.go (about)

     1  package service
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"net"
     7  	"time"
     8  
     9  	"github.com/database64128/shadowsocks-go/conn"
    10  	"go.uber.org/zap"
    11  )
    12  
    13  const (
    14  	// minimumMTU is the minimum allowed MTU.
    15  	minimumMTU = 1280
    16  
    17  	// defaultRelayBatchSize is the default batch size of recvmmsg(2) and sendmmsg(2) calls in relay sessions.
    18  	//
    19  	// On an i9-13900K, the average number of messages received in a single recvmmsg(2) call is
    20  	// around 100 in iperf3 tests. Bumping the msgvec size to greater than 256 does not seem to
    21  	// yield any performance improvement.
    22  	//
    23  	// Note that the mainline iperf3 does not use sendmmsg(2) or io_uring for batch sending at the
    24  	// time of writing. So this value is still subject to change in the future.
    25  	defaultRelayBatchSize = 256
    26  
    27  	// defaultServerRecvBatchSize is the default batch size of a UDP relay's main receive routine.
    28  	defaultServerRecvBatchSize = 64
    29  
    30  	// defaultSendChannelCapacity is the default capacity of a UDP relay session's uplink send channel.
    31  	defaultSendChannelCapacity = 1024
    32  
    33  	// defaultNatTimeout is the default duration after which an inactive NAT entry is evicted.
    34  	defaultNatTimeout = 5 * time.Minute
    35  )
    36  
    37  var ErrMTUTooSmall = errors.New("MTU must be at least 1280")
    38  
    39  // UDPPerfConfig exposes performance tuning parameters for UDP relays.
    40  type UDPPerfConfig struct {
    41  	// BatchMode controls the mode of batch receiving and sending.
    42  	//
    43  	// Available values:
    44  	// - "": Platform default.
    45  	// - "no": Do not receive or send packets in batches.
    46  	// - "sendmmsg": Use recvmmsg(2) and sendmmsg(2) calls. This is the default on Linux and NetBSD.
    47  	BatchMode string `json:"batchMode"`
    48  
    49  	// RelayBatchSize is the batch size of recvmmsg(2) and sendmmsg(2) calls in relay sessions.
    50  	//
    51  	// The default value is 256.
    52  	RelayBatchSize int `json:"relayBatchSize"`
    53  
    54  	// ServerRecvBatchSize is the batch size of a UDP relay's main receive routine.
    55  	//
    56  	// The default value is 64.
    57  	ServerRecvBatchSize int `json:"serverRecvBatchSize"`
    58  
    59  	// SendChannelCapacity is the capacity of a UDP relay session's uplink send channel.
    60  	//
    61  	// The default value is 1024.
    62  	SendChannelCapacity int `json:"sendChannelCapacity"`
    63  }
    64  
    65  // CheckAndApplyDefaults checks the validity of the configuration and applies default values.
    66  func (c *UDPPerfConfig) CheckAndApplyDefaults() error {
    67  	switch c.BatchMode {
    68  	case "", "no", "sendmmsg":
    69  	default:
    70  		return fmt.Errorf("unknown batch mode: %s", c.BatchMode)
    71  	}
    72  
    73  	switch {
    74  	case c.RelayBatchSize > 0 && c.RelayBatchSize <= 1024:
    75  	case c.RelayBatchSize == 0:
    76  		c.RelayBatchSize = defaultRelayBatchSize
    77  	default:
    78  		return fmt.Errorf("relay batch size out of range [0, 1024]: %d", c.RelayBatchSize)
    79  	}
    80  
    81  	switch {
    82  	case c.ServerRecvBatchSize > 0 && c.ServerRecvBatchSize <= 1024:
    83  	case c.ServerRecvBatchSize == 0:
    84  		c.ServerRecvBatchSize = defaultServerRecvBatchSize
    85  	default:
    86  		return fmt.Errorf("server recv batch size out of range [0, 1024]: %d", c.ServerRecvBatchSize)
    87  	}
    88  
    89  	switch {
    90  	case c.SendChannelCapacity >= 64:
    91  	case c.SendChannelCapacity == 0:
    92  		c.SendChannelCapacity = defaultSendChannelCapacity
    93  	default:
    94  		return fmt.Errorf("send channel capacity must be at least 64: %d", c.SendChannelCapacity)
    95  	}
    96  
    97  	return nil
    98  }
    99  
   100  // udpRelayServerConn configures the server socket for a UDP relay.
   101  type udpRelayServerConn struct {
   102  	logger              *zap.Logger
   103  	serverConn          *net.UDPConn
   104  	listenConfig        conn.ListenConfig
   105  	network             string
   106  	address             string
   107  	batchMode           string
   108  	relayBatchSize      int
   109  	serverRecvBatchSize int
   110  	sendChannelCapacity int
   111  	natTimeout          time.Duration
   112  }