mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2025-04-28 22:25:07 +03:00
Add DSCP classification to TCP
This commit is contained in:
parent
401960e17e
commit
3f729c2fb4
3 changed files with 38 additions and 3 deletions
|
@ -7,6 +7,7 @@ type NodeConfig struct {
|
|||
Peers []string `comment:"List of connection strings for static peers in URI format, i.e.\ntcp://a.b.c.d:e or socks://a.b.c.d:e/f.g.h.i:j."`
|
||||
InterfacePeers map[string][]string `comment:"List of connection strings for static peers in URI format, arranged\nby source interface, i.e. { \"eth0\": [ tcp://a.b.c.d:e ] }. Note that\nSOCKS peerings will NOT be affected by this option and should go in\nthe \"Peers\" section instead."`
|
||||
ReadTimeout int32 `comment:"Read timeout for connections, specified in milliseconds. If less\nthan 6000 and not negative, 6000 (the default) is used. If negative,\nreads won't time out."`
|
||||
DSCPClassification uint8 `comment:"DSCP classification, in decimal, for applying Quality of Service\n(QoS) markings to outbound peering traffic. This value will more\nthan likely be ignored if peering over the Internet."`
|
||||
AllowedEncryptionPublicKeys []string `comment:"List of peer encryption public keys to allow or incoming TCP\nconnections from. If left empty/undefined then all connections\nwill be allowed by default."`
|
||||
EncryptionPublicKey string `comment:"Your public encryption key. Your peers may ask you for this to put\ninto their AllowedEncryptionPublicKeys configuration."`
|
||||
EncryptionPrivateKey string `comment:"Your private encryption key. DO NOT share this with anyone!"`
|
||||
|
|
|
@ -97,7 +97,7 @@ func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) error {
|
|||
c.init(&boxPub, &boxPriv, &sigPub, &sigPriv)
|
||||
c.admin.init(c, nc.AdminListen)
|
||||
|
||||
if err := c.tcp.init(c, nc.Listen, nc.ReadTimeout); err != nil {
|
||||
if err := c.tcp.init(c, nc.Listen, nc.ReadTimeout, nc.DSCPClassification); err != nil {
|
||||
c.log.Println("Failed to start TCP interface")
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ import (
|
|||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/ipv4"
|
||||
"golang.org/x/net/ipv6"
|
||||
"golang.org/x/net/proxy"
|
||||
)
|
||||
|
||||
|
@ -47,6 +49,7 @@ type tcpInterface struct {
|
|||
mutex sync.Mutex // Protecting the below
|
||||
calls map[string]struct{}
|
||||
conns map[tcpInfo](chan struct{})
|
||||
dscp uint8
|
||||
}
|
||||
|
||||
// This is used as the key to a map that tracks existing connections, to prevent multiple connections to the same keys and local/remote address pair from occuring.
|
||||
|
@ -74,9 +77,14 @@ func (iface *tcpInterface) connectSOCKS(socksaddr, peeraddr string) {
|
|||
}
|
||||
|
||||
// Initializes the struct.
|
||||
func (iface *tcpInterface) init(core *Core, addr string, readTimeout int32) (err error) {
|
||||
func (iface *tcpInterface) init(core *Core, addr string, readTimeout int32, dscp uint8) (err error) {
|
||||
iface.core = core
|
||||
|
||||
// The DSCP value is 6-bit
|
||||
if dscp >= 0 && dscp <= 63 {
|
||||
iface.dscp = dscp
|
||||
}
|
||||
|
||||
iface.tcp_timeout = time.Duration(readTimeout) * time.Millisecond
|
||||
if iface.tcp_timeout >= 0 && iface.tcp_timeout < default_tcp_timeout {
|
||||
iface.tcp_timeout = default_tcp_timeout
|
||||
|
@ -164,7 +172,7 @@ func (iface *tcpInterface) call(saddr string, socksaddr *string, sintf string) {
|
|||
if err != nil {
|
||||
return
|
||||
} else {
|
||||
if ief.Flags & net.FlagUp == 0 {
|
||||
if ief.Flags&net.FlagUp == 0 {
|
||||
return
|
||||
}
|
||||
addrs, err := ief.Addrs()
|
||||
|
@ -197,6 +205,19 @@ func (iface *tcpInterface) call(saddr string, socksaddr *string, sintf string) {
|
|||
return
|
||||
}
|
||||
}
|
||||
// Configure DSCP on the connection, if set
|
||||
if iface.dscp != 0 {
|
||||
addr := conn.RemoteAddr().(*net.TCPAddr)
|
||||
if addr.IP.To16() != nil && addr.IP.To4() == nil {
|
||||
if err := ipv6.NewConn(conn).SetTrafficClass(int(iface.dscp << 2)); err != nil {
|
||||
iface.core.log.Println("Failed to set traffic class:", err)
|
||||
}
|
||||
} else {
|
||||
if err := ipv4.NewConn(conn).SetTOS(int(iface.dscp << 2)); err != nil {
|
||||
iface.core.log.Println("Failed to set TOS:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
iface.handler(conn, false)
|
||||
}()
|
||||
}
|
||||
|
@ -223,6 +244,19 @@ func (iface *tcpInterface) handler(sock net.Conn, incoming bool) {
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
// Configure DSCP on the connection, if set
|
||||
if iface.dscp != 0 {
|
||||
addr := sock.RemoteAddr().(*net.TCPAddr)
|
||||
if addr.IP.To16() != nil && addr.IP.To4() == nil {
|
||||
if err := ipv6.NewConn(sock).SetTrafficClass(int(iface.dscp << 2)); err != nil {
|
||||
iface.core.log.Println("Failed to set traffic class:", err)
|
||||
}
|
||||
} else {
|
||||
if err := ipv4.NewConn(sock).SetTOS(int(iface.dscp << 2)); err != nil {
|
||||
iface.core.log.Println("Failed to set TOS:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
meta = version_metadata{} // Reset to zero value
|
||||
if !meta.decode(metaBytes) || !meta.check() {
|
||||
// Failed to decode and check the metadata
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue