mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-05-08 14:13:22 +00:00
Finalmask quicParams: Add bbrProfile ("conservative" / "standard" (default) / "aggressive") (#5869)
And Update github.com/apernet/quic-go to 20260330051153
This commit is contained in:
2
go.mod
2
go.mod
@@ -3,7 +3,7 @@ module github.com/xtls/xray-core
|
|||||||
go 1.26
|
go 1.26
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/apernet/quic-go v0.59.1-0.20260217092621-db4786c77a22
|
github.com/apernet/quic-go v0.59.1-0.20260330051153-c402ee641eb6
|
||||||
github.com/cloudflare/circl v1.6.3
|
github.com/cloudflare/circl v1.6.3
|
||||||
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344
|
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344
|
||||||
github.com/golang/mock v1.7.0-rc.1
|
github.com/golang/mock v1.7.0-rc.1
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -1,7 +1,7 @@
|
|||||||
github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
|
github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
|
||||||
github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||||
github.com/apernet/quic-go v0.59.1-0.20260217092621-db4786c77a22 h1:00ziBGnLWQEcR9LThDwvxOznJJquJ9bYUdmBFnawLMU=
|
github.com/apernet/quic-go v0.59.1-0.20260330051153-c402ee641eb6 h1:cbF95uMsQwCwAzH2i8+2lNO2TReoELLuqeeMfyBjFbY=
|
||||||
github.com/apernet/quic-go v0.59.1-0.20260217092621-db4786c77a22/go.mod h1:Npbg8qBtAZlsAB3FWmqwlVh5jtVG6a4DlYsOylUpvzA=
|
github.com/apernet/quic-go v0.59.1-0.20260330051153-c402ee641eb6/go.mod h1:Npbg8qBtAZlsAB3FWmqwlVh5jtVG6a4DlYsOylUpvzA=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8=
|
github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8=
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/transport/internet/finalmask/xicmp"
|
"github.com/xtls/xray-core/transport/internet/finalmask/xicmp"
|
||||||
"github.com/xtls/xray-core/transport/internet/httpupgrade"
|
"github.com/xtls/xray-core/transport/internet/httpupgrade"
|
||||||
"github.com/xtls/xray-core/transport/internet/hysteria"
|
"github.com/xtls/xray-core/transport/internet/hysteria"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/hysteria/congestion/bbr"
|
||||||
"github.com/xtls/xray-core/transport/internet/kcp"
|
"github.com/xtls/xray-core/transport/internet/kcp"
|
||||||
"github.com/xtls/xray-core/transport/internet/reality"
|
"github.com/xtls/xray-core/transport/internet/reality"
|
||||||
"github.com/xtls/xray-core/transport/internet/splithttp"
|
"github.com/xtls/xray-core/transport/internet/splithttp"
|
||||||
@@ -630,6 +631,7 @@ func (c *TLSCertConfig) Build() (*tls.Certificate, error) {
|
|||||||
type QuicParamsConfig struct {
|
type QuicParamsConfig struct {
|
||||||
Congestion string `json:"congestion"`
|
Congestion string `json:"congestion"`
|
||||||
Debug bool `json:"debug"`
|
Debug bool `json:"debug"`
|
||||||
|
BbrProfile string `json:"bbrProfile"`
|
||||||
BrutalUp Bandwidth `json:"brutalUp"`
|
BrutalUp Bandwidth `json:"brutalUp"`
|
||||||
BrutalDown Bandwidth `json:"brutalDown"`
|
BrutalDown Bandwidth `json:"brutalDown"`
|
||||||
UdpHop UdpHop `json:"udpHop"`
|
UdpHop UdpHop `json:"udpHop"`
|
||||||
@@ -1894,6 +1896,16 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
|
|||||||
config.Udpmasks = append(config.Udpmasks, serial.ToTypedMessage(u))
|
config.Udpmasks = append(config.Udpmasks, serial.ToTypedMessage(u))
|
||||||
}
|
}
|
||||||
if c.FinalMask.QuicParams != nil {
|
if c.FinalMask.QuicParams != nil {
|
||||||
|
profile := strings.ToLower(c.FinalMask.QuicParams.BbrProfile)
|
||||||
|
switch profile {
|
||||||
|
case "", string(bbr.ProfileConservative), string(bbr.ProfileStandard), string(bbr.ProfileAggressive):
|
||||||
|
if profile == "" {
|
||||||
|
profile = string(bbr.ProfileStandard)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil, errors.New("unknown bbr profile")
|
||||||
|
}
|
||||||
|
|
||||||
up, err := c.FinalMask.QuicParams.BrutalUp.Bps()
|
up, err := c.FinalMask.QuicParams.BrutalUp.Bps()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -1965,6 +1977,7 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
|
|||||||
|
|
||||||
config.QuicParams = &internet.QuicParams{
|
config.QuicParams = &internet.QuicParams{
|
||||||
Congestion: c.FinalMask.QuicParams.Congestion,
|
Congestion: c.FinalMask.QuicParams.Congestion,
|
||||||
|
BbrProfile: profile,
|
||||||
BrutalUp: up,
|
BrutalUp: up,
|
||||||
BrutalDown: down,
|
BrutalDown: down,
|
||||||
UdpHop: &internet.UdpHop{
|
UdpHop: &internet.UdpHop{
|
||||||
|
|||||||
@@ -445,17 +445,18 @@ func (x *UdpHop) GetIntervalMax() int64 {
|
|||||||
type QuicParams struct {
|
type QuicParams struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
Congestion string `protobuf:"bytes,1,opt,name=congestion,proto3" json:"congestion,omitempty"`
|
Congestion string `protobuf:"bytes,1,opt,name=congestion,proto3" json:"congestion,omitempty"`
|
||||||
BrutalUp uint64 `protobuf:"varint,2,opt,name=brutal_up,json=brutalUp,proto3" json:"brutal_up,omitempty"`
|
BbrProfile string `protobuf:"bytes,2,opt,name=bbr_profile,json=bbrProfile,proto3" json:"bbr_profile,omitempty"`
|
||||||
BrutalDown uint64 `protobuf:"varint,3,opt,name=brutal_down,json=brutalDown,proto3" json:"brutal_down,omitempty"`
|
BrutalUp uint64 `protobuf:"varint,3,opt,name=brutal_up,json=brutalUp,proto3" json:"brutal_up,omitempty"`
|
||||||
UdpHop *UdpHop `protobuf:"bytes,4,opt,name=udp_hop,json=udpHop,proto3" json:"udp_hop,omitempty"`
|
BrutalDown uint64 `protobuf:"varint,4,opt,name=brutal_down,json=brutalDown,proto3" json:"brutal_down,omitempty"`
|
||||||
InitStreamReceiveWindow uint64 `protobuf:"varint,5,opt,name=init_stream_receive_window,json=initStreamReceiveWindow,proto3" json:"init_stream_receive_window,omitempty"`
|
UdpHop *UdpHop `protobuf:"bytes,5,opt,name=udp_hop,json=udpHop,proto3" json:"udp_hop,omitempty"`
|
||||||
MaxStreamReceiveWindow uint64 `protobuf:"varint,6,opt,name=max_stream_receive_window,json=maxStreamReceiveWindow,proto3" json:"max_stream_receive_window,omitempty"`
|
InitStreamReceiveWindow uint64 `protobuf:"varint,6,opt,name=init_stream_receive_window,json=initStreamReceiveWindow,proto3" json:"init_stream_receive_window,omitempty"`
|
||||||
InitConnReceiveWindow uint64 `protobuf:"varint,7,opt,name=init_conn_receive_window,json=initConnReceiveWindow,proto3" json:"init_conn_receive_window,omitempty"`
|
MaxStreamReceiveWindow uint64 `protobuf:"varint,7,opt,name=max_stream_receive_window,json=maxStreamReceiveWindow,proto3" json:"max_stream_receive_window,omitempty"`
|
||||||
MaxConnReceiveWindow uint64 `protobuf:"varint,8,opt,name=max_conn_receive_window,json=maxConnReceiveWindow,proto3" json:"max_conn_receive_window,omitempty"`
|
InitConnReceiveWindow uint64 `protobuf:"varint,8,opt,name=init_conn_receive_window,json=initConnReceiveWindow,proto3" json:"init_conn_receive_window,omitempty"`
|
||||||
MaxIdleTimeout int64 `protobuf:"varint,9,opt,name=max_idle_timeout,json=maxIdleTimeout,proto3" json:"max_idle_timeout,omitempty"`
|
MaxConnReceiveWindow uint64 `protobuf:"varint,9,opt,name=max_conn_receive_window,json=maxConnReceiveWindow,proto3" json:"max_conn_receive_window,omitempty"`
|
||||||
KeepAlivePeriod int64 `protobuf:"varint,10,opt,name=keep_alive_period,json=keepAlivePeriod,proto3" json:"keep_alive_period,omitempty"`
|
MaxIdleTimeout int64 `protobuf:"varint,10,opt,name=max_idle_timeout,json=maxIdleTimeout,proto3" json:"max_idle_timeout,omitempty"`
|
||||||
DisablePathMtuDiscovery bool `protobuf:"varint,11,opt,name=disable_path_mtu_discovery,json=disablePathMtuDiscovery,proto3" json:"disable_path_mtu_discovery,omitempty"`
|
KeepAlivePeriod int64 `protobuf:"varint,11,opt,name=keep_alive_period,json=keepAlivePeriod,proto3" json:"keep_alive_period,omitempty"`
|
||||||
MaxIncomingStreams int64 `protobuf:"varint,12,opt,name=max_incoming_streams,json=maxIncomingStreams,proto3" json:"max_incoming_streams,omitempty"`
|
DisablePathMtuDiscovery bool `protobuf:"varint,12,opt,name=disable_path_mtu_discovery,json=disablePathMtuDiscovery,proto3" json:"disable_path_mtu_discovery,omitempty"`
|
||||||
|
MaxIncomingStreams int64 `protobuf:"varint,13,opt,name=max_incoming_streams,json=maxIncomingStreams,proto3" json:"max_incoming_streams,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
@@ -497,6 +498,13 @@ func (x *QuicParams) GetCongestion() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *QuicParams) GetBbrProfile() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.BbrProfile
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func (x *QuicParams) GetBrutalUp() uint64 {
|
func (x *QuicParams) GetBrutalUp() uint64 {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.BrutalUp
|
return x.BrutalUp
|
||||||
@@ -1028,25 +1036,27 @@ const file_transport_internet_config_proto_rawDesc = "" +
|
|||||||
"\x06UdpHop\x12\x14\n" +
|
"\x06UdpHop\x12\x14\n" +
|
||||||
"\x05ports\x18\x01 \x03(\rR\x05ports\x12!\n" +
|
"\x05ports\x18\x01 \x03(\rR\x05ports\x12!\n" +
|
||||||
"\finterval_min\x18\x02 \x01(\x03R\vintervalMin\x12!\n" +
|
"\finterval_min\x18\x02 \x01(\x03R\vintervalMin\x12!\n" +
|
||||||
"\finterval_max\x18\x03 \x01(\x03R\vintervalMax\"\xd1\x04\n" +
|
"\finterval_max\x18\x03 \x01(\x03R\vintervalMax\"\xf2\x04\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"QuicParams\x12\x1e\n" +
|
"QuicParams\x12\x1e\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"congestion\x18\x01 \x01(\tR\n" +
|
"congestion\x18\x01 \x01(\tR\n" +
|
||||||
"congestion\x12\x1b\n" +
|
"congestion\x12\x1f\n" +
|
||||||
"\tbrutal_up\x18\x02 \x01(\x04R\bbrutalUp\x12\x1f\n" +
|
"\vbbr_profile\x18\x02 \x01(\tR\n" +
|
||||||
"\vbrutal_down\x18\x03 \x01(\x04R\n" +
|
"bbrProfile\x12\x1b\n" +
|
||||||
|
"\tbrutal_up\x18\x03 \x01(\x04R\bbrutalUp\x12\x1f\n" +
|
||||||
|
"\vbrutal_down\x18\x04 \x01(\x04R\n" +
|
||||||
"brutalDown\x128\n" +
|
"brutalDown\x128\n" +
|
||||||
"\audp_hop\x18\x04 \x01(\v2\x1f.xray.transport.internet.UdpHopR\x06udpHop\x12;\n" +
|
"\audp_hop\x18\x05 \x01(\v2\x1f.xray.transport.internet.UdpHopR\x06udpHop\x12;\n" +
|
||||||
"\x1ainit_stream_receive_window\x18\x05 \x01(\x04R\x17initStreamReceiveWindow\x129\n" +
|
"\x1ainit_stream_receive_window\x18\x06 \x01(\x04R\x17initStreamReceiveWindow\x129\n" +
|
||||||
"\x19max_stream_receive_window\x18\x06 \x01(\x04R\x16maxStreamReceiveWindow\x127\n" +
|
"\x19max_stream_receive_window\x18\a \x01(\x04R\x16maxStreamReceiveWindow\x127\n" +
|
||||||
"\x18init_conn_receive_window\x18\a \x01(\x04R\x15initConnReceiveWindow\x125\n" +
|
"\x18init_conn_receive_window\x18\b \x01(\x04R\x15initConnReceiveWindow\x125\n" +
|
||||||
"\x17max_conn_receive_window\x18\b \x01(\x04R\x14maxConnReceiveWindow\x12(\n" +
|
"\x17max_conn_receive_window\x18\t \x01(\x04R\x14maxConnReceiveWindow\x12(\n" +
|
||||||
"\x10max_idle_timeout\x18\t \x01(\x03R\x0emaxIdleTimeout\x12*\n" +
|
"\x10max_idle_timeout\x18\n" +
|
||||||
"\x11keep_alive_period\x18\n" +
|
" \x01(\x03R\x0emaxIdleTimeout\x12*\n" +
|
||||||
" \x01(\x03R\x0fkeepAlivePeriod\x12;\n" +
|
"\x11keep_alive_period\x18\v \x01(\x03R\x0fkeepAlivePeriod\x12;\n" +
|
||||||
"\x1adisable_path_mtu_discovery\x18\v \x01(\bR\x17disablePathMtuDiscovery\x120\n" +
|
"\x1adisable_path_mtu_discovery\x18\f \x01(\bR\x17disablePathMtuDiscovery\x120\n" +
|
||||||
"\x14max_incoming_streams\x18\f \x01(\x03R\x12maxIncomingStreams\"Q\n" +
|
"\x14max_incoming_streams\x18\r \x01(\x03R\x12maxIncomingStreams\"Q\n" +
|
||||||
"\vProxyConfig\x12\x10\n" +
|
"\vProxyConfig\x12\x10\n" +
|
||||||
"\x03tag\x18\x01 \x01(\tR\x03tag\x120\n" +
|
"\x03tag\x18\x01 \x01(\tR\x03tag\x120\n" +
|
||||||
"\x13transportLayerProxy\x18\x02 \x01(\bR\x13transportLayerProxy\"\x93\x01\n" +
|
"\x13transportLayerProxy\x18\x02 \x01(\bR\x13transportLayerProxy\"\x93\x01\n" +
|
||||||
|
|||||||
@@ -72,17 +72,18 @@ message UdpHop {
|
|||||||
|
|
||||||
message QuicParams {
|
message QuicParams {
|
||||||
string congestion = 1;
|
string congestion = 1;
|
||||||
uint64 brutal_up = 2;
|
string bbr_profile = 2;
|
||||||
uint64 brutal_down = 3;
|
uint64 brutal_up = 3;
|
||||||
UdpHop udp_hop = 4;
|
uint64 brutal_down = 4;
|
||||||
uint64 init_stream_receive_window = 5;
|
UdpHop udp_hop = 5;
|
||||||
uint64 max_stream_receive_window = 6;
|
uint64 init_stream_receive_window = 6;
|
||||||
uint64 init_conn_receive_window = 7;
|
uint64 max_stream_receive_window = 7;
|
||||||
uint64 max_conn_receive_window = 8;
|
uint64 init_conn_receive_window = 8;
|
||||||
int64 max_idle_timeout = 9;
|
uint64 max_conn_receive_window = 9;
|
||||||
int64 keep_alive_period = 10;
|
int64 max_idle_timeout = 10;
|
||||||
bool disable_path_mtu_discovery = 11;
|
int64 keep_alive_period = 11;
|
||||||
int64 max_incoming_streams = 12;
|
bool disable_path_mtu_discovery = 12;
|
||||||
|
int64 max_incoming_streams = 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ProxyConfig {
|
message ProxyConfig {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/apernet/quic-go/congestion"
|
"github.com/apernet/quic-go/congestion"
|
||||||
@@ -28,16 +29,13 @@ const (
|
|||||||
|
|
||||||
invalidPacketNumber = -1
|
invalidPacketNumber = -1
|
||||||
initialCongestionWindowPackets = 32
|
initialCongestionWindowPackets = 32
|
||||||
|
minCongestionWindowPackets = 4
|
||||||
|
|
||||||
// Constants based on TCP defaults.
|
// Constants based on TCP defaults.
|
||||||
// The minimum CWND to ensure delayed acks don't reduce bandwidth measurements.
|
// The minimum CWND to ensure delayed acks don't reduce bandwidth measurements.
|
||||||
// Does not inflate the pacing rate.
|
// Does not inflate the pacing rate.
|
||||||
defaultMinimumCongestionWindow = 4 * congestion.ByteCount(congestion.InitialPacketSize)
|
|
||||||
|
|
||||||
// The gain used for the STARTUP, equal to 2/ln(2).
|
// The gain used for the STARTUP, equal to 2/ln(2).
|
||||||
defaultHighGain = 2.885
|
defaultHighGain = 2.885
|
||||||
// The newly derived gain for STARTUP, equal to 4 * ln(2)
|
|
||||||
derivedHighGain = 2.773
|
|
||||||
// The newly derived CWND gain for STARTUP, 2.
|
// The newly derived CWND gain for STARTUP, 2.
|
||||||
derivedHighCWNDGain = 2.0
|
derivedHighCWNDGain = 2.0
|
||||||
|
|
||||||
@@ -66,7 +64,6 @@ const (
|
|||||||
// Flag.
|
// Flag.
|
||||||
defaultStartupFullLossCount = 8
|
defaultStartupFullLossCount = 8
|
||||||
quicBbr2DefaultLossThreshold = 0.02
|
quicBbr2DefaultLossThreshold = 0.02
|
||||||
maxBbrBurstPackets = 10
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type bbrMode int
|
type bbrMode int
|
||||||
@@ -97,6 +94,76 @@ const (
|
|||||||
bbrRecoveryStateGrowth
|
bbrRecoveryStateGrowth
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Profile string
|
||||||
|
|
||||||
|
const (
|
||||||
|
ProfileConservative Profile = "conservative"
|
||||||
|
ProfileStandard Profile = "standard"
|
||||||
|
ProfileAggressive Profile = "aggressive"
|
||||||
|
)
|
||||||
|
|
||||||
|
type profileConfig struct {
|
||||||
|
highGain float64
|
||||||
|
highCwndGain float64
|
||||||
|
congestionWindowGainConstant float64
|
||||||
|
numStartupRtts int64
|
||||||
|
drainToTarget bool
|
||||||
|
detectOvershooting bool
|
||||||
|
bytesLostMultiplier uint8
|
||||||
|
enableAckAggregationStartup bool
|
||||||
|
expireAckAggregationStartup bool
|
||||||
|
enableOverestimateAvoidance bool
|
||||||
|
reduceExtraAckedOnBandwidthIncrease bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseProfile(profile string) (Profile, error) {
|
||||||
|
switch normalized := strings.ToLower(profile); normalized {
|
||||||
|
case "", string(ProfileStandard):
|
||||||
|
return ProfileStandard, nil
|
||||||
|
case string(ProfileConservative):
|
||||||
|
return ProfileConservative, nil
|
||||||
|
case string(ProfileAggressive):
|
||||||
|
return ProfileAggressive, nil
|
||||||
|
default:
|
||||||
|
return "", fmt.Errorf("unsupported BBR profile %q", profile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func configForProfile(profile Profile) profileConfig {
|
||||||
|
switch profile {
|
||||||
|
case ProfileConservative:
|
||||||
|
return profileConfig{
|
||||||
|
highGain: 2.25,
|
||||||
|
highCwndGain: 1.75,
|
||||||
|
congestionWindowGainConstant: 1.75,
|
||||||
|
numStartupRtts: 2,
|
||||||
|
drainToTarget: true,
|
||||||
|
detectOvershooting: true,
|
||||||
|
bytesLostMultiplier: 1,
|
||||||
|
enableOverestimateAvoidance: true,
|
||||||
|
reduceExtraAckedOnBandwidthIncrease: true,
|
||||||
|
}
|
||||||
|
case ProfileAggressive:
|
||||||
|
return profileConfig{
|
||||||
|
highGain: 3.0,
|
||||||
|
highCwndGain: 2.25,
|
||||||
|
congestionWindowGainConstant: 2.5,
|
||||||
|
numStartupRtts: 4,
|
||||||
|
bytesLostMultiplier: 2,
|
||||||
|
enableAckAggregationStartup: true,
|
||||||
|
expireAckAggregationStartup: true,
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return profileConfig{
|
||||||
|
highGain: defaultHighGain,
|
||||||
|
highCwndGain: derivedHighCWNDGain,
|
||||||
|
congestionWindowGainConstant: 2.0,
|
||||||
|
numStartupRtts: roundTripsWithoutGrowthBeforeExitingStartup,
|
||||||
|
bytesLostMultiplier: 2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type bbrSender struct {
|
type bbrSender struct {
|
||||||
rttStats congestion.RTTStatsProvider
|
rttStats congestion.RTTStatsProvider
|
||||||
clock Clock
|
clock Clock
|
||||||
@@ -145,6 +212,9 @@ type bbrSender struct {
|
|||||||
// The smallest value the |congestion_window_| can achieve.
|
// The smallest value the |congestion_window_| can achieve.
|
||||||
minCongestionWindow congestion.ByteCount
|
minCongestionWindow congestion.ByteCount
|
||||||
|
|
||||||
|
// The BBR profile used by the sender.
|
||||||
|
profile Profile
|
||||||
|
|
||||||
// The pacing gain applied during the STARTUP phase.
|
// The pacing gain applied during the STARTUP phase.
|
||||||
highGain float64
|
highGain float64
|
||||||
|
|
||||||
@@ -251,12 +321,14 @@ var _ congestion.CongestionControl = &bbrSender{}
|
|||||||
func NewBbrSender(
|
func NewBbrSender(
|
||||||
clock Clock,
|
clock Clock,
|
||||||
initialMaxDatagramSize congestion.ByteCount,
|
initialMaxDatagramSize congestion.ByteCount,
|
||||||
|
profile Profile,
|
||||||
) *bbrSender {
|
) *bbrSender {
|
||||||
return newBbrSender(
|
return newBbrSender(
|
||||||
clock,
|
clock,
|
||||||
initialMaxDatagramSize,
|
initialMaxDatagramSize,
|
||||||
initialCongestionWindowPackets*initialMaxDatagramSize,
|
initialCongestionWindowPackets*initialMaxDatagramSize,
|
||||||
congestion.MaxCongestionWindowPackets*initialMaxDatagramSize,
|
congestion.MaxCongestionWindowPackets*initialMaxDatagramSize,
|
||||||
|
profile,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,6 +337,7 @@ func newBbrSender(
|
|||||||
initialMaxDatagramSize,
|
initialMaxDatagramSize,
|
||||||
initialCongestionWindow,
|
initialCongestionWindow,
|
||||||
initialMaxCongestionWindow congestion.ByteCount,
|
initialMaxCongestionWindow congestion.ByteCount,
|
||||||
|
profile Profile,
|
||||||
) *bbrSender {
|
) *bbrSender {
|
||||||
debug, _ := strconv.ParseBool(os.Getenv(debugEnv))
|
debug, _ := strconv.ParseBool(os.Getenv(debugEnv))
|
||||||
b := &bbrSender{
|
b := &bbrSender{
|
||||||
@@ -277,9 +350,10 @@ func newBbrSender(
|
|||||||
congestionWindow: initialCongestionWindow,
|
congestionWindow: initialCongestionWindow,
|
||||||
initialCongestionWindow: initialCongestionWindow,
|
initialCongestionWindow: initialCongestionWindow,
|
||||||
maxCongestionWindow: initialMaxCongestionWindow,
|
maxCongestionWindow: initialMaxCongestionWindow,
|
||||||
minCongestionWindow: defaultMinimumCongestionWindow,
|
minCongestionWindow: minCongestionWindowForMaxDatagramSize(initialMaxDatagramSize),
|
||||||
|
profile: ProfileStandard,
|
||||||
highGain: defaultHighGain,
|
highGain: defaultHighGain,
|
||||||
highCwndGain: defaultHighGain,
|
highCwndGain: derivedHighCWNDGain,
|
||||||
drainGain: 1.0 / defaultHighGain,
|
drainGain: 1.0 / defaultHighGain,
|
||||||
pacingGain: 1.0,
|
pacingGain: 1.0,
|
||||||
congestionWindowGain: 1.0,
|
congestionWindowGain: 1.0,
|
||||||
@@ -295,20 +369,63 @@ func newBbrSender(
|
|||||||
debug: debug,
|
debug: debug,
|
||||||
}
|
}
|
||||||
b.pacer = common.NewPacer(b.bandwidthForPacer)
|
b.pacer = common.NewPacer(b.bandwidthForPacer)
|
||||||
|
b.applyProfile(profile)
|
||||||
/*
|
if b.debug {
|
||||||
if b.tracer != nil {
|
b.debugPrint("Profile: %s", b.profile)
|
||||||
b.lastState = logging.CongestionStateStartup
|
}
|
||||||
b.tracer.UpdatedCongestionState(logging.CongestionStateStartup)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
b.enterStartupMode(b.clock.Now())
|
b.enterStartupMode(b.clock.Now())
|
||||||
b.setHighCwndGain(derivedHighCWNDGain)
|
|
||||||
|
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *bbrSender) applyProfile(profile Profile) {
|
||||||
|
if profile == "" {
|
||||||
|
profile = ProfileStandard
|
||||||
|
}
|
||||||
|
cfg := configForProfile(profile)
|
||||||
|
b.profile = profile
|
||||||
|
b.highGain = cfg.highGain
|
||||||
|
b.highCwndGain = cfg.highCwndGain
|
||||||
|
b.drainGain = 1.0 / cfg.highGain
|
||||||
|
b.congestionWindowGainConstant = cfg.congestionWindowGainConstant
|
||||||
|
b.numStartupRtts = cfg.numStartupRtts
|
||||||
|
b.drainToTarget = cfg.drainToTarget
|
||||||
|
b.detectOvershooting = cfg.detectOvershooting
|
||||||
|
b.bytesLostMultiplierWhileDetectingOvershooting = cfg.bytesLostMultiplier
|
||||||
|
b.enableAckAggregationDuringStartup = cfg.enableAckAggregationStartup
|
||||||
|
b.expireAckAggregationInStartup = cfg.expireAckAggregationStartup
|
||||||
|
if cfg.enableOverestimateAvoidance {
|
||||||
|
b.sampler.EnableOverestimateAvoidance()
|
||||||
|
}
|
||||||
|
b.sampler.SetReduceExtraAckedOnBandwidthIncrease(cfg.reduceExtraAckedOnBandwidthIncrease)
|
||||||
|
}
|
||||||
|
|
||||||
|
func minCongestionWindowForMaxDatagramSize(maxDatagramSize congestion.ByteCount) congestion.ByteCount {
|
||||||
|
return minCongestionWindowPackets * maxDatagramSize
|
||||||
|
}
|
||||||
|
|
||||||
|
func scaleByteWindowForDatagramSize(window, oldMaxDatagramSize, newMaxDatagramSize congestion.ByteCount) congestion.ByteCount {
|
||||||
|
if oldMaxDatagramSize == newMaxDatagramSize {
|
||||||
|
return window
|
||||||
|
}
|
||||||
|
return congestion.ByteCount(uint64(window) * uint64(newMaxDatagramSize) / uint64(oldMaxDatagramSize))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *bbrSender) rescalePacketSizedWindows(maxDatagramSize congestion.ByteCount) {
|
||||||
|
oldMaxDatagramSize := b.maxDatagramSize
|
||||||
|
b.maxDatagramSize = maxDatagramSize
|
||||||
|
b.initialCongestionWindow = scaleByteWindowForDatagramSize(b.initialCongestionWindow, oldMaxDatagramSize, maxDatagramSize)
|
||||||
|
b.maxCongestionWindow = scaleByteWindowForDatagramSize(b.maxCongestionWindow, oldMaxDatagramSize, maxDatagramSize)
|
||||||
|
b.minCongestionWindow = minCongestionWindowForMaxDatagramSize(maxDatagramSize)
|
||||||
|
b.cwndToCalculateMinPacingRate = scaleByteWindowForDatagramSize(b.cwndToCalculateMinPacingRate, oldMaxDatagramSize, maxDatagramSize)
|
||||||
|
b.maxCongestionWindowWithNetworkParametersAdjusted = scaleByteWindowForDatagramSize(
|
||||||
|
b.maxCongestionWindowWithNetworkParametersAdjusted,
|
||||||
|
oldMaxDatagramSize,
|
||||||
|
maxDatagramSize,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func (b *bbrSender) SetRTTStatsProvider(provider congestion.RTTStatsProvider) {
|
func (b *bbrSender) SetRTTStatsProvider(provider congestion.RTTStatsProvider) {
|
||||||
b.rttStats = provider
|
b.rttStats = provider
|
||||||
}
|
}
|
||||||
@@ -370,14 +487,24 @@ func (b *bbrSender) OnRetransmissionTimeout(packetsRetransmitted bool) {
|
|||||||
|
|
||||||
// SetMaxDatagramSize implements the SendAlgorithm interface.
|
// SetMaxDatagramSize implements the SendAlgorithm interface.
|
||||||
func (b *bbrSender) SetMaxDatagramSize(s congestion.ByteCount) {
|
func (b *bbrSender) SetMaxDatagramSize(s congestion.ByteCount) {
|
||||||
|
if b.debug {
|
||||||
|
b.debugPrint("Max Datagram Size: %d", s)
|
||||||
|
}
|
||||||
if s < b.maxDatagramSize {
|
if s < b.maxDatagramSize {
|
||||||
panic(fmt.Sprintf("congestion BUG: decreased max datagram size from %d to %d", b.maxDatagramSize, s))
|
panic(fmt.Sprintf("congestion BUG: decreased max datagram size from %d to %d", b.maxDatagramSize, s))
|
||||||
}
|
}
|
||||||
cwndIsMinCwnd := b.congestionWindow == b.minCongestionWindow
|
oldMinCongestionWindow := b.minCongestionWindow
|
||||||
b.maxDatagramSize = s
|
oldInitialCongestionWindow := b.initialCongestionWindow
|
||||||
if cwndIsMinCwnd {
|
b.rescalePacketSizedWindows(s)
|
||||||
|
switch b.congestionWindow {
|
||||||
|
case oldMinCongestionWindow:
|
||||||
b.congestionWindow = b.minCongestionWindow
|
b.congestionWindow = b.minCongestionWindow
|
||||||
|
case oldInitialCongestionWindow:
|
||||||
|
b.congestionWindow = b.initialCongestionWindow
|
||||||
|
default:
|
||||||
|
b.congestionWindow = min(b.maxCongestionWindow, max(b.congestionWindow, b.minCongestionWindow))
|
||||||
}
|
}
|
||||||
|
b.recoveryWindow = min(b.maxCongestionWindow, max(b.recoveryWindow, b.minCongestionWindow))
|
||||||
b.pacer.SetMaxDatagramSize(s)
|
b.pacer.SetMaxDatagramSize(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -519,22 +646,6 @@ func (b *bbrSender) PacingRate() Bandwidth {
|
|||||||
return b.pacingRate
|
return b.pacingRate
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *bbrSender) hasGoodBandwidthEstimateForResumption() bool {
|
|
||||||
return b.hasNonAppLimitedSample()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *bbrSender) hasNonAppLimitedSample() bool {
|
|
||||||
return b.hasNoAppLimitedSample
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets the pacing gain used in STARTUP. Must be greater than 1.
|
|
||||||
func (b *bbrSender) setHighGain(highGain float64) {
|
|
||||||
b.highGain = highGain
|
|
||||||
if b.mode == bbrModeStartup {
|
|
||||||
b.pacingGain = highGain
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets the CWND gain used in STARTUP. Must be greater than 1.
|
// Sets the CWND gain used in STARTUP. Must be greater than 1.
|
||||||
func (b *bbrSender) setHighCwndGain(highCwndGain float64) {
|
func (b *bbrSender) setHighCwndGain(highCwndGain float64) {
|
||||||
b.highCwndGain = highCwndGain
|
b.highCwndGain = highCwndGain
|
||||||
@@ -543,11 +654,6 @@ func (b *bbrSender) setHighCwndGain(highCwndGain float64) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the gain used in DRAIN. Must be less than 1.
|
|
||||||
func (b *bbrSender) setDrainGain(drainGain float64) {
|
|
||||||
b.drainGain = drainGain
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the current bandwidth estimate. Note that Bandwidth is in bits per second.
|
// Get the current bandwidth estimate. Note that Bandwidth is in bits per second.
|
||||||
func (b *bbrSender) bandwidthEstimate() Bandwidth {
|
func (b *bbrSender) bandwidthEstimate() Bandwidth {
|
||||||
return b.maxBandwidth.GetBest()
|
return b.maxBandwidth.GetBest()
|
||||||
|
|||||||
130
transport/internet/hysteria/congestion/bbr/bbr_sender_test.go
Normal file
130
transport/internet/hysteria/congestion/bbr/bbr_sender_test.go
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
package bbr
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/apernet/quic-go/congestion"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSetMaxDatagramSizeRescalesPacketSizedWindows(t *testing.T) {
|
||||||
|
const oldMaxDatagramSize = congestion.ByteCount(1000)
|
||||||
|
const newMaxDatagramSize = congestion.ByteCount(1400)
|
||||||
|
const initialCongestionWindowPackets = congestion.ByteCount(20)
|
||||||
|
const maxCongestionWindowPackets = congestion.ByteCount(80)
|
||||||
|
|
||||||
|
b := newBbrSender(
|
||||||
|
DefaultClock{},
|
||||||
|
oldMaxDatagramSize,
|
||||||
|
initialCongestionWindowPackets*oldMaxDatagramSize,
|
||||||
|
maxCongestionWindowPackets*oldMaxDatagramSize,
|
||||||
|
ProfileStandard,
|
||||||
|
)
|
||||||
|
b.congestionWindow = b.initialCongestionWindow
|
||||||
|
|
||||||
|
b.SetMaxDatagramSize(newMaxDatagramSize)
|
||||||
|
|
||||||
|
require.Equal(t, initialCongestionWindowPackets*newMaxDatagramSize, b.initialCongestionWindow)
|
||||||
|
require.Equal(t, maxCongestionWindowPackets*newMaxDatagramSize, b.maxCongestionWindow)
|
||||||
|
require.Equal(t, minCongestionWindowPackets*newMaxDatagramSize, b.minCongestionWindow)
|
||||||
|
require.Equal(t, initialCongestionWindowPackets*newMaxDatagramSize, b.congestionWindow)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetMaxDatagramSizeClampsCongestionWindow(t *testing.T) {
|
||||||
|
const oldMaxDatagramSize = congestion.ByteCount(1000)
|
||||||
|
const newMaxDatagramSize = congestion.ByteCount(1400)
|
||||||
|
|
||||||
|
b := NewBbrSender(DefaultClock{}, oldMaxDatagramSize, ProfileStandard)
|
||||||
|
b.congestionWindow = b.minCongestionWindow + oldMaxDatagramSize
|
||||||
|
b.recoveryWindow = b.minCongestionWindow + oldMaxDatagramSize
|
||||||
|
|
||||||
|
b.SetMaxDatagramSize(newMaxDatagramSize)
|
||||||
|
|
||||||
|
require.Equal(t, b.minCongestionWindow, b.congestionWindow)
|
||||||
|
require.Equal(t, b.minCongestionWindow, b.recoveryWindow)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewBbrSenderAppliesProfiles(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
profile Profile
|
||||||
|
highGain float64
|
||||||
|
highCwndGain float64
|
||||||
|
congestionWindowGainConstant float64
|
||||||
|
numStartupRtts int64
|
||||||
|
drainToTarget bool
|
||||||
|
detectOvershooting bool
|
||||||
|
bytesLostMultiplier uint8
|
||||||
|
enableAckAggregationDuringStartup bool
|
||||||
|
expireAckAggregationInStartup bool
|
||||||
|
enableOverestimateAvoidance bool
|
||||||
|
reduceExtraAckedOnBandwidthIncrease bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "standard",
|
||||||
|
profile: ProfileStandard,
|
||||||
|
highGain: defaultHighGain,
|
||||||
|
highCwndGain: derivedHighCWNDGain,
|
||||||
|
congestionWindowGainConstant: 2.0,
|
||||||
|
numStartupRtts: roundTripsWithoutGrowthBeforeExitingStartup,
|
||||||
|
bytesLostMultiplier: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "conservative",
|
||||||
|
profile: ProfileConservative,
|
||||||
|
highGain: 2.25,
|
||||||
|
highCwndGain: 1.75,
|
||||||
|
congestionWindowGainConstant: 1.75,
|
||||||
|
numStartupRtts: 2,
|
||||||
|
drainToTarget: true,
|
||||||
|
detectOvershooting: true,
|
||||||
|
bytesLostMultiplier: 1,
|
||||||
|
enableOverestimateAvoidance: true,
|
||||||
|
reduceExtraAckedOnBandwidthIncrease: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "aggressive",
|
||||||
|
profile: ProfileAggressive,
|
||||||
|
highGain: 3.0,
|
||||||
|
highCwndGain: 2.25,
|
||||||
|
congestionWindowGainConstant: 2.5,
|
||||||
|
numStartupRtts: 4,
|
||||||
|
bytesLostMultiplier: 2,
|
||||||
|
enableAckAggregationDuringStartup: true,
|
||||||
|
expireAckAggregationInStartup: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
b := NewBbrSender(DefaultClock{}, congestion.InitialPacketSize, tc.profile)
|
||||||
|
require.Equal(t, tc.profile, b.profile)
|
||||||
|
require.Equal(t, tc.highGain, b.highGain)
|
||||||
|
require.Equal(t, tc.highCwndGain, b.highCwndGain)
|
||||||
|
require.Equal(t, tc.congestionWindowGainConstant, b.congestionWindowGainConstant)
|
||||||
|
require.Equal(t, tc.numStartupRtts, b.numStartupRtts)
|
||||||
|
require.Equal(t, tc.drainToTarget, b.drainToTarget)
|
||||||
|
require.Equal(t, tc.detectOvershooting, b.detectOvershooting)
|
||||||
|
require.Equal(t, tc.bytesLostMultiplier, b.bytesLostMultiplierWhileDetectingOvershooting)
|
||||||
|
require.Equal(t, tc.enableAckAggregationDuringStartup, b.enableAckAggregationDuringStartup)
|
||||||
|
require.Equal(t, tc.expireAckAggregationInStartup, b.expireAckAggregationInStartup)
|
||||||
|
require.Equal(t, tc.enableOverestimateAvoidance, b.sampler.IsOverestimateAvoidanceEnabled())
|
||||||
|
require.Equal(t, tc.reduceExtraAckedOnBandwidthIncrease, b.sampler.maxAckHeightTracker.reduceExtraAckedOnBandwidthIncrease)
|
||||||
|
require.Equal(t, b.highGain, b.pacingGain)
|
||||||
|
require.Equal(t, b.highCwndGain, b.congestionWindowGain)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseProfile(t *testing.T) {
|
||||||
|
profile, err := ParseProfile("")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, ProfileStandard, profile)
|
||||||
|
|
||||||
|
profile, err = ParseProfile("Aggressive")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, ProfileAggressive, profile)
|
||||||
|
|
||||||
|
_, err = ParseProfile("turbo")
|
||||||
|
require.EqualError(t, err, `unsupported BBR profile "turbo"`)
|
||||||
|
}
|
||||||
@@ -1,18 +1,55 @@
|
|||||||
package congestion
|
package congestion
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/apernet/quic-go"
|
"github.com/apernet/quic-go"
|
||||||
"github.com/xtls/xray-core/transport/internet/hysteria/congestion/bbr"
|
"github.com/xtls/xray-core/transport/internet/hysteria/congestion/bbr"
|
||||||
"github.com/xtls/xray-core/transport/internet/hysteria/congestion/brutal"
|
"github.com/xtls/xray-core/transport/internet/hysteria/congestion/brutal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func UseBBR(conn *quic.Conn) {
|
const (
|
||||||
|
TypeBBR = "bbr"
|
||||||
|
TypeReno = "reno"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NormalizeType(congestionType string) (string, error) {
|
||||||
|
switch normalized := strings.ToLower(congestionType); normalized {
|
||||||
|
case "", TypeBBR:
|
||||||
|
return TypeBBR, nil
|
||||||
|
case TypeReno:
|
||||||
|
return TypeReno, nil
|
||||||
|
default:
|
||||||
|
return "", fmt.Errorf("unsupported congestion type %q", congestionType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NormalizeBBRProfile(profile string) (string, error) {
|
||||||
|
normalized, err := bbr.ParseProfile(profile)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return string(normalized), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func UseBBR(conn *quic.Conn, profile bbr.Profile) {
|
||||||
conn.SetCongestionControl(bbr.NewBbrSender(
|
conn.SetCongestionControl(bbr.NewBbrSender(
|
||||||
bbr.DefaultClock{},
|
bbr.DefaultClock{},
|
||||||
bbr.GetInitialPacketSize(conn.RemoteAddr()),
|
bbr.GetInitialPacketSize(conn.RemoteAddr()),
|
||||||
|
profile,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
func UseBrutal(conn *quic.Conn, tx uint64) {
|
func UseBrutal(conn *quic.Conn, tx uint64) {
|
||||||
conn.SetCongestionControl(brutal.NewBrutalSender(tx))
|
conn.SetCongestionControl(brutal.NewBrutalSender(tx))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func UseConfigured(conn *quic.Conn, congestionType, bbrProfile string) {
|
||||||
|
switch congestionType {
|
||||||
|
case TypeReno:
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
UseBBR(conn, bbr.Profile(bbrProfile))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
"github.com/xtls/xray-core/transport/internet/finalmask"
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
"github.com/xtls/xray-core/transport/internet/hysteria/congestion"
|
"github.com/xtls/xray-core/transport/internet/hysteria/congestion"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/hysteria/congestion/bbr"
|
||||||
"github.com/xtls/xray-core/transport/internet/hysteria/udphop"
|
"github.com/xtls/xray-core/transport/internet/hysteria/udphop"
|
||||||
"github.com/xtls/xray-core/transport/internet/stat"
|
"github.com/xtls/xray-core/transport/internet/stat"
|
||||||
"github.com/xtls/xray-core/transport/internet/tls"
|
"github.com/xtls/xray-core/transport/internet/tls"
|
||||||
@@ -157,10 +158,10 @@ func (c *client) dial() error {
|
|||||||
|
|
||||||
quicParams := c.quicParams
|
quicParams := c.quicParams
|
||||||
if quicParams == nil {
|
if quicParams == nil {
|
||||||
quicParams = &internet.QuicParams{}
|
quicParams = &internet.QuicParams{
|
||||||
}
|
BbrProfile: string(bbr.ProfileStandard),
|
||||||
if quicParams.UdpHop == nil {
|
UdpHop: &internet.UdpHop{},
|
||||||
quicParams.UdpHop = &internet.UdpHop{}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var index int
|
var index int
|
||||||
@@ -298,12 +299,12 @@ func (c *client) dial() error {
|
|||||||
case "reno":
|
case "reno":
|
||||||
errors.LogDebug(c.ctx, "congestion reno")
|
errors.LogDebug(c.ctx, "congestion reno")
|
||||||
case "bbr":
|
case "bbr":
|
||||||
errors.LogDebug(c.ctx, "congestion bbr")
|
errors.LogDebug(c.ctx, "congestion bbr ", quicParams.BbrProfile)
|
||||||
congestion.UseBBR(quicConn)
|
congestion.UseBBR(quicConn, bbr.Profile(quicParams.BbrProfile))
|
||||||
case "brutal", "":
|
case "brutal", "":
|
||||||
if serverAuto == "auto" || quicParams.BrutalUp == 0 || serverDown == 0 {
|
if serverAuto == "auto" || quicParams.BrutalUp == 0 || serverDown == 0 {
|
||||||
errors.LogDebug(c.ctx, "congestion bbr")
|
errors.LogDebug(c.ctx, "congestion bbr ", quicParams.BbrProfile)
|
||||||
congestion.UseBBR(quicConn)
|
congestion.UseBBR(quicConn, bbr.Profile(quicParams.BbrProfile))
|
||||||
} else {
|
} else {
|
||||||
errors.LogDebug(c.ctx, "congestion brutal bytes per second ", min(quicParams.BrutalUp, serverDown))
|
errors.LogDebug(c.ctx, "congestion brutal bytes per second ", min(quicParams.BrutalUp, serverDown))
|
||||||
congestion.UseBrutal(quicConn, min(quicParams.BrutalUp, serverDown))
|
congestion.UseBrutal(quicConn, min(quicParams.BrutalUp, serverDown))
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import (
|
|||||||
hyCtx "github.com/xtls/xray-core/proxy/hysteria/ctx"
|
hyCtx "github.com/xtls/xray-core/proxy/hysteria/ctx"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
"github.com/xtls/xray-core/transport/internet/hysteria/congestion"
|
"github.com/xtls/xray-core/transport/internet/hysteria/congestion"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/hysteria/congestion/bbr"
|
||||||
"github.com/xtls/xray-core/transport/internet/tls"
|
"github.com/xtls/xray-core/transport/internet/tls"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -188,12 +189,12 @@ func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
case "reno":
|
case "reno":
|
||||||
errors.LogDebug(context.Background(), h.conn.RemoteAddr(), " ", "congestion reno")
|
errors.LogDebug(context.Background(), h.conn.RemoteAddr(), " ", "congestion reno")
|
||||||
case "bbr":
|
case "bbr":
|
||||||
errors.LogDebug(context.Background(), h.conn.RemoteAddr(), " ", "congestion bbr")
|
errors.LogDebug(context.Background(), h.conn.RemoteAddr(), " ", "congestion bbr ", h.quicParams.BbrProfile)
|
||||||
congestion.UseBBR(h.conn)
|
congestion.UseBBR(h.conn, bbr.Profile(h.quicParams.BbrProfile))
|
||||||
case "brutal", "":
|
case "brutal", "":
|
||||||
if h.quicParams.BrutalUp == 0 || clientDown == 0 {
|
if h.quicParams.BrutalUp == 0 || clientDown == 0 {
|
||||||
errors.LogDebug(context.Background(), h.conn.RemoteAddr(), " ", "congestion bbr")
|
errors.LogDebug(context.Background(), h.conn.RemoteAddr(), " ", "congestion bbr ", h.quicParams.BbrProfile)
|
||||||
congestion.UseBBR(h.conn)
|
congestion.UseBBR(h.conn, bbr.Profile(h.quicParams.BbrProfile))
|
||||||
} else {
|
} else {
|
||||||
errors.LogDebug(context.Background(), h.conn.RemoteAddr(), " ", "congestion brutal bytes per second ", min(h.quicParams.BrutalUp, clientDown))
|
errors.LogDebug(context.Background(), h.conn.RemoteAddr(), " ", "congestion brutal bytes per second ", min(h.quicParams.BrutalUp, clientDown))
|
||||||
congestion.UseBrutal(h.conn, min(h.quicParams.BrutalUp, clientDown))
|
congestion.UseBrutal(h.conn, min(h.quicParams.BrutalUp, clientDown))
|
||||||
@@ -389,7 +390,10 @@ func Listen(ctx context.Context, address net.Address, port net.Port, streamSetti
|
|||||||
|
|
||||||
quicParams := streamSettings.QuicParams
|
quicParams := streamSettings.QuicParams
|
||||||
if quicParams == nil {
|
if quicParams == nil {
|
||||||
quicParams = &internet.QuicParams{}
|
quicParams = &internet.QuicParams{
|
||||||
|
BbrProfile: string(bbr.ProfileStandard),
|
||||||
|
UdpHop: &internet.UdpHop{},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
quicConfig := &quic.Config{
|
quicConfig := &quic.Config{
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
"github.com/xtls/xray-core/transport/internet/browser_dialer"
|
"github.com/xtls/xray-core/transport/internet/browser_dialer"
|
||||||
"github.com/xtls/xray-core/transport/internet/hysteria/congestion"
|
"github.com/xtls/xray-core/transport/internet/hysteria/congestion"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/hysteria/congestion/bbr"
|
||||||
"github.com/xtls/xray-core/transport/internet/hysteria/udphop"
|
"github.com/xtls/xray-core/transport/internet/hysteria/udphop"
|
||||||
"github.com/xtls/xray-core/transport/internet/reality"
|
"github.com/xtls/xray-core/transport/internet/reality"
|
||||||
"github.com/xtls/xray-core/transport/internet/stat"
|
"github.com/xtls/xray-core/transport/internet/stat"
|
||||||
@@ -158,10 +159,10 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea
|
|||||||
if httpVersion == "3" {
|
if httpVersion == "3" {
|
||||||
quicParams := streamSettings.QuicParams
|
quicParams := streamSettings.QuicParams
|
||||||
if quicParams == nil {
|
if quicParams == nil {
|
||||||
quicParams = &internet.QuicParams{}
|
quicParams = &internet.QuicParams{
|
||||||
}
|
BbrProfile: string(bbr.ProfileStandard),
|
||||||
if quicParams.UdpHop == nil {
|
UdpHop: &internet.UdpHop{},
|
||||||
quicParams.UdpHop = &internet.UdpHop{}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
quicConfig := &quic.Config{
|
quicConfig := &quic.Config{
|
||||||
@@ -292,8 +293,8 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea
|
|||||||
case "reno":
|
case "reno":
|
||||||
errors.LogDebug(context.Background(), quicConn.RemoteAddr(), " ", "congestion reno")
|
errors.LogDebug(context.Background(), quicConn.RemoteAddr(), " ", "congestion reno")
|
||||||
default:
|
default:
|
||||||
errors.LogDebug(context.Background(), quicConn.RemoteAddr(), " ", "congestion bbr")
|
errors.LogDebug(context.Background(), quicConn.RemoteAddr(), " ", "congestion bbr ", quicParams.BbrProfile)
|
||||||
congestion.UseBBR(quicConn)
|
congestion.UseBBR(quicConn, bbr.Profile(quicParams.BbrProfile))
|
||||||
}
|
}
|
||||||
|
|
||||||
return quicConn, nil
|
return quicConn, nil
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/signal/done"
|
"github.com/xtls/xray-core/common/signal/done"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
"github.com/xtls/xray-core/transport/internet/hysteria/congestion"
|
"github.com/xtls/xray-core/transport/internet/hysteria/congestion"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/hysteria/congestion/bbr"
|
||||||
"github.com/xtls/xray-core/transport/internet/reality"
|
"github.com/xtls/xray-core/transport/internet/reality"
|
||||||
"github.com/xtls/xray-core/transport/internet/stat"
|
"github.com/xtls/xray-core/transport/internet/stat"
|
||||||
"github.com/xtls/xray-core/transport/internet/tls"
|
"github.com/xtls/xray-core/transport/internet/tls"
|
||||||
@@ -496,7 +497,10 @@ func ListenXH(ctx context.Context, address net.Address, port net.Port, streamSet
|
|||||||
|
|
||||||
quicParams := streamSettings.QuicParams
|
quicParams := streamSettings.QuicParams
|
||||||
if quicParams == nil {
|
if quicParams == nil {
|
||||||
quicParams = &internet.QuicParams{}
|
quicParams = &internet.QuicParams{
|
||||||
|
BbrProfile: string(bbr.ProfileStandard),
|
||||||
|
UdpHop: &internet.UdpHop{},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
quicConfig := &quic.Config{
|
quicConfig := &quic.Config{
|
||||||
@@ -535,8 +539,8 @@ func ListenXH(ctx context.Context, address net.Address, port net.Port, streamSet
|
|||||||
case "reno":
|
case "reno":
|
||||||
errors.LogDebug(context.Background(), conn.RemoteAddr(), " ", "congestion reno")
|
errors.LogDebug(context.Background(), conn.RemoteAddr(), " ", "congestion reno")
|
||||||
default:
|
default:
|
||||||
errors.LogDebug(context.Background(), conn.RemoteAddr(), " ", "congestion bbr")
|
errors.LogDebug(context.Background(), conn.RemoteAddr(), " ", "congestion bbr ", quicParams.BbrProfile)
|
||||||
congestion.UseBBR(conn)
|
congestion.UseBBR(conn, bbr.Profile(quicParams.BbrProfile))
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
|||||||
Reference in New Issue
Block a user